262 lines
9.8 KiB
C#
262 lines
9.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
using Newtonsoft.Json;
|
|
using StardewValley;
|
|
|
|
namespace Revitalize.Framework.Illuminate
|
|
{
|
|
/// <summary>
|
|
/// Deals with handling lights on custom objects.
|
|
/// </summary>
|
|
public class LightManager
|
|
{
|
|
/// <summary>
|
|
/// The lights held by this object.
|
|
/// </summary>
|
|
public Dictionary<Vector2, LightSource> lights;
|
|
/// <summary>
|
|
/// Used to recreate lights at run time.
|
|
/// </summary>
|
|
public Dictionary<Vector2, FakeLightSource> fakeLights;
|
|
/// <summary>
|
|
/// Are the lights on this object on?
|
|
/// </summary>
|
|
public bool lightsOn;
|
|
|
|
/// <summary>
|
|
/// Magic number for positioning.
|
|
/// </summary>
|
|
public const int lightBigNumber= 1000000;
|
|
|
|
[JsonIgnore]
|
|
public bool requiresUpdate;
|
|
|
|
/// <summary>
|
|
/// Constructor.
|
|
/// </summary>
|
|
public LightManager()
|
|
{
|
|
this.lights = new Dictionary<Vector2, LightSource>();
|
|
this.fakeLights = new Dictionary<Vector2, FakeLightSource>();
|
|
this.lightsOn = false;
|
|
}
|
|
|
|
/// <summary>Add a light to the list of tracked lights.</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Adds in a light at the given tile location in the world.
|
|
/// </summary>
|
|
/// <param name="IdKey"></param>
|
|
/// <param name="light"></param>
|
|
/// <param name="gameObjectTileLocation"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>Turn off a single light.</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>Turn on a single light.</summary>
|
|
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;
|
|
}
|
|
|
|
/// <summary>Add a light source to this location.</summary>
|
|
/// <param name="environment">The game location to add the light source in.</param>
|
|
public virtual void turnOnLights(GameLocation environment, StardewValley.Object gameObject)
|
|
{
|
|
foreach (KeyValuePair<Vector2, LightSource> pair in this.lights)
|
|
this.turnOnLight(pair.Key, environment, gameObject);
|
|
this.repositionLights(gameObject);
|
|
}
|
|
|
|
/// <summary>Removes a lightsource from the game location.</summary>
|
|
/// <param name="environment">The game location to remove the light source from.</param>
|
|
public void turnOffLights(GameLocation environment)
|
|
{
|
|
foreach (KeyValuePair<Vector2, LightSource> pair in this.lights)
|
|
this.turnOffLight(pair.Key, environment);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Repositions all lights for this object.
|
|
/// </summary>
|
|
/// <param name="gameObject"></param>
|
|
public void repositionLights(StardewValley.Object gameObject)
|
|
{
|
|
foreach (KeyValuePair<Vector2, LightSource> pair in this.lights)
|
|
this.repositionLight(pair.Value, pair.Key, gameObject);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reposition a light for this object.
|
|
/// </summary>
|
|
/// <param name="light"></param>
|
|
/// <param name="offset"></param>
|
|
/// <param name="gameObject"></param>
|
|
public void repositionLight(LightSource light, Vector2 offset, StardewValley.Object gameObject)
|
|
{
|
|
Vector2 initialPosition = gameObject.TileLocation * Game1.tileSize;
|
|
light.position.Value = initialPosition + offset;
|
|
this.requiresUpdate = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Toggles the lights for this object.
|
|
/// </summary>
|
|
/// <param name="location"></param>
|
|
/// <param name="gameObject"></param>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Removes the lights from the world when this object needs to be cleaned up.
|
|
/// </summary>
|
|
/// <param name="loc"></param>
|
|
public virtual void removeForCleanUp(GameLocation loc)
|
|
{
|
|
this.turnOffLights(loc);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Loads in the appropriate texture from sdv depending on the int value used.
|
|
/// </summary>
|
|
/// <param name="value"></param>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets a copy of all of the
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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<Vector2, FakeLightSource> 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());
|
|
}
|
|
|
|
}
|
|
}
|