public Game(IModHelper helper, ModConfig modConfig) { this.ModHelper = helper; this.modConfig = modConfig; Spawns.LoadSpawnLocations(helper); Chests.LoadChestsSpawns(helper); Storm.LoadStormData(helper); //Ban people from hiding in the elevator building. ModEntry.Events.Display.MenuChanged += (o, e) => { if (IsGameInProgress && e.NewMenu != null && e.NewMenu.GetType().Name == "ElevatorMenu") { e.NewMenu.exitThisMenu(false); } }; ModEntry.Events.GameLoop.UpdateTicked += (o, e) => { if (IsGameInProgress && Game1.IsServer && e.IsMultipleOf(8)) { Storm.QuarterSecUpdate(alivePlayers); } }; }
public void ProcessPlayerJoin(NetFarmerRoot farmerRoot) { Console.WriteLine($"(Game) Player joining..."); Storm.SendPhasesData(farmerRoot.Value.UniqueMultiplayerID); //If you run immediately it does nothing Task.Factory.StartNew(() => { System.Threading.Thread.Sleep(1000); //TODO: reduce/increase maybe? NetworkUtility.WarpFarmer(farmerRoot.Value, new TileLocation("Forest", 100, 20)); }); if (IsGameInProgress && alivePlayers.Count <= 1) { //Restart the game, or nothing will ever happen HandleWin(null, null); } }
public void ServerStartGame() { if (IsGameInProgress) { Console.WriteLine("A game is already in progress!"); return; } IsGameInProgress = true; Console.WriteLine("Server start game"); NetworkUtility.SendChatMessageToAllPlayers("Game starting!"); //Wipe objects foreach (GameLocation location in Game1.locations) { location.Objects.Clear(); location.debris.Clear(); } Game1.MasterPlayer.Money = 0; //Spawn chests new Chests().SpawnAndFillChests(); #region Store tree locations or replant Random random = new Random(); if (trees.Count == 0) //Store info { foreach (GameLocation gameLocation in Game1.locations) { foreach (var pair in gameLocation.terrainFeatures.Pairs) { TerrainFeature feature = pair.Value; if (feature is Tree tree && tree.growthStage.Value >= 5) { Vector2 vector = pair.Key; trees.Add(new TileLocation(gameLocation.Name, (int)vector.X, (int)vector.Y)); } } } } else //Replant { //Delete all trees foreach (GameLocation gameLocation in Game1.locations) { List <Vector2> toRemove = new List <Vector2>(); foreach (Vector2 vector in gameLocation.terrainFeatures.Keys) { TerrainFeature feature = gameLocation.terrainFeatures[vector]; if (feature is Tree tree && tree.growthStage.Value >= 5) { toRemove.Add(vector); } } foreach (Vector2 vector in toRemove) { gameLocation.terrainFeatures.Remove(vector); } } //Replant foreach (TileLocation treeLocation in trees) { treeLocation.GetGameLocation().terrainFeatures.Remove(treeLocation.CreateVector2()); treeLocation.GetGameLocation().terrainFeatures.Add(treeLocation.CreateVector2(), new Tree(random.Next(1, 4), 100)); } } #endregion //Remove resource clumps (e.g. boulders) other than stumps and hollow logs var rc = Game1.getFarm().resourceClumps; foreach (var a in rc.Where(a => a.parentSheetIndex.Value != 600 || a.parentSheetIndex.Value != 602).ToList()) { rc.Remove(a); } //Remove small stones and weeds var farmObjects = Game1.getFarm().objects; var keys = farmObjects.Keys.ToList(); for (int i = 0; i < keys.Count(); i++) { var key0 = keys[i]; if (farmObjects[key0].name == "Stone" || farmObjects[key0].name == "Weeds") { farmObjects.Remove(key0); } } //Setup alive players alivePlayers.Clear(); foreach (Farmer player in Game1.getOnlineFarmers()) { if (player != null && !(player == Game1.player && !modConfig.ShouldHostParticipate)) { Console.WriteLine($"Adding {player.Name} to the game"); alivePlayers.Add(player.UniqueMultiplayerID); } } //Storm index int stormIndex = Storm.GetRandomStormIndex(); //Spawn players in & Tell the clients to start game var chosenSpawns = new Spawns().ScatterPlayers(Game1.getOnlineFarmers()); foreach (Farmer player in chosenSpawns.Keys) { if (player == Game1.player) { ClientStartGame(alivePlayers.Count, modConfig.ShouldHostParticipate, stormIndex); if (modConfig.ShouldHostParticipate) { NetworkUtility.WarpFarmer(player, chosenSpawns[player]); } else { player.warpFarmer(new TileLocation("Forest", 100, 20).CreateWarp()); } } else { NetworkUtility.BroadcastGameStartToClient(player, alivePlayers.Count, modConfig.ShouldHostParticipate, stormIndex); NetworkUtility.WarpFarmer(player, chosenSpawns[player]); } } //Remove horses/NPCs foreach (GameLocation loc in Game1.locations) { foreach (NPC horse in loc.characters.Where(x => ModEntry.Config.KillAllNPCs || x is StardewValley.Characters.Horse).ToList()) { loc.characters.Remove(horse); } } //Freeze time Game1.timeOfDay = 1400; FreezeTime.TimeFrozen = true; }
public void ClientStartGame(int numberOfPlayers, bool isHostParticipating, int stormIndex) //string locationName, int tileX, int tileY) { Console.WriteLine($"Client start game"); IsGameInProgress = true; //Prevent draw issues if they were holding a slingshot before round ended/started foreach (Farmer p in Game1.getAllFarmers()) { p.forceCanMove(); } //Setup alive players (server has already done this in ServerStartGame) if (!Game1.IsServer) { alivePlayers.Clear(); foreach (Farmer player in Game1.getOnlineFarmers()) { if (player != null && !(player == Game1.MasterPlayer && !isHostParticipating)) { Console.WriteLine($"Adding {player.Name} to the game"); alivePlayers.Add(player.UniqueMultiplayerID); } } } //Time TimeWhenGameStarted = DateTime.Now; //Freeze time Game1.timeOfDay = 1200; FreezeTime.TimeFrozen = true; //Wipe quests Game1.player.questLog.Clear(); //Storm Storm.StartStorm(stormIndex); //Open locations var strings = new string[] { "OpenedSewer", "wizardJunimoNote", "ccDoorUnlock", "guildMember", "krobusUnseal" }; foreach (var s in strings) { if (!Game1.player.mailReceived.Contains(s)) { Game1.player.mailReceived.Add(s); } } Game1.player.hasDarkTalisman = true; //Removes the chest in bugland //Set NPC relations to 2 hearts so you can enter every room var namesToIgnore = new string[] { "Krobus", "Dwarf", "Sandy", "Kent" }; //Because spoilers foreach (GameLocation gameLocation in Game1.locations) { foreach (NPC npc in gameLocation.characters.Where(x => !namesToIgnore.Contains(x.Name))) { Game1.player.hasPlayerTalkedToNPC(npc.Name); //Creates friendship entries if they have never met before if (Game1.player.friendshipData.ContainsKey(npc.Name)) { Game1.player.friendshipData[npc.Name].Points = 500; //Each heart is 250 points } } } //Clear buffs Game1.player.removeBuffAttributes(); Game1.player.maxHealth = maxHealth; Game1.player.health = maxHealth; Game1.player.Stamina = Game1.player.MaxStamina; Game1.player.swimming.Value = false; Game1.player.changeOutOfSwimSuit(); //Items Game1.player.MaxItems = 36; Game1.player.leftRing.Set(null); Game1.player.rightRing.Set(null); Game1.player.boots.Set(null); Game1.getFarm().lastItemShipped = null; for (int i = 0; i < Game1.player.items.Count; i++) { if (!(Game1.player.items[i] is StardewValley.Objects.Hat)) { Game1.player.items[i] = null; } } Game1.player.addItemToInventory(new StardewValley.Tools.Axe() { UpgradeLevel = 3 }); //3 = Gold level //Game1.player.addItemToInventory(new StardewValley.Tools.Pickaxe() { UpgradeLevel = 3 }); Pickaxe lets them have too much slingshot ammo //Setup crafting recipes Game1.player.craftingRecipes.Clear(); Game1.player.craftingRecipes.Add("Gate", 0); Game1.player.craftingRecipes.Add("Wood Fence", 0); Game1.player.craftingRecipes.Add("Hardwood Fence", 0); //Game1.player.craftingRecipes.Add("Stone Fence", 0); (Need pickaxe to break) Game1.player.craftingRecipes.Add("Chest", 0); //Clear mail Game1.mailbox?.Clear(); //Dismount var horse = Game1.player.mount; if (horse != null) { horse.dismount(); Game1.currentLocation.characters.Remove(horse); Game1.player.mount = null; } //Setup UI if (!(Game1.activeClickableMenu is CharacterCustomization)) { Game1.activeClickableMenu?.exitThisMenu(false); } IClickableMenu toRemove = null; foreach (IClickableMenu menu in Game1.onScreenMenus) { if (menu is DayTimeMoneyBox) { toRemove = menu; break; } } Game1.onScreenMenus.Remove(toRemove); OverlayUI = new OverlayUI(numberOfPlayers); Game1.onScreenMenus.Add(OverlayUI); }
public override void Entry(IModHelper helper) { Events = helper.Events; if (AntiCheat.HasIllegalMods()) { Game1.quit = true; Console.Clear(); Monitor.Log("You have an illegal mod installed. Please uninstall it before using this mod.", LogLevel.Warn); if (AntiCheat.IllegalMod != null) { Monitor.Log($"- '{AntiCheat.IllegalMod}'", LogLevel.Warn); } Monitor.Log("Press any key to continue...", LogLevel.Warn); Console.ReadKey(); return; } var config = helper.ReadConfig <ModConfig>(); if (config == null) { config = new ModConfig(); helper.WriteConfig(config); } Config = config; BRGame = new Game(helper, config); Patch.PatchAll("ilyaki.battleroyale"); try { //Remove player limit var multiplayer = helper.Reflection.GetField <Multiplayer>(typeof(Game1), "multiplayer").GetValue(); multiplayer.playerLimit = config.PlayerLimit;//250 is the Galaxy limit (it's multiplied by two for some reason, so set 125) }catch (Exception) { Monitor.Log("Error setting player limit. The max is 125", LogLevel.Error); } helper.ConsoleCommands.Add("br_start", "Start the game. Alternative to pressing Right control", (c, a) => { if (Game1.IsServer) { BRGame.ServerStartGame(); } }); Events.Input.ButtonPressed += (o, e) => { if (Game1.IsServer && e.Button.TryGetKeyboard(out Keys key) && key == Keys.RightControl) { BRGame.ServerStartGame(); } if (e.Button.TryGetKeyboard(out Keys key2) && key2 == Keys.RightAlt) { var loc = Game1.player.currentLocation; int x = Game1.player.getTileX(); int y = Game1.player.getTileY(); Monitor.Log($"tile location={loc.Name}, pos=({x},{y})", LogLevel.Info); Monitor.Log($"my id : {Game1.player.UniqueMultiplayerID}", LogLevel.Info); Monitor.Log($"precise position = {Game1.player.Position}", LogLevel.Info); /*Game1.player.addItemToInventory(new StardewValley.Tools.Slingshot()); * Game1.player.addItemToInventory(new StardewValley.Tools.Slingshot(33)); * * var xd = new int[] { 388, 390, 378, 380, 384, 382, 386, 441 }; * foreach(int asdf in xd) * { * Game1.player.addItemToInventory(new StardewValley.Object(asdf, 100)); * }*/ } }; Events.GameLoop.UpdateTicked += (o, e) => BRGame?.Update(Game1.currentGameTime); Events.GameLoop.UpdateTicked += (o, e) => HitShaker.Update(Game1.currentGameTime); Events.GameLoop.UpdateTicked += (o, e) => SpectatorMode.Update(); //https://github.com/funny-snek/Always-On-Server-for-Multiplayer/blob/master/Always%20On%20Server/ModEntry.cs string currentSavedInviteCode = ""; Events.GameLoop.UpdateTicked += (o, e) => { if (e.IsMultipleOf(60 * 5) && Game1.server != null && Game1.options.enableServer == true && !string.Equals(currentSavedInviteCode, Game1.server.getInviteCode())) { currentSavedInviteCode = Game1.server.getInviteCode(); try { //helper.DirectoryPath StreamWriter sw = new StreamWriter("InviteCode.txt"); //Should be in the same folder as StardewModdingAPI.exe sw.WriteLine(currentSavedInviteCode); sw.Close(); } catch (Exception b) { Console.WriteLine("Exception writing InviteCode: " + b.Message); } } }; Events.Player.Warped += (o, e) => { if (e.NewLocation != null && (e.NewLocation is StardewValley.Locations.Woods || e.NewLocation.Name == "BugLand")) { e.NewLocation.characters.Clear(); } }; Events.Display.RenderingHud += (o, e) => { if (!SpectatorMode.InSpectatorMode) { Storm.Draw(Game1.spriteBatch); } }; Events.Display.Rendered += (o, e) => { if (SpectatorMode.InSpectatorMode) //Spectator mode can only see the storm when it is drawn above everything { Storm.Draw(Game1.spriteBatch); if (Game1.activeClickableMenu == null) { string message = "Spectating"; SpriteText.drawStringWithScrollBackground(Game1.spriteBatch, message, Game1.viewport.Width / 2 - SpriteText.getWidthOfString(message) / 2, 16, "", 1f, -1); } } }; helper.ConsoleCommands.Add("br_kick", "Kick a player. Usage: br_kick <player ID>", (a, b) => { if (!Game1.IsServer) { Monitor.Log("Need to be the server host", LogLevel.Info); } else if (b.Length != 1) { Monitor.Log("Need 1 argument", LogLevel.Info); } else if (!long.TryParse(b[0], out long x)) { Monitor.Log("Not a valid number", LogLevel.Info); } else { try { var f = Game1.getOnlineFarmers().First(p => p != Game1.player && p.UniqueMultiplayerID == x); NetworkUtility.KickPlayer(f, "You have been kicked by the host."); } catch (Exception) { Monitor.Log($"Could not find player with id {x}", LogLevel.Info); } } }); helper.ConsoleCommands.Add("br_setNumberOfPlayerSlots", "Sets the number of player slots. Usage: br_setNumberOfPlayerSlots <number of slots>", (a, b) => { if (!Game1.IsServer) { Monitor.Log("Need to be the server host", LogLevel.Info); } else if (b.Length != 1) { Monitor.Log("Need 1 argument", LogLevel.Info); } else if (!int.TryParse(b[0], out int n)) { Monitor.Log("Not a valid number", LogLevel.Info); } else { n = Math.Abs(n); var emptyCabins = Game1.getFarm().buildings.Where(z => z.daysOfConstructionLeft.Value <= 0 && z.indoors.Value is Cabin).ToArray(); if (n > emptyCabins.Length) { for (int i = 0; i < n - emptyCabins.Length; i++) { var blueprint = new BluePrint("Log Cabin"); var building = new Building(blueprint, new Vector2(-10000, 0)); Game1.getFarm().buildings.Add(building); try { foreach (var warp in building.indoors.Value.warps) { //warp.TargetName = "Forest"; Helper.Reflection.GetField <NetString>(warp, "targetName", true).SetValue(new NetString("Forest")); warp.TargetX = 100; warp.TargetY = 20; } } catch (Exception) { } } Monitor.Log($"Added {n - emptyCabins.Length} player slots", LogLevel.Info); } else if (n < emptyCabins.Length) { for (int i = 0; i < emptyCabins.Length - n; i++) { Game1.getFarm().buildings.Remove(emptyCabins[i]); } Monitor.Log($"Removed {emptyCabins.Length - n} player slots", LogLevel.Info); } else { Monitor.Log($"There are already {n} player slots", LogLevel.Info); } } }); }