private void onWarped(object sender, WarpedEventArgs e) { if (!e.IsLocalPlayer) { return; } BuildableGameLocation farm = e.NewLocation as BuildableGameLocation; if (farm == null) { farm = e.OldLocation as BuildableGameLocation; } if (farm != null) { for (int i = 0; i < farm.buildings.Count; ++i) { var b = farm.buildings[i]; // This is probably a new building if it hasn't been converted yet. if (buildings.ContainsKey(b.buildingType.Value) && !(b is Coop)) { farm.buildings[i] = new Coop(new BluePrint(b.buildingType), new Vector2(b.tileX, b.tileY)); farm.buildings[i].indoors.Value = b.indoors.Value; farm.buildings[i].load(); (farm.buildings[i].indoors.Value as AnimalHouse).animalLimit.Value = buildings[b.buildingType.Value].MaxOccupants; } } } }
public override void Entry(IModHelper helper) { Farm = null; this.Config = this.Helper.ReadConfig <ModConfig>(); helper.Events.GameLoop.SaveLoaded += GetFarm; helper.Events.Display.Rendering += ChangeWater; }
/********* ** Public methods *********/ /// <summary>Construct an instance.</summary> /// <param name="location">The location containing the garage.</param> /// <param name="building">The garage building.</param> /// <param name="tractor">The tractor for this garage (if found).</param> /// <param name="saveData">The garage save data.</param> public GarageMetadata(BuildableGameLocation location, Building building, Tractor tractor, CustomSaveBuilding saveData) { this.Location = location; this.Building = building; this.Tractor = tractor; this.SaveData = saveData; }
/// <summary>Restore tractor and garage data removed by <see cref="StashCustomData"/>.</summary> /// <remarks>The Robin construction logic is derived from <see cref="NPC.reloadSprite"/> and <see cref="StardewValley.Farm.resetForPlayerEntry"/>.</remarks> private void RestoreCustomData() { // get save data CustomSaveData saveData = this.Helper.ReadJsonFile <CustomSaveData>(this.GetDataPath(Constants.SaveFolderName)); if (saveData?.Buildings == null) { return; } // add tractor + garages BuildableGameLocation[] locations = CommonHelper.GetLocations().OfType <BuildableGameLocation>().ToArray(); foreach (CustomSaveBuilding garageData in saveData.Buildings) { // get location BuildableGameLocation location = locations.FirstOrDefault(p => this.GetMapName(p) == (garageData.Map ?? "Farm")); if (location == null) { this.Monitor.Log($"Ignored tractor garage in unknown location '{garageData.Map}'."); continue; } // add garage int daysOfConstructionLeft = Math.Max(0, garageData.DaysOfConstructionLeft - 1); this.SpawnGarage(location, (int)garageData.Tile.X, (int)garageData.Tile.Y, daysOfConstructionLeft, garageData.TractorID, garageData.TractorHatID); } }
/**** ** State methods ****/ /// <summary>Detect and fix tractor garages that started construction today.</summary> private void ProcessNewConstruction() { foreach (GarageMetadata metadata in this.GetGarages().ToArray()) { this.HasAnyGarages = true; Building garage = metadata.Building; BuildableGameLocation location = metadata.Location; // skip if not built today if (garage is TractorGarage) { continue; } // set construction days after it's placed if (!this.GaragesStartedToday.Contains(garage)) { garage.daysOfConstructionLeft = this.GarageConstructionDays; this.GaragesStartedToday.Add(garage); } // spawn tractor if built instantly by a mod if (!garage.isUnderConstruction()) { this.GaragesStartedToday.Remove(garage); location.destroyStructure(garage); location.buildings.Add(new TractorGarage(this.GetBlueprint(), new Vector2(garage.tileX, garage.tileY), 0)); if (this.Tractor == null) { this.Tractor = this.SpawnTractor(location, garage.tileX + 1, garage.tileY + 1); } } } }
public static void addAnimal(string loc, FarmAnimal animal) { Log.debug("DEBUG:Adding farm animal"); AnimalHouse home = (AnimalHouse)Game1.getLocationFromName(loc); (home as AnimalHouse).animals.Add(animal.myID, animal); (home as AnimalHouse).animalsThatLiveHere.Add(animal.myID); if (!Multiplayer.COOP) { Log.warn("NOT IMPLEMENTED:ANIMAL ADDITION"); return; } BuildableGameLocation farm = ( BuildableGameLocation )Game1.getLocationFromName("Farm"); Building buildingAt = null; foreach (Building building in farm.buildings) { if (building.tileX == animal.homeLocation.X && building.tileY == animal.homeLocation.Y) { buildingAt = building; break; } } if (buildingAt != null) { animal.home = buildingAt; } animals[animal.myID] = new FarmAnimalState(animal); }
private void onWarped(object sender, WarpedEventArgs e) { if (!e.IsLocalPlayer) { return; } BuildableGameLocation farm = e.NewLocation as BuildableGameLocation ?? e.OldLocation as BuildableGameLocation; if (farm != null) { for (int i = 0; i < farm.buildings.Count; ++i) { var b = farm.buildings[i]; if (b.buildingType.Value == "GreenhouseConstruction_SpecialGreenhouse" && !(b is CustomGreenhouseBuilding)) { farm.buildings[i] = new CustomGreenhouseBuilding(); farm.buildings[i].buildingType.Value = b.buildingType.Value; farm.buildings[i].daysOfConstructionLeft.Value = b.daysOfConstructionLeft.Value; farm.buildings[i].indoors.Value = b.indoors.Value; farm.buildings[i].tileX.Value = b.tileX.Value; farm.buildings[i].tileY.Value = b.tileY.Value; farm.buildings[i].tilesWide.Value = b.tilesWide.Value; farm.buildings[i].tilesHigh.Value = b.tilesHigh.Value; farm.buildings[i].load(); } } } }
/********* ** Private methods *********/ /// <summary>The method to call before <see cref="SaveGame.loadDataToLocations"/>.</summary> private static void Before_LoadDataToLocations(List <GameLocation> gamelocations) { SaveGamePatcher.Locations = gamelocations; foreach (GameLocation gamelocation in gamelocations) { if (gamelocation.Name == "Farm") { continue; } if (gamelocation is BuildableGameLocation buildableGameLocation) { BuildableGameLocation locationFromName = (BuildableGameLocation)Game1.getLocationFromName(gamelocation.Name); foreach (Building building in buildableGameLocation.buildings) { building.load(); } locationFromName.buildings.Set(buildableGameLocation.buildings); } else if (gamelocation is IAnimalLocation al) { foreach (FarmAnimal farmAnimal in al.Animals.Values) { farmAnimal.reload(null); } } } }
public static void endChecks() { foreach (long id in checkMissing) { if (!Multiplayer.COOP) { Log.warn("NOT IMPLEMENTED:ANIMAL DELETION"); continue; } BuildableGameLocation farm = ( BuildableGameLocation )Game1.getLocationFromName("Farm"); Building buildingAt = null; foreach (Building building in farm.buildings) { if (building.tileX == animals[id].homeLoc.X && building.tileY == animals[id].homeLoc.Y) { buildingAt = building; break; } } if (buildingAt != null) { Log.trace("Sending animal deletion packet"); animals.Remove(id); Multiplayer.sendFunc(new FarmAnimalPacket(buildingAt, id)); } } checkMissing.Clear(); }
/// <summary>Spawn a new tractor.</summary> /// <param name="location">The location in which to spawn a tractor.</param> /// <param name="tileX">The tile X position at which to spawn it.</param> /// <param name="tileY">The tile Y position at which to spawn it.</param> private TractorManager SpawnTractor(BuildableGameLocation location, int tileX, int tileY) { TractorManager tractor = new TractorManager(tileX, tileY, this.Config, this.Attachments, this.GetTexture("tractor"), this.Helper.Translation, this.Helper.Reflection); tractor.SetLocation(location, new Vector2(tileX, tileY)); tractor.SetPixelPosition(new Vector2(tractor.Current.Position.X + 20, tractor.Current.Position.Y)); return(tractor); }
/// <summary>Spawn a new tractor.</summary> /// <param name="location">The location in which to spawn a tractor.</param> /// <param name="tractorID">The tractor's unique horse ID.</param> /// <param name="tileX">The tile X position at which to spawn it.</param> /// <param name="tileY">The tile Y position at which to spawn it.</param> private Tractor SpawnTractor(Guid tractorID, BuildableGameLocation location, int tileX, int tileY) { Tractor tractor = new Tractor(tractorID, tileX, tileY, this.Config, this.Attachments, this.Helper.Content.GetActualAssetKey(this.GetTextureKey("tractor")), this.Helper.Translation, this.Helper.Reflection); tractor.SetLocation(location, new Vector2(tileX, tileY)); tractor.SetPixelPosition(new Vector2(tractor.Position.X + 20, tractor.Position.Y)); return(tractor); }
/// <summary>Restore tractor and garage data removed by <see cref="StashCustomData"/>.</summary> /// <remarks>The Robin construction logic is derived from <see cref="NPC.reloadSprite"/> and <see cref="StardewValley.Farm.resetForPlayerEntry"/>.</remarks> private void RestoreCustomData() { // get save data CustomSaveData saveData = this.Helper.ReadJsonFile <CustomSaveData>(this.GetDataPath(Constants.SaveFolderName)); if (saveData?.Buildings == null) { return; } // add tractor + garages BluePrint blueprint = this.GetBlueprint(); BuildableGameLocation[] locations = CommonHelper.GetLocations().OfType <BuildableGameLocation>().ToArray(); foreach (CustomSaveBuilding garageData in saveData.Buildings) { // get location BuildableGameLocation location = locations.FirstOrDefault(p => this.GetMapName(p) == (garageData.Map ?? "Farm")); if (location == null) { this.Monitor.Log($"Ignored tractor garage in unknown location '{garageData.Map}'."); continue; } // add garage TractorGarage garage = new TractorGarage(blueprint, garageData.Tile, Math.Max(0, garageData.DaysOfConstructionLeft - 1)); location.buildings.Add(garage); // add Robin construction if (garage.isUnderConstruction() && !this.IsRobinBusy) { this.IsRobinBusy = true; NPC robin = Game1.getCharacterFromName("Robin"); // update Robin robin.ignoreMultiplayerUpdates = true; robin.sprite.setCurrentAnimation(new List <FarmerSprite.AnimationFrame> { new FarmerSprite.AnimationFrame(24, 75), new FarmerSprite.AnimationFrame(25, 75), new FarmerSprite.AnimationFrame(26, 300, false, false, farmer => this.Helper.Reflection.GetPrivateMethod(robin, "robinHammerSound").Invoke(farmer)), new FarmerSprite.AnimationFrame(27, 1000, false, false, farmer => this.Helper.Reflection.GetPrivateMethod(robin, "robinVariablePause").Invoke(farmer)) }); robin.ignoreScheduleToday = true; Game1.warpCharacter(robin, location.Name, new Vector2(garage.tileX + garage.tilesWide / 2, garage.tileY + garage.tilesHigh / 2), false, false); robin.position.X += Game1.tileSize / 4; robin.position.Y -= Game1.tileSize / 2; robin.CurrentDialogue.Clear(); robin.CurrentDialogue.Push(new Dialogue(Game1.content.LoadString("Strings\\StringsFromCSFiles:NPC.cs.3926"), robin)); } // spawn tractor if (this.Tractor == null && !garage.isUnderConstruction()) { this.Tractor = this.SpawnTractor(location, garage.tileX + 1, garage.tileY + 1); } } }
/// <summary>Get a machine, container, or connector from the given entity, if any.</summary> /// <param name="location">The location to check.</param> /// <param name="tile">The tile to check.</param> /// <param name="entity">The entity to check.</param> public IAutomatable?GetEntityFor(GameLocation location, Vector2 tile, object entity) { return(entity switch { SObject obj => this.GetEntityFor(location, tile, obj), TerrainFeature feature => this.GetEntityFor(location, tile, feature), Building building when location is BuildableGameLocation buildableLocation => this.GetEntityFor(buildableLocation, tile, building), _ => null });
public void populateChests() { chests.Clear(); foreach (GameLocation location in Game1.locations) { List <Chest> chestss = new List <Chest>(); foreach (KeyValuePair <Vector2, Object> o in location.objects) { if (o.Value is Chest) { if (showChest(o.Value.name)) { chestss.Add((Chest)o.Value); } } } if (location is BuildableGameLocation) { BuildableGameLocation bLocation = (BuildableGameLocation)location; foreach (Building building in bLocation.buildings) { if (building.indoors != null) { foreach (KeyValuePair <Vector2, Object> o in building.indoors.objects) { if (o.Value is Chest) { if (showChest(o.Value.name)) { chestss.Add((Chest)o.Value); } } } } } } if (location is FarmHouse) { FarmHouse farmHouse = (FarmHouse)location; if (farmHouse.fridge != null && farmHouse.fridge.items.Count > 0) { if (farmHouse.fridge.name == "Chest") { farmHouse.fridge.Name = "Fridge"; } chestss.Add(farmHouse.fridge); } } if (chestss.Count > 0) { var orderedChests = from element in chestss orderby element.name select element; chests.Add(location.name, new List <Chest>(orderedChests)); } } }
public Aquaponics(Vector2 position, BuildableGameLocation location) : base() { build(position, location, 4); if (position != Vector2.Zero) { AquaponicsLocation apl = new AquaponicsLocation(AquaponicsMod.helper.Content.Load <Map>(@"assets\greenhouseMap.tbin", ContentSource.ModFolder), nameOfIndoors, (BuildableGameLocation)location); indoors = apl; } }
public void rebuild(Dictionary <string, string> additionalSaveData, object replacement) { Building building = (Building)replacement; indoors = building.indoors; Vector2 p = new Vector2(building.tileX, building.tileY); BuildableGameLocation l = (BuildableGameLocation)Game1.getLocationFromName(additionalSaveData["location"]); build(p, l, building.daysOfConstructionLeft); }
public Aquaponics(Vector2 coords, BuildableGameLocation location) : base() { build(coords, location, DaysToBuild); if (coords != Vector2.Zero) { ghLocation = new Vector2(45, 45); //Routine's Code: //AquaponicsLocation apl = new AquaponicsLocation(AquaponicsMod.helper.Content.Load<Map>(@"assets\greenhouseMap.xnb", ContentSource.ModFolder), nameOfIndoors, (BuildableGameLocation)location); //indoors = apl; } }
/********* ** Internal Methods *********/ /// <summary>The prefix for the <see cref="BuildableGameLocation.isBuildingConstructed(string)"/> method.</summary> /// <param name="name">The name of the building to check for a constructed version.</param> /// <param name="__instance">The <see cref="BuildableGameLocation"/> instance being patched.</param> /// <param name="__result">The return value of the method being patched.</param> /// <returns><see langword="false"/>, meaning the original method will not get ran.</returns> /// <remarks>This reimplements the original method so the passed building name can be case insensitive.</remarks> internal static bool IsBuildingConstructedPrefix(string name, BuildableGameLocation __instance, ref bool __result) { foreach (var building in __instance.buildings) { if (building.buildingType.Value.ToLower() == name.ToLower() && building.daysOfConstructionLeft <= 0) { __result = true; } } return(false); }
/**** ** State methods ****/ /// <summary>Fix a garage if necessary so it has the correct custom behavior.</summary> /// <param name="building">The building to fix.</param> /// <param name="location">The location containing the building.</param> /// <returns>Returns whether the building is a tractor.</returns> private void FixGarage(Building building, BuildableGameLocation location) { // skip if no fix needed if (building is TractorGarage || building.buildingType.Value != this.GarageBuildingType) { return; } // replace building location.destroyStructure(building); this.SpawnGarage(location, building.tileX.Value, building.tileY.Value, building.daysOfConstructionLeft.Value, Guid.NewGuid(), 0); }
internal static GameLocation GetNewLocation(LocationData data) { string type = data.Type.ToLower(); if (data.Save) { try { if (Helper.Data.ReadSaveData <LocationSaveData>($"{LocationSaveData}") is LocationSaveData saveDataStore && saveDataStore.Locations.ContainsKey(data.Name) && saveDataStore.Locations[data.Name] is string savedata && !string.IsNullOrEmpty(savedata)) { XmlSerializer serializer = null; if (Type.GetType(data.Type) is Type customType) { serializer = new XmlSerializer(customType, ExtraTypes); } else { serializer = new XmlSerializer(typeof(GameLocation), ExtraTypes); } using (StringReader dataReader = new StringReader(savedata)) using (var reader = XmlReader.Create(dataReader, SaveReaderSettings)) if (serializer.Deserialize(reader) is GameLocation savedLocation) { return(savedLocation); } } } catch { } } GameLocation result; switch (type) { case "buildable": result = new BuildableGameLocation(data.MapPath, data.Name); break; case "decoratable": result = new DecoratableLocation(data.MapPath, data.Name); break; case "default": result = new GameLocation(data.MapPath, data.Name); break; default: { if (Type.GetType(data.Type) is Type customType && Activator.CreateInstance(customType, data.MapPath, data.Name) is GameLocation customLocation) { result = customLocation; }
public void build(BuildableGameLocation buildAt) { this.buildAt = buildAt; isFarm = true; isStructure = true; floor = new List <int>(); wallPaper = new List <int>(); terrainFeatures = new SerializableDictionary <Vector2, StardewValley.TerrainFeatures.TerrainFeature>(); objects = new SerializableDictionary <Vector2, Object>(); largeTerrainFeatures = new List <StardewValley.TerrainFeatures.LargeTerrainFeature>(); furniture = new List <StardewValley.Objects.Furniture>(); }
private Fence LookAround(BuildableGameLocation location, List <Vector2> list) { foreach (Vector2 pos in list) { Fence gate = this.GetGate(location, pos); if (gate != null) { return(gate); } } return(null); }
public static List <Cabin> getCabins(BuildableGameLocation location) { List <Cabin> outCabins = new List <Cabin>(); foreach (Building b in location.buildings) { if (b.indoors != null && b.indoors.Value is Cabin) { outCabins.Add(b.indoors.Value as Cabin); } } return(outCabins); }
/// <summary>Migrate tractors and garages from older versions of the mod.</summary> /// <remarks>The Robin construction logic is derived from <see cref="NPC.reloadSprite"/> and <see cref="Farm.resetForPlayerEntry"/>.</remarks> private void LoadLegacyData() { // fix building types foreach (BuildableGameLocation location in this.GetBuildableLocations()) { foreach (Stable stable in location.buildings.OfType <Stable>()) { if (stable.buildingType.Value == this.BlueprintBuildingType) { stable.buildingType.Value = "Stable"; stable.maxOccupants.Value = this.MaxOccupantsID; } } } // get save data LegacySaveData saveData = this.Helper.Data.ReadSaveData <LegacySaveData>("tractors"); // 4.6 if (saveData?.Buildings == null) { saveData = this.Helper.Data.ReadJsonFile <LegacySaveData>(this.LegacySaveDataRelativePath); // pre-4.6 } if (saveData?.Buildings == null) { return; } // add tractor + garages BuildableGameLocation[] locations = this.GetBuildableLocations().ToArray(); foreach (LegacySaveDataBuilding garageData in saveData.Buildings) { // get location BuildableGameLocation location = locations.FirstOrDefault(p => p.NameOrUniqueName == (garageData.Map ?? "Farm")); if (location == null) { this.Monitor.Log($"Ignored legacy tractor garage in unknown location '{garageData.Map}'.", LogLevel.Warn); continue; } // add garage Stable garage = location.buildings.OfType <Stable>().FirstOrDefault(p => p.tileX.Value == (int)garageData.Tile.X && p.tileY.Value == (int)garageData.Tile.Y); if (garage == null) { garage = new Stable(garageData.TractorID, this.GetBlueprint(), garageData.Tile); garage.daysOfConstructionLeft.Value = 0; location.buildings.Add(garage); } garage.maxOccupants.Value = this.MaxOccupantsID; garage.load(); } }
private Fence GetGate(BuildableGameLocation location, Vector2 pos) { if (!location.objects.TryGetValue(pos, out StardewValley.Object obj)) { return(null); } if (obj is Fence fence && fence.isGate.Value && !this.OpenGates.ContainsKey(pos)) { this.OpenGates[pos] = fence; return(fence); } return(null); }
// public void setNewActiveFarmMap() { if (currentFarmIndex < 0) { currentFarmIndex = Memory.farmMaps.Count - 1; } else if (currentFarmIndex > Memory.farmMaps.Count - 1) { currentFarmIndex = 0; } currentFarmDisplay = Memory.farmMaps[currentFarmIndex].displayName; currentFarmMap = (BuildableGameLocation)Game1.getLocationFromName(Memory.farmMaps[currentFarmIndex].Location); }
private static void AddLocations(List <GameLocation> list, BuildableGameLocation bloc) { foreach (var building in bloc.buildings) { if (building.indoors.Value != null) { list.Add(building.indoors.Value); if (building.indoors.Value is BuildableGameLocation bloc2) { AddLocations(list, bloc2); } } } }
public void checkIfBuilding() { this.building = -1; this.bgl = null; if (this.index == -1) { if (this.location.GetType().GetMethod("getBuilding") != null) { Building building = (this.location as AnimalHouse).getBuilding(); this.building = Game1.getFarm().buildings.IndexOf(building); this.bgl = Game1.getFarm(); } } }
private static void updateAnimal(BuildableGameLocation farm, FarmAnimal animal, FarmAnimalState state) {/* * Log.Async("Updating animal " + animal.myID); * Log.Async("Name: " + animal.name + " -> " + state.name); * Log.Async("Reproduction: " + animal.allowReproduction + " -> " + state.reproduce); * Log.Async("Fullness: " + animal.fullness + " -> " + state.fullness); * Log.Async("Product: " + animal.currentProduce + " -> " + state.product); * Log.Async("Petted: " + animal.wasPet + " -> " + state.pet); * Log.Async("Affection: " + animal.friendshipTowardFarmer + " -> " + state.friendship); * Log.Async("Home: (" + animal.homeLocation.X + ", " + animal.homeLocation.Y + ") -> (" + state.homeLoc.X + ", " + state.homeLoc.Y + ")"); */ animal.name = state.name; animal.allowReproduction = state.reproduce; animal.fullness = (byte)state.fullness; animal.currentProduce = state.product; animal.wasPet = state.pet; animal.friendshipTowardFarmer = state.friendship; if (animal.homeLocation.X != state.homeLoc.X && animal.homeLocation.Y != state.homeLoc.Y) { Building buildingAt = null; foreach (Building building in farm.buildings) { if (building.tileX == state.homeLoc.X && building.tileY == state.homeLoc.Y) { buildingAt = building; break; } } if (buildingAt != null) { // From AnimalQueryMenu (animal.home.indoors as AnimalHouse).animalsThatLiveHere.Remove(animal.myID); if ((animal.home.indoors as AnimalHouse).animals.ContainsKey(animal.myID)) { (buildingAt.indoors as AnimalHouse).animals.Add(animal.myID, animal); (animal.home.indoors as AnimalHouse).animals.Remove(animal.myID); } animal.home = buildingAt; animal.homeLocation = state.homeLoc; (buildingAt.indoors as AnimalHouse).animalsThatLiveHere.Add(animal.myID); } } animals[animal.myID] = state; }
public void rebuild(Dictionary <string, string> additionalSaveData, object replacement) { BuildableGameLocation e = (BuildableGameLocation)Game1.getLocationFromName(additionalSaveData["buildAt"]); build(e); name = additionalSaveData["name"]; Shed shed = (Shed)replacement; objects = shed.objects; terrainFeatures = shed.terrainFeatures; furniture = shed.furniture; floor = shed.floor; wallPaper = shed.wallPaper; largeTerrainFeatures = shed.largeTerrainFeatures; }