2018-12-30 18:00:05 +08:00
using System ;
using System.Collections.Generic ;
2019-01-11 03:09:51 +08:00
using System.IO ;
2019-10-04 14:42:16 +08:00
using System.Linq ;
2019-01-09 20:03:27 +08:00
using System.Text ;
2018-12-30 18:00:05 +08:00
using Microsoft.Xna.Framework ;
2018-12-23 16:53:43 +08:00
using Microsoft.Xna.Framework.Graphics ;
2019-09-10 06:44:25 +08:00
using Newtonsoft.Json ;
2018-12-23 16:53:43 +08:00
using PyTK.CustomElementHandler ;
2019-09-10 06:44:25 +08:00
using Revitalize.Framework.Energy ;
2019-09-24 09:13:45 +08:00
using Revitalize.Framework.Managers ;
2019-08-28 06:10:56 +08:00
using Revitalize.Framework.Utilities ;
2018-12-23 16:53:43 +08:00
using StardewValley ;
using StardewValley.Objects ;
namespace Revitalize.Framework.Objects
{
2019-01-09 20:03:27 +08:00
public class MultiTiledComponent : CustomObject , ISaveElement
2018-12-23 16:53:43 +08:00
{
2019-08-28 06:10:56 +08:00
2019-09-10 06:44:25 +08:00
[JsonIgnore]
2019-08-28 06:10:56 +08:00
public override string ItemInfo
{
get
{
string info = Revitalize . ModCore . Serializer . ToJSONString ( this . info ) ;
string guidStr = this . guid . ToString ( ) ;
2019-08-28 15:31:14 +08:00
string pyTkData = ModCore . Serializer . ToJSONString ( this . data ) ;
2019-08-28 06:10:56 +08:00
string offsetKey = this . offsetKey ! = null ? ModCore . Serializer . ToJSONString ( this . offsetKey ) : "" ;
string container = this . containerObject ! = null ? this . containerObject . guid . ToString ( ) : "" ;
2019-08-28 15:31:14 +08:00
return info + "<" + guidStr + "<" + pyTkData + "<" + offsetKey + "<" + container ;
2019-08-28 06:10:56 +08:00
}
set
{
if ( string . IsNullOrEmpty ( value ) ) return ;
string [ ] data = value . Split ( '<' ) ;
string infoString = data [ 0 ] ;
string guidString = data [ 1 ] ;
2019-08-28 15:31:14 +08:00
string pyTKData = data [ 2 ] ;
string offsetVec = data [ 3 ] ;
string containerObject = data [ 4 ] ;
2019-08-28 06:10:56 +08:00
this . info = ( BasicItemInformation ) Revitalize . ModCore . Serializer . DeserializeFromJSONString ( infoString , typeof ( BasicItemInformation ) ) ;
2019-08-28 15:31:14 +08:00
this . data = Revitalize . ModCore . Serializer . DeserializeFromJSONString < CustomObjectData > ( pyTKData ) ;
2019-08-28 06:10:56 +08:00
if ( string . IsNullOrEmpty ( offsetVec ) ) return ;
if ( string . IsNullOrEmpty ( containerObject ) ) return ;
this . offsetKey = ModCore . Serializer . DeserializeFromJSONString < Vector2 > ( offsetVec ) ;
Guid oldGuid = this . guid ;
this . guid = Guid . Parse ( guidString ) ;
if ( ModCore . CustomObjects . ContainsKey ( this . guid ) )
{
//ModCore.log("Update item with guid: " + this.guid);
ModCore . CustomObjects [ this . guid ] = this ;
}
else
{
//ModCore.log("Add in new guid: " + this.guid);
ModCore . CustomObjects . Add ( this . guid , this ) ;
}
if ( this . containerObject = = null )
{
//ModCore.log(containerObject);
Guid containerGuid = Guid . Parse ( containerObject ) ;
if ( ModCore . CustomObjects . ContainsKey ( containerGuid ) )
{
this . containerObject = ( MultiTiledObject ) ModCore . CustomObjects [ containerGuid ] ;
this . containerObject . removeComponent ( this . offsetKey ) ;
this . containerObject . addComponent ( this . offsetKey , this ) ;
//ModCore.log("Set container object from existing object!");
}
else
{
//ModCore.log("Container hasn't been synced???");
MultiplayerUtilities . RequestGuidObject ( containerGuid ) ;
MultiplayerUtilities . RequestGuidObject_Tile ( this . guid ) ;
}
}
else
{
this . containerObject . updateInfo ( ) ;
}
if ( ModCore . CustomObjects . ContainsKey ( oldGuid ) & & ModCore . CustomObjects . ContainsKey ( this . guid ) )
{
if ( ModCore . CustomObjects [ oldGuid ] = = ModCore . CustomObjects [ this . guid ] & & oldGuid ! = this . guid )
{
//ModCore.CustomObjects.Remove(oldGuid);
}
}
}
}
2018-12-23 16:53:43 +08:00
public MultiTiledObject containerObject ;
2019-01-09 14:15:58 +08:00
public Vector2 offsetKey ;
2019-09-10 06:44:25 +08:00
2018-12-30 18:00:05 +08:00
public MultiTiledComponent ( ) { }
2018-12-23 16:53:43 +08:00
2019-07-16 17:09:42 +08:00
public MultiTiledComponent ( CustomObjectData PyTKData , BasicItemInformation info ) : base ( PyTKData , info ) { }
2018-12-23 16:53:43 +08:00
2019-07-16 17:09:42 +08:00
public MultiTiledComponent ( CustomObjectData PyTKData , BasicItemInformation info , Vector2 TileLocation , MultiTiledObject obj = null ) : base ( PyTKData , info , TileLocation ) {
2019-01-09 20:03:27 +08:00
this . containerObject = obj ;
}
2018-12-23 16:53:43 +08:00
2019-07-16 17:09:42 +08:00
public MultiTiledComponent ( CustomObjectData PyTKData , BasicItemInformation info , Vector2 TileLocation , Vector2 offsetKey , MultiTiledObject obj = null ) : base ( PyTKData , info , TileLocation ) {
2019-01-09 20:03:27 +08:00
this . offsetKey = offsetKey ;
this . containerObject = obj ;
}
2019-01-09 14:15:58 +08:00
2019-08-28 06:10:56 +08:00
public override void updateWhenCurrentLocation ( GameTime time , GameLocation environment )
{
base . updateWhenCurrentLocation ( time , environment ) ;
}
2019-01-09 14:15:58 +08:00
public override bool isPassable ( )
{
return this . info . ignoreBoundingBox | | Revitalize . ModCore . playerInfo . sittingInfo . SittingObject = = this . containerObject ;
}
2018-12-23 16:53:43 +08:00
public override bool checkForAction ( Farmer who , bool justCheckingForActivity = false )
{
2018-12-30 18:00:05 +08:00
//ModCore.log("Checking for a clicky click???");
2018-12-23 16:53:43 +08:00
return base . checkForAction ( who , justCheckingForActivity ) ;
}
2019-09-25 06:18:57 +08:00
public override bool canBePlacedHere ( GameLocation l , Vector2 tile )
{
return base . canBePlacedHere ( l , tile ) ;
}
2018-12-23 16:53:43 +08:00
public override bool clicked ( Farmer who )
{
2019-01-13 02:40:47 +08:00
//ModCore.log("Clicked a multiTiledComponent!");
2019-09-25 06:18:57 +08:00
if ( ModCore . playerInfo . justPlacedACustomObject = = true ) return false ;
if ( PlayerUtilities . CanPlayerInventoryReceiveThisItem ( this . containerObject ) ) {
this . containerObject . pickUp ( who ) ;
}
else
{
return false ;
}
2018-12-23 16:53:43 +08:00
return true ;
//return base.clicked(who);
}
2018-12-26 11:48:45 +08:00
public override bool rightClicked ( Farmer who )
{
if ( this . location = = null )
this . location = Game1 . player . currentLocation ;
2018-12-29 15:28:21 +08:00
2019-01-09 14:15:58 +08:00
//ModCore.playerInfo.sittingInfo.sit(this, Vector2.Zero);
2018-12-29 15:28:21 +08:00
2018-12-26 11:48:45 +08:00
return true ;
}
2018-12-23 16:53:43 +08:00
public override void performRemoveAction ( Vector2 tileLocation , GameLocation environment )
{
2018-12-26 11:48:45 +08:00
this . location = null ;
2018-12-23 16:53:43 +08:00
base . performRemoveAction ( this . TileLocation , environment ) ;
}
2018-12-30 18:00:05 +08:00
public virtual void removeFromLocation ( GameLocation location , Vector2 offset )
2018-12-23 16:53:43 +08:00
{
2019-05-18 00:43:50 +08:00
this . cleanUpLights ( ) ;
2018-12-30 18:00:05 +08:00
location . removeObject ( this . TileLocation , false ) ;
2018-12-26 11:48:45 +08:00
this . location = null ;
2018-12-23 16:53:43 +08:00
//this.performRemoveAction(this.TileLocation,location);
}
2019-05-18 00:43:50 +08:00
public virtual void cleanUpLights ( )
{
if ( this . info . lightManager ! = null ) this . info . lightManager . removeForCleanUp ( this . location ) ;
}
2018-12-30 18:00:05 +08:00
/// <summary>Places an object down.</summary>
2018-12-23 16:53:43 +08:00
public override bool placementAction ( GameLocation location , int x , int y , Farmer who = null )
{
2019-08-28 06:10:56 +08:00
this . updateInfo ( ) ;
2018-12-30 18:00:05 +08:00
this . updateDrawPosition ( x , y ) ;
2018-12-23 16:53:43 +08:00
this . location = location ;
2018-12-26 11:48:45 +08:00
if ( this . location = = null ) this . location = Game1 . player . currentLocation ;
2018-12-23 16:53:43 +08:00
this . TileLocation = new Vector2 ( ( int ) ( x / Game1 . tileSize ) , ( int ) ( y / Game1 . tileSize ) ) ;
2019-08-14 10:26:20 +08:00
//ModCore.log("TileLocation: " + this.TileLocation);
2019-05-17 04:00:43 +08:00
/ *
2018-12-23 16:53:43 +08:00
return base . placementAction ( location , x , y , who ) ;
2019-05-17 04:00:43 +08:00
* /
2019-05-18 00:43:50 +08:00
//this.updateLightManager();
2019-05-17 04:00:43 +08:00
this . performDropDownAction ( who ) ;
location . objects . Add ( this . TileLocation , this ) ;
2019-08-22 10:06:17 +08:00
2019-09-25 06:18:57 +08:00
2019-08-22 10:06:17 +08:00
if ( this . getBoundingBox ( this . TileLocation ) . Width = = 0 & & this . getBoundingBox ( this . TileLocation ) . Height = = 0 )
{
this . boundingBox . Value = new Rectangle ( this . boundingBox . X , this . boundingBox . Y , Game1 . tileSize , Game1 . tileSize ) ;
}
2019-08-23 04:43:11 +08:00
//ModCore.log(this.getBoundingBox(this.TileLocation));
2019-08-22 10:06:17 +08:00
2019-05-17 04:00:43 +08:00
return true ;
2018-12-23 16:53:43 +08:00
}
2019-05-18 00:43:50 +08:00
2018-12-23 16:53:43 +08:00
public override void drawInMenu ( SpriteBatch spriteBatch , Vector2 location , float scaleSize , float transparency , float layerDepth , bool drawStackNumber , Color c , bool drawShadow )
{
2019-08-28 06:10:56 +08:00
this . updateInfo ( ) ;
2018-12-23 16:53:43 +08:00
if ( drawStackNumber & & this . maximumStackSize ( ) > 1 & & ( ( double ) scaleSize > 0.3 & & this . Stack ! = int . MaxValue ) & & this . Stack > 1 )
Utility . drawTinyDigits ( this . Stack , spriteBatch , location + new Vector2 ( ( float ) ( Game1 . tileSize - Utility . getWidthOfTinyDigitString ( this . Stack , 3f * scaleSize ) ) + 3f * scaleSize , ( float ) ( ( double ) Game1 . tileSize - 18.0 * ( double ) scaleSize + 2.0 ) ) , 3f * scaleSize , 1f , Color . White ) ;
if ( drawStackNumber & & this . Quality > 0 )
{
float num = this . Quality < 4 ? 0.0f : ( float ) ( ( Math . Cos ( ( double ) Game1 . currentGameTime . TotalGameTime . Milliseconds * Math . PI / 512.0 ) + 1.0 ) * 0.0500000007450581 ) ;
spriteBatch . Draw ( Game1 . mouseCursors , location + new Vector2 ( 12f , ( float ) ( Game1 . tileSize - 12 ) + num ) , new Microsoft . Xna . Framework . Rectangle ? ( this . Quality < 4 ? new Microsoft . Xna . Framework . Rectangle ( 338 + ( this . Quality - 1 ) * 8 , 400 , 8 , 8 ) : new Microsoft . Xna . Framework . Rectangle ( 346 , 392 , 8 , 8 ) ) , Color . White * transparency , 0.0f , new Vector2 ( 4f , 4f ) , ( float ) ( 3.0 * ( double ) scaleSize * ( 1.0 + ( double ) num ) ) , SpriteEffects . None , layerDepth ) ;
}
2019-09-08 10:04:24 +08:00
2019-09-19 08:33:45 +08:00
spriteBatch . Draw ( this . displayTexture , location , new Rectangle ? ( this . animationManager . currentAnimation . sourceRectangle ) , this . info . DrawColor * transparency , 0f , new Vector2 ( ( float ) ( this . animationManager . currentAnimation . sourceRectangle . Width / 2 ) , ( float ) ( this . animationManager . currentAnimation . sourceRectangle . Height ) ) , scaleSize , SpriteEffects . None , layerDepth ) ;
2018-12-23 16:53:43 +08:00
}
public override Item getOne ( )
{
2019-08-17 06:32:14 +08:00
MultiTiledComponent component = new MultiTiledComponent ( this . data , this . info . Copy ( ) , this . TileLocation , this . offsetKey , this . containerObject ) ;
2018-12-23 16:53:43 +08:00
return component ;
}
2019-01-11 03:09:51 +08:00
public override object getReplacement ( )
{
return base . getReplacement ( ) ;
}
2018-12-23 16:53:43 +08:00
public override ICustomObject recreate ( Dictionary < string , string > additionalSaveData , object replacement )
{
2019-01-09 20:03:27 +08:00
//instead of using this.offsetkey.x use get additional save data function and store offset key there
2019-01-10 03:41:40 +08:00
Vector2 offsetKey = new Vector2 ( Convert . ToInt32 ( additionalSaveData [ "offsetKeyX" ] ) , Convert . ToInt32 ( additionalSaveData [ "offsetKeyY" ] ) ) ;
2019-01-13 03:25:45 +08:00
MultiTiledComponent self = Revitalize . ModCore . Serializer . DeserializeGUID < MultiTiledComponent > ( additionalSaveData [ "GUID" ] ) ;
if ( self = = null )
{
return null ;
}
2019-01-10 18:31:23 +08:00
2019-01-11 04:44:10 +08:00
if ( ! Revitalize . ModCore . ObjectGroups . ContainsKey ( additionalSaveData [ "ParentGUID" ] ) )
2019-01-13 03:25:45 +08:00
{
2019-01-11 03:09:51 +08:00
//Get new container
2019-01-11 15:24:55 +08:00
MultiTiledObject obj = ( MultiTiledObject ) Revitalize . ModCore . Serializer . DeserializeGUID < MultiTiledObject > ( additionalSaveData [ "ParentGUID" ] ) ;
2019-01-11 04:44:10 +08:00
self . containerObject = obj ;
obj . addComponent ( offsetKey , self ) ;
2019-01-13 02:40:47 +08:00
//Revitalize.ModCore.log("ADD IN AN OBJECT!!!!");
Revitalize . ModCore . ObjectGroups . Add ( additionalSaveData [ "ParentGUID" ] , ( MultiTiledObject ) obj ) ;
2019-01-13 03:25:45 +08:00
}
else
{
self . containerObject = Revitalize . ModCore . ObjectGroups [ additionalSaveData [ "ParentGUID" ] ] ;
2019-01-11 04:44:10 +08:00
Revitalize . ModCore . ObjectGroups [ additionalSaveData [ "GUID" ] ] . addComponent ( offsetKey , self ) ;
2019-01-13 02:40:47 +08:00
//Revitalize.ModCore.log("READD AN OBJECT!!!!");
2019-01-13 03:25:45 +08:00
}
2019-01-10 18:31:23 +08:00
2019-01-13 03:25:45 +08:00
return ( ICustomObject ) self ;
2018-12-23 16:53:43 +08:00
}
2019-01-09 14:15:58 +08:00
2019-01-10 03:41:40 +08:00
public override Dictionary < string , string > getAdditionalSaveData ( )
{
Dictionary < string , string > saveData = base . getAdditionalSaveData ( ) ;
2019-01-10 18:31:23 +08:00
saveData . Add ( "ParentID" , this . containerObject . info . id ) ;
2019-01-10 03:41:40 +08:00
saveData . Add ( "offsetKeyX" , this . offsetKey . X . ToString ( ) ) ;
saveData . Add ( "offsetKeyY" , this . offsetKey . Y . ToString ( ) ) ;
string saveLocation = "" ;
if ( this . location = = null )
{
2019-01-13 03:25:45 +08:00
//Revitalize.ModCore.log("WHY IS LOCTION NULL???");
2019-01-10 03:41:40 +08:00
saveLocation = "" ;
}
else
{
if ( ! string . IsNullOrEmpty ( this . location . uniqueName . Value ) ) saveLocation = this . location . uniqueName . Value ;
else
{
saveLocation = this . location . Name ;
}
}
2019-01-10 18:31:23 +08:00
2019-01-10 03:41:40 +08:00
saveData . Add ( "GameLocationName" , saveLocation ) ;
saveData . Add ( "Rotation" , ( ( int ) this . info . facingDirection ) . ToString ( ) ) ;
2019-01-11 04:44:10 +08:00
saveData . Add ( "ParentGUID" , this . containerObject . guid . ToString ( ) ) ;
saveData . Add ( "GUID" , this . guid . ToString ( ) ) ;
2019-08-28 06:10:56 +08:00
if ( this . containerObject . childrenGuids . ContainsKey ( this . offsetKey ) )
{
Revitalize . ModCore . Serializer . SerializeGUID ( this . containerObject . childrenGuids [ this . offsetKey ] . ToString ( ) , this ) ;
}
2019-08-28 07:47:22 +08:00
2019-08-22 10:06:17 +08:00
this . containerObject . getAdditionalSaveData ( ) ;
2019-01-10 03:41:40 +08:00
return saveData ;
}
2019-01-09 20:03:27 +08:00
protected string recreateParentId ( string id )
{
StringBuilder b = new StringBuilder ( ) ;
string [ ] splits = id . Split ( '.' ) ;
for ( int i = 0 ; i < splits . Length - 1 ; i + + )
{
b . Append ( splits [ i ] ) ;
if ( i = = splits . Length - 2 ) continue ;
b . Append ( "." ) ;
}
return b . ToString ( ) ;
}
2019-01-09 14:15:58 +08:00
/// <summary>What happens when the object is drawn at a tile location.</summary>
public override void draw ( SpriteBatch spriteBatch , int x , int y , float alpha = 1f )
{
2019-08-28 06:10:56 +08:00
this . updateInfo ( ) ;
2019-01-21 15:34:11 +08:00
if ( this . info . ignoreBoundingBox = = true )
2019-01-09 14:15:58 +08:00
{
2019-01-21 15:34:11 +08:00
x * = - 1 ;
y * = - 1 ;
2019-01-09 14:15:58 +08:00
}
2019-01-21 15:34:11 +08:00
if ( this . info = = null )
2019-01-09 14:15:58 +08:00
{
2019-01-21 15:34:11 +08:00
Revitalize . ModCore . log ( "info is null" ) ;
if ( this . syncObject = = null ) Revitalize . ModCore . log ( "DEAD SYNC" ) ;
}
if ( this . animationManager = = null ) Revitalize . ModCore . log ( "Animation Manager Null" ) ;
if ( this . displayTexture = = null ) Revitalize . ModCore . log ( "Display texture is null" ) ;
2019-01-09 14:15:58 +08:00
//The actual planter box being drawn.
if ( this . animationManager = = null )
{
if ( this . animationManager . getExtendedTexture ( ) = = null )
ModCore . ModMonitor . Log ( "Tex Extended is null???" ) ;
2019-09-19 08:33:45 +08:00
spriteBatch . Draw ( this . displayTexture , Game1 . GlobalToLocal ( Game1 . viewport , new Vector2 ( ( float ) ( x * Game1 . tileSize ) , y * Game1 . tileSize ) ) , new Rectangle ? ( this . animationManager . currentAnimation . sourceRectangle ) , this . info . DrawColor * alpha , 0f , Vector2 . Zero , ( float ) Game1 . pixelZoom , this . flipped ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0f , ( float ) ( y * Game1 . tileSize ) / 10000f ) ) ;
2019-01-09 14:15:58 +08:00
// Log.AsyncG("ANIMATION IS NULL?!?!?!?!");
}
else
{
//Log.AsyncC("Animation Manager is working!");
float addedDepth = 0 ;
if ( Revitalize . ModCore . playerInfo . sittingInfo . SittingObject = = this . containerObject & & this . info . facingDirection = = Enums . Direction . Up )
{
addedDepth + = ( this . containerObject . Height - 1 ) - ( ( int ) ( this . offsetKey . Y ) ) ;
if ( this . info . ignoreBoundingBox ) addedDepth + = 1.5f ;
}
2019-01-14 06:46:31 +08:00
else if ( this . info . ignoreBoundingBox )
{
addedDepth + = 1.0f ;
}
2019-09-19 08:33:45 +08:00
this . animationManager . draw ( spriteBatch , this . displayTexture , Game1 . GlobalToLocal ( Game1 . viewport , new Vector2 ( ( float ) ( x * Game1 . tileSize ) , y * Game1 . tileSize ) ) , new Rectangle ? ( this . animationManager . currentAnimation . sourceRectangle ) , this . info . DrawColor * alpha , 0f , Vector2 . Zero , ( float ) Game1 . pixelZoom , this . flipped ? SpriteEffects . FlipHorizontally : SpriteEffects . None , Math . Max ( 0f , ( float ) ( ( y + addedDepth ) * Game1 . tileSize ) / 10000f ) + . 00001f ) ;
2019-01-09 14:15:58 +08:00
try
{
this . animationManager . tickAnimation ( ) ;
// Log.AsyncC("Tick animation");
}
catch ( Exception err )
{
ModCore . ModMonitor . Log ( err . ToString ( ) ) ;
}
}
// spriteBatch.Draw(Game1.mouseCursors, Game1.GlobalToLocal(Game1.viewport, new Vector2((float)((double)tileLocation.X * (double)Game1.tileSize + (((double)tileLocation.X * 11.0 + (double)tileLocation.Y * 7.0) % 10.0 - 5.0)) + (float)(Game1.tileSize / 2), (float)((double)tileLocation.Y * (double)Game1.tileSize + (((double)tileLocation.Y * 11.0 + (double)tileLocation.X * 7.0) % 10.0 - 5.0)) + (float)(Game1.tileSize / 2))), new Rectangle?(new Rectangle((int)((double)tileLocation.X * 51.0 + (double)tileLocation.Y * 77.0) % 3 * 16, 128 + this.whichForageCrop * 16, 16, 16)), Color.White, 0.0f, new Vector2(8f, 8f), (float)Game1.pixelZoom, SpriteEffects.None, (float)(((double)tileLocation.Y * (double)Game1.tileSize + (double)(Game1.tileSize / 2) + (((double)tileLocation.Y * 11.0 + (double)tileLocation.X * 7.0) % 10.0 - 5.0)) / 10000.0));
2019-01-21 15:34:11 +08:00
2019-01-09 14:15:58 +08:00
}
2019-09-12 05:40:22 +08:00
public override void drawFullyInMenu ( SpriteBatch spriteBatch , Vector2 objectPosition , float Depth )
{
this . updateInfo ( ) ;
if ( this . animationManager = = null )
{
Revitalize . ModCore . log ( "Animation Manager Null" ) ;
}
if ( this . displayTexture = = null ) Revitalize . ModCore . log ( "Display texture is null" ) ;
2019-09-19 08:33:45 +08:00
spriteBatch . Draw ( this . displayTexture , objectPosition , this . animationManager . currentAnimation . sourceRectangle , this . info . DrawColor , 0f , Vector2 . Zero , ( float ) Game1 . pixelZoom , SpriteEffects . None , Depth ) ;
2019-09-12 05:40:22 +08:00
//base.drawWhenHeld(spriteBatch, objectPosition, f);
}
2019-08-28 06:10:56 +08:00
public override void updateInfo ( )
{
2019-08-28 07:47:22 +08:00
if ( this . info = = null | | this . containerObject = = null )
2019-08-28 06:10:56 +08:00
{
2019-08-28 07:47:22 +08:00
this . ItemInfo = this . text ;
2019-09-22 15:18:48 +08:00
2019-08-28 10:42:05 +08:00
//ModCore.log("Updated item info!");
2019-08-28 07:47:22 +08:00
return ;
2019-08-28 06:10:56 +08:00
}
2019-08-28 07:47:22 +08:00
if ( this . requiresUpdate ( ) )
{
2019-08-29 03:29:51 +08:00
//this.ItemInfo = this.text;
2019-08-28 07:47:22 +08:00
this . text = this . ItemInfo ;
this . info . cleanAfterUpdate ( ) ;
2019-08-29 03:29:51 +08:00
MultiplayerUtilities . RequestUpdateSync ( this . guid ) ;
2019-08-28 07:47:22 +08:00
}
}
2019-09-10 04:31:55 +08:00
/// <summary>
/// Gets a list of neighboring tiled objects that produce or transfer energy. This should be used for machines/objects that consume or transfer energy
/// </summary>
/// <returns></returns>
protected virtual List < MultiTiledComponent > GetNeighboringOutputEnergySources ( )
{
Vector2 tileLocation = this . TileLocation ;
List < MultiTiledComponent > customObjects = new List < MultiTiledComponent > ( ) ;
if ( this . location ! = null )
{
for ( int i = - 1 ; i < = 1 ; i + + )
{
for ( int j = - 1 ; j < = 1 ; j + + )
{
if ( i = = j | | i = = ( - j ) ) continue ;
Vector2 neighborTile = tileLocation + new Vector2 ( i , j ) ;
if ( this . location . isObjectAtTile ( ( int ) neighborTile . X , ( int ) neighborTile . Y ) )
{
StardewValley . Object obj = this . location . getObjectAtTile ( ( int ) neighborTile . X , ( int ) neighborTile . Y ) ;
if ( obj is MultiTiledComponent )
{
2019-09-22 15:18:48 +08:00
if ( ( obj as MultiTiledComponent ) . GetEnergyManager ( ) . energyInteractionType = = Enums . EnergyInteractionType . Produces | | ( obj as MultiTiledComponent ) . GetEnergyManager ( ) . energyInteractionType = = Enums . EnergyInteractionType . Transfers | | ( obj as MultiTiledComponent ) . GetEnergyManager ( ) . energyInteractionType = = Enums . EnergyInteractionType . Storage )
2019-09-10 04:31:55 +08:00
{
2019-09-26 06:02:58 +08:00
if ( ( obj as MultiTiledComponent ) . containerObject = = this . containerObject ) continue ;
2019-09-10 04:31:55 +08:00
customObjects . Add ( ( MultiTiledComponent ) obj ) ;
}
}
else continue ;
}
}
}
}
return customObjects ;
}
/// <summary>
/// Gets a list of neighboring tiled objects that consume or transfer energy. This should be used for machines/objects that produce or transfer energy
/// </summary>
/// <returns></returns>
protected virtual List < MultiTiledComponent > GetNeighboringInputEnergySources ( )
{
Vector2 tileLocation = this . TileLocation ;
List < MultiTiledComponent > customObjects = new List < MultiTiledComponent > ( ) ;
if ( this . location ! = null )
{
for ( int i = - 1 ; i < = 1 ; i + + )
{
for ( int j = - 1 ; j < = 1 ; j + + )
{
if ( i = = j | | i = = ( - j ) ) continue ;
Vector2 neighborTile = tileLocation + new Vector2 ( i , j ) ;
if ( this . location . isObjectAtTile ( ( int ) neighborTile . X , ( int ) neighborTile . Y ) )
{
StardewValley . Object obj = this . location . getObjectAtTile ( ( int ) neighborTile . X , ( int ) neighborTile . Y ) ;
if ( obj is MultiTiledComponent )
{
2019-09-22 15:18:48 +08:00
if ( ( obj as MultiTiledComponent ) . GetEnergyManager ( ) . energyInteractionType = = Enums . EnergyInteractionType . Consumes | | ( obj as MultiTiledComponent ) . GetEnergyManager ( ) . energyInteractionType = = Enums . EnergyInteractionType . Transfers | | ( obj as MultiTiledComponent ) . GetEnergyManager ( ) . energyInteractionType = = Enums . EnergyInteractionType . Storage )
2019-09-10 04:31:55 +08:00
{
2019-09-26 06:02:58 +08:00
if ( ( obj as MultiTiledComponent ) . containerObject = = this . containerObject ) continue ;
2019-09-10 04:31:55 +08:00
customObjects . Add ( ( MultiTiledComponent ) obj ) ;
}
}
else continue ;
}
}
}
}
return customObjects ;
}
/// <summary>
/// Gets the appropriate energy neighbors to move energy around from/to.
/// </summary>
/// <returns></returns>
protected virtual List < MultiTiledComponent > getAppropriateEnergyNeighbors ( )
{
2019-09-22 15:18:48 +08:00
if ( this . GetEnergyManager ( ) . consumesEnergy )
2019-09-10 04:31:55 +08:00
{
return this . GetNeighboringOutputEnergySources ( ) ;
}
2019-09-22 15:18:48 +08:00
else if ( this . GetEnergyManager ( ) . producesEnergy )
2019-09-10 04:31:55 +08:00
{
return this . GetNeighboringInputEnergySources ( ) ;
}
2019-09-22 15:18:48 +08:00
else if ( this . GetEnergyManager ( ) . transfersEnergy )
2019-09-10 04:31:55 +08:00
{
List < MultiTiledComponent > objs = new List < MultiTiledComponent > ( ) ;
objs . AddRange ( this . GetNeighboringInputEnergySources ( ) ) ;
objs . AddRange ( this . GetNeighboringOutputEnergySources ( ) ) ;
return objs ;
}
return new List < MultiTiledComponent > ( ) ;
}
/// <summary>
/// Gets all of the energy nodes in a network that are either producers or is storage.
/// </summary>
/// <returns></returns>
protected virtual List < MultiTiledObject > EnergyGraphSearchSources ( )
{
List < MultiTiledObject > energySources = new List < MultiTiledObject > ( ) ;
List < MultiTiledComponent > searchedComponents = new List < MultiTiledComponent > ( ) ;
List < MultiTiledComponent > entitiesToSearch = new List < MultiTiledComponent > ( ) ;
entitiesToSearch . AddRange ( this . getAppropriateEnergyNeighbors ( ) ) ;
searchedComponents . Add ( this ) ;
while ( entitiesToSearch . Count > 0 )
{
MultiTiledComponent searchComponent = entitiesToSearch [ 0 ] ;
entitiesToSearch . Remove ( searchComponent ) ;
if ( searchedComponents . Contains ( searchComponent ) )
{
continue ;
}
else
{
searchedComponents . Add ( searchComponent ) ;
entitiesToSearch . AddRange ( searchComponent . getAppropriateEnergyNeighbors ( ) ) ;
if ( searchComponent . containerObject . info . EnergyManager . energyInteractionType = = Enums . EnergyInteractionType . Produces | | searchComponent . containerObject . info . EnergyManager . energyInteractionType = = Enums . EnergyInteractionType . Storage )
{
energySources . Add ( searchComponent . containerObject ) ;
}
}
}
return energySources ;
}
/// <summary>
/// Gets all of the energy nodes in a network that are either consumers or storage. This should ALWAYS be ran after EnergyGraphSearchSources
/// </summary>
/// <returns></returns>
protected virtual List < MultiTiledObject > EnergyGraphSearchConsumers ( )
{
List < MultiTiledObject > energySources = new List < MultiTiledObject > ( ) ;
List < MultiTiledComponent > searchedComponents = new List < MultiTiledComponent > ( ) ;
List < MultiTiledComponent > entitiesToSearch = new List < MultiTiledComponent > ( ) ;
entitiesToSearch . AddRange ( this . getAppropriateEnergyNeighbors ( ) ) ;
searchedComponents . Add ( this ) ;
while ( entitiesToSearch . Count > 0 )
{
MultiTiledComponent searchComponent = entitiesToSearch [ 0 ] ;
entitiesToSearch . Remove ( searchComponent ) ;
if ( searchedComponents . Contains ( searchComponent ) )
{
continue ;
}
else
{
searchedComponents . Add ( searchComponent ) ;
entitiesToSearch . AddRange ( searchComponent . getAppropriateEnergyNeighbors ( ) ) ;
if ( searchComponent . containerObject . info . EnergyManager . energyInteractionType = = Enums . EnergyInteractionType . Consumes | | searchComponent . containerObject . info . EnergyManager . energyInteractionType = = Enums . EnergyInteractionType . Storage )
{
energySources . Add ( searchComponent . containerObject ) ;
}
}
}
return energySources ;
}
/// <summary>
/// Gets all nodes in a connected energy network and tries to drain the necessary amount of energy from the network.
/// </summary>
public void drainEnergyFromNetwork ( )
{
//Machines that consume should ALWAYS try to drain energy from a network first.
//Then producers should always try to store energy to a network.
//Storage should never try to push or pull energy from a network as consumers will pull from storage and producers will push to storage.
//Transfer nodes are used just to connect the network.
List < MultiTiledObject > energySources = this . EnergyGraphSearchSources ( ) ;
int index = 0 ;
for ( int i = 0 ; i < energySources . Count ; i + + )
{
2019-09-22 15:18:48 +08:00
this . GetEnergyManager ( ) . transferEnergyFromAnother ( energySources [ i ] . GetEnergyManager ( ) , this . GetEnergyManager ( ) . capacityRemaining ) ;
if ( this . GetEnergyManager ( ) . hasMaxEnergy ) break ;
2019-09-10 04:31:55 +08:00
}
}
2019-09-10 06:44:25 +08:00
public void drainEnergyFromNetwork ( List < MultiTiledObject > energySources )
{
int index = 0 ;
for ( int i = 0 ; i < energySources . Count ; i + + )
{
2019-09-22 15:18:48 +08:00
this . GetEnergyManager ( ) . transferEnergyFromAnother ( energySources [ i ] . GetEnergyManager ( ) , this . GetEnergyManager ( ) . capacityRemaining ) ;
if ( this . GetEnergyManager ( ) . hasMaxEnergy ) break ;
2019-09-10 06:44:25 +08:00
}
}
2019-09-10 04:31:55 +08:00
/// <summary>
/// Gets all of the nodes in a connected energy network and tries to store the necessary amount of energy from the network.
/// </summary>
public void storeEnergyToNetwork ( )
{
List < MultiTiledObject > energySources = this . EnergyGraphSearchConsumers ( ) ;
int index = 0 ;
for ( int i = 0 ; i < energySources . Count ; i + + )
{
2019-09-22 15:18:48 +08:00
this . GetEnergyManager ( ) . transferEnergyToAnother ( energySources [ i ] . GetEnergyManager ( ) , this . GetEnergyManager ( ) . capacityRemaining ) ;
if ( this . GetEnergyManager ( ) . hasEnergy = = false ) break ;
2019-09-20 05:44:46 +08:00
}
}
public void storeEnergyToNetwork ( List < MultiTiledObject > energySources )
{
int index = 0 ;
for ( int i = 0 ; i < energySources . Count ; i + + )
{
2019-09-22 15:18:48 +08:00
this . GetEnergyManager ( ) . transferEnergyToAnother ( energySources [ i ] . GetEnergyManager ( ) , this . GetEnergyManager ( ) . capacityRemaining ) ;
if ( this . GetEnergyManager ( ) . hasEnergy = = false ) break ;
}
}
public override ref EnergyManager GetEnergyManager ( )
{
if ( this . info = = null | | this . containerObject = = null )
{
this . updateInfo ( ) ;
if ( this . containerObject = = null ) return ref this . info . EnergyManager ;
return ref this . containerObject . info . EnergyManager ;
}
return ref this . containerObject . info . EnergyManager ;
}
public override void SetEnergyManager ( ref EnergyManager Manager )
{
this . info . EnergyManager = Manager ;
}
public override ref InventoryManager GetInventoryManager ( )
{
if ( this . info = = null | | this . containerObject = = null )
{
this . updateInfo ( ) ;
if ( this . containerObject = = null )
{
return ref this . info . inventory ;
}
return ref this . containerObject . info . inventory ;
}
return ref this . containerObject . info . inventory ;
}
public override void SetInventoryManager ( InventoryManager Manager )
{
this . info . inventory = Manager ;
this . containerObject . info . inventory = Manager ;
}
2019-09-24 09:13:45 +08:00
public override ref FluidManagerV2 GetFluidManager ( )
{
if ( this . info = = null | | this . containerObject = = null )
{
this . updateInfo ( ) ;
if ( this . containerObject = = null ) return ref this . info . fluidManager ;
return ref this . containerObject . info . fluidManager ;
}
return ref this . containerObject . info . fluidManager ;
}
public override void SetFluidManager ( FluidManagerV2 FluidManager )
{
this . info . fluidManager = FluidManager ;
}
/// <summary>
/// Gets corresponding neighbor objects that can interact with fluid.
/// </summary>
/// <returns></returns>
protected virtual List < MultiTiledComponent > GetNeighboringFluidManagers ( )
{
Vector2 tileLocation = this . TileLocation ;
List < MultiTiledComponent > customObjects = new List < MultiTiledComponent > ( ) ;
if ( this . location ! = null )
{
for ( int i = - 1 ; i < = 1 ; i + + )
{
for ( int j = - 1 ; j < = 1 ; j + + )
{
if ( i = = j | | i = = ( - j ) ) continue ;
Vector2 neighborTile = tileLocation + new Vector2 ( i , j ) ;
if ( this . location . isObjectAtTile ( ( int ) neighborTile . X , ( int ) neighborTile . Y ) )
{
StardewValley . Object obj = this . location . getObjectAtTile ( ( int ) neighborTile . X , ( int ) neighborTile . Y ) ;
if ( obj is MultiTiledComponent )
{
2019-09-25 08:31:33 +08:00
2019-09-24 09:13:45 +08:00
if ( ( obj as MultiTiledComponent ) . GetFluidManager ( ) . InteractsWithFluids )
{
2019-09-26 06:02:58 +08:00
if ( ( obj as MultiTiledComponent ) . containerObject = = this . containerObject ) continue ;
2019-09-24 09:13:45 +08:00
customObjects . Add ( ( MultiTiledComponent ) obj ) ;
2019-09-25 08:31:33 +08:00
//ModCore.log("Found a neighboring fluid manager");
}
else
{
2019-09-26 06:02:58 +08:00
//ModCore.log("Found a neighboring object but it isn't a valid fluid manager.");
2019-09-24 09:13:45 +08:00
}
}
else continue ;
}
}
}
}
return customObjects ;
}
/// <summary>
/// Searches a network of fluid managers to see if any of these fluid managers have an output tank with the corresponding fluid.
/// </summary>
/// <param name="L"></param>
/// <returns></returns>
protected virtual List < MultiTiledObject > FluidGraphSearchForFluidFromOutputTanks ( Fluid L )
{
List < MultiTiledObject > fluidSources = new List < MultiTiledObject > ( ) ;
2019-10-04 14:42:16 +08:00
HashSet < Guid > searchedComponents = new HashSet < Guid > ( ) ;
Queue < MultiTiledComponent > entitiesToSearch = new Queue < MultiTiledComponent > ( ) ;
HashSet < Guid > searchedObjects = new HashSet < Guid > ( ) ;
foreach ( MultiTiledComponent tile in this . GetNeighboringFluidManagers ( ) )
{
entitiesToSearch . Enqueue ( tile ) ;
}
//entitiesToSearch.AddRange(this.GetNeighboringFluidManagers());
searchedComponents . Add ( this . guid ) ;
2019-09-24 09:13:45 +08:00
while ( entitiesToSearch . Count > 0 )
{
2019-10-04 14:42:16 +08:00
MultiTiledComponent searchComponent = entitiesToSearch . Dequeue ( ) ;
//entitiesToSearch.Remove(searchComponent);
if ( searchedComponents . Contains ( searchComponent . guid ) )
{
continue ;
}
/ *
else if ( searchedObjects . Contains ( searchComponent . containerObject ) )
2019-09-24 09:13:45 +08:00
{
continue ;
}
2019-10-04 14:42:16 +08:00
* /
2019-09-24 09:13:45 +08:00
else
{
2019-10-04 14:42:16 +08:00
searchedComponents . Add ( searchComponent . guid ) ;
searchedObjects . Add ( searchComponent . containerObject . guid ) ;
List < MultiTiledComponent > neighbors = searchComponent . GetNeighboringFluidManagers ( ) ;
foreach ( MultiTiledComponent tile in neighbors )
{
if ( searchedObjects . Contains ( tile . containerObject . guid ) | | searchedComponents . Contains ( tile . guid ) ) continue ;
else
{
entitiesToSearch . Enqueue ( tile ) ;
}
}
2019-09-24 09:13:45 +08:00
if ( searchComponent . containerObject . info . fluidManager . doesThisOutputTankContainThisFluid ( L ) )
{
fluidSources . Add ( searchComponent . containerObject ) ;
2019-09-25 08:31:33 +08:00
//ModCore.log("Found a tank that contains this fluid!");
2019-09-24 09:13:45 +08:00
}
}
}
return fluidSources ;
}
protected virtual List < MultiTiledObject > FluidGraphSearchInputTanksThatCanAcceptThisFluid ( Fluid L )
{
List < MultiTiledObject > fluidSources = new List < MultiTiledObject > ( ) ;
List < MultiTiledComponent > searchedComponents = new List < MultiTiledComponent > ( ) ;
List < MultiTiledComponent > entitiesToSearch = new List < MultiTiledComponent > ( ) ;
entitiesToSearch . AddRange ( this . GetNeighboringFluidManagers ( ) ) ;
searchedComponents . Add ( this ) ;
while ( entitiesToSearch . Count > 0 )
{
MultiTiledComponent searchComponent = entitiesToSearch [ 0 ] ;
entitiesToSearch . Remove ( searchComponent ) ;
if ( searchedComponents . Contains ( searchComponent ) )
{
continue ;
}
else
{
searchedComponents . Add ( searchComponent ) ;
entitiesToSearch . AddRange ( searchComponent . GetNeighboringFluidManagers ( ) ) ;
if ( searchComponent . containerObject . info . fluidManager . canRecieveThisFluid ( L ) )
{
fluidSources . Add ( searchComponent . containerObject ) ;
}
}
}
return fluidSources ;
}
/// <summary>
/// Searches for output tanks that have the corresponding fluid and tries to drain from them.
/// </summary>
/// <param name="L"></param>
public void pullFluidFromNetworkOutputs ( Fluid L )
{
List < MultiTiledObject > energySources = this . FluidGraphSearchForFluidFromOutputTanks ( L ) ;
int index = 0 ;
for ( int i = 0 ; i < energySources . Count ; i + + )
{
FluidManagerV2 other = energySources [ i ] . GetFluidManager ( ) ;
other . outputFluidToOtherSources ( this . GetFluidManager ( ) ) ;
if ( this . GetFluidManager ( ) . canRecieveThisFluid ( L ) = = false ) break ; //Since we already check for valid tanks this will basically check again to see if the tanks are full.
}
}
/// <summary>
/// Searches for output tanks that have the corresponding fluid and tries to drain from them.
/// </summary>
/// <param name="L"></param>
/// <param name="FluidSources"></param>
public void pullFluidFromNetworkOutputs ( List < MultiTiledObject > FluidSources , Fluid L )
{
List < MultiTiledObject > energySources = FluidSources ;
int index = 0 ;
for ( int i = 0 ; i < energySources . Count ; i + + )
{
FluidManagerV2 other = energySources [ i ] . GetFluidManager ( ) ;
other . outputFluidToOtherSources ( this . GetFluidManager ( ) ) ;
if ( this . GetFluidManager ( ) . canRecieveThisFluid ( L ) = = false ) break ; //Since we already check for valid tanks this will basically check again to see if the tanks are full.
}
}
2019-09-22 15:18:48 +08:00
public override bool requiresUpdate ( )
{
if ( this . info . requiresSyncUpdate ( ) | | this . containerObject . info . requiresSyncUpdate ( ) )
{
return true ;
}
else
{
return false ;
2019-09-10 04:31:55 +08:00
}
}
2018-12-23 16:53:43 +08:00
}
}