using System; using System.Collections.Generic; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Graphics; using Newtonsoft.Json; using StardewValley; namespace Revitalize.Framework.Illuminate { /// /// Deals with handling lights on custom objects. /// public class LightManager { /// /// The lights held by this object. /// public Dictionary lights; /// /// Used to recreate lights at run time. /// public Dictionary fakeLights; /// /// Are the lights on this object on? /// public bool lightsOn; /// /// Magic number for positioning. /// public const int lightBigNumber= 1000000; [JsonIgnore] public bool requiresUpdate; /// /// Constructor. /// public LightManager() { this.lights = new Dictionary(); this.fakeLights = new Dictionary(); this.lightsOn = false; } /// Add a light to the list of tracked lights. public bool addLight(Vector2 IdKey, LightSource light, StardewValley.Object gameObject) { if (gameObject.TileLocation.X < 0) gameObject.TileLocation = new Vector2(gameObject.TileLocation.X * -1, gameObject.TileLocation.Y); if (gameObject.TileLocation.Y < 0) gameObject.TileLocation = new Vector2(gameObject.TileLocation.X, gameObject.TileLocation.Y*-1); Vector2 initialPosition = gameObject.TileLocation * Game1.tileSize; initialPosition += IdKey; if (this.lights.ContainsKey(IdKey)) return false; light.position.Value = initialPosition; this.lights.Add(IdKey, light); if (this.fakeLights.ContainsKey(IdKey)) return true; this.fakeLights.Add(IdKey, new FakeLightSource(light.Identifier, light.position.Value, light.color.Value.Invert(), light.radius.Value)); this.requiresUpdate = true; return true; } /// /// Adds in a light at the given tile location in the world. /// /// /// /// /// public bool addLight(Vector2 IdKey, LightSource light, Vector2 gameObjectTileLocation) { if (gameObjectTileLocation.X < 0) gameObjectTileLocation = new Vector2(gameObjectTileLocation.X * -1, gameObjectTileLocation.Y); if (gameObjectTileLocation.Y < 0) gameObjectTileLocation = new Vector2(gameObjectTileLocation.X, gameObjectTileLocation.Y * -1); Vector2 initialPosition = gameObjectTileLocation * Game1.tileSize; initialPosition += IdKey; if (this.lights.ContainsKey(IdKey)) return false; light.position.Value = initialPosition; this.lights.Add(IdKey, light); if (this.fakeLights.ContainsKey(IdKey)) return true; this.fakeLights.Add(IdKey, new FakeLightSource(light.Identifier, light.position.Value, light.color.Value.Invert(), light.radius.Value)); this.requiresUpdate = true; return true; } /// Turn off a single light. public bool turnOffLight(Vector2 IdKey, GameLocation location) { if (!this.lights.ContainsKey(IdKey)) return false; this.lights.TryGetValue(IdKey, out LightSource light); Game1.currentLightSources.Remove(light); location.sharedLights.Remove((int)IdKey.X * lightBigNumber + (int)IdKey.Y); return true; } /// Turn on a single light. public bool turnOnLight(Vector2 IdKey, GameLocation location, StardewValley.Object gameObject) { if (!this.lights.ContainsKey(IdKey)) return false; this.lights.TryGetValue(IdKey, out var light); if (light == null) throw new Exception("Light is null????"); Game1.currentLightSources.Add(light); if (location == null) throw new Exception("WHY IS LOC NULL???"); if (location.sharedLights == null) throw new Exception("Locational lights is null!"); if (light.lightTexture == null) { light.lightTexture = this.loadTextureFromConstantValue(light.Identifier); } Game1.currentLightSources.Add(light); location.sharedLights.Add((int)IdKey.X*lightBigNumber+(int)IdKey.Y,light); this.repositionLight(light, IdKey, gameObject); this.requiresUpdate = true; return true; } /// Add a light source to this location. /// The game location to add the light source in. public virtual void turnOnLights(GameLocation environment, StardewValley.Object gameObject) { foreach (KeyValuePair pair in this.lights) this.turnOnLight(pair.Key, environment, gameObject); this.repositionLights(gameObject); } /// Removes a lightsource from the game location. /// The game location to remove the light source from. public void turnOffLights(GameLocation environment) { foreach (KeyValuePair pair in this.lights) this.turnOffLight(pair.Key, environment); } /// /// Repositions all lights for this object. /// /// public void repositionLights(StardewValley.Object gameObject) { foreach (KeyValuePair pair in this.lights) this.repositionLight(pair.Value, pair.Key, gameObject); } /// /// Reposition a light for this object. /// /// /// /// public void repositionLight(LightSource light, Vector2 offset, StardewValley.Object gameObject) { Vector2 initialPosition = gameObject.TileLocation * Game1.tileSize; light.position.Value = initialPosition + offset; this.requiresUpdate = true; } /// /// Toggles the lights for this object. /// /// /// public virtual void toggleLights(GameLocation location, StardewValley.Object gameObject) { if (!this.lightsOn) { this.turnOnLights(location, gameObject); this.lightsOn = true; return; } else if (this.lightsOn) { this.turnOffLights(Game1.player.currentLocation); this.lightsOn = false; return; } } /// /// Removes the lights from the world when this object needs to be cleaned up. /// /// public virtual void removeForCleanUp(GameLocation loc) { this.turnOffLights(loc); } /// /// Loads in the appropriate texture from sdv depending on the int value used. /// /// /// private Texture2D loadTextureFromConstantValue(int value) { switch (value) { case 1: return Game1.lantern; break; case 2: return Game1.windowLight; break; case 4: return Game1.sconceLight; break; case 5: return Game1.cauldronLight; break; case 6: return Game1.indoorWindowLight; break; } return Game1.sconceLight; } /// /// Gets a copy of all of the /// /// public LightManager Copy() { LightManager copy= new LightManager(); if (this.lights != null) { //ModCore.log("Info for file"+Path.GetFileNameWithoutExtension(file)+" has this many lights: " + info.info.lightManager.fakeLights.Count); copy.lights.Clear(); foreach (KeyValuePair light in this.fakeLights) { Vector2 position = light.Value.positionOffset; position -= light.Key; position /= Game1.tileSize; position = new Vector2((float)Math.Round(position.X), (float)Math.Round(position.Y)); copy.addLight(light.Key, new LightSource(light.Value.id, new Vector2(0, 0), light.Value.radius, light.Value.color.Invert()), position); } } return copy; } public static LightSource CreateLightSource(float Radius, Color ActualColor,int Texture=4) { return new LightSource(Texture, new Vector2(0, 0), Radius, ActualColor.Invert()); } } }