diff --git a/GeneralMods/StardustCore/ModCore.cs b/GeneralMods/StardustCore/ModCore.cs
index 2008f0b5..3ac57511 100644
--- a/GeneralMods/StardustCore/ModCore.cs
+++ b/GeneralMods/StardustCore/ModCore.cs
@@ -3,7 +3,9 @@ using Microsoft.Xna.Framework.Input;
using StardewModdingAPI;
using StardewValley;
using StardewValley.Menus;
+using StardewValley.Network;
using StardustCore.ModInfo;
+using StardustCore.NetCode;
using StardustCore.Objects;
using StardustCore.Objects.Tools;
using StardustCore.Serialization;
@@ -13,6 +15,7 @@ using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Reflection;
using System.Text;
using System.Threading.Tasks;
@@ -25,6 +28,9 @@ namespace StardustCore
public static Serialization.SerializationManager SerializationManager;
public static UIUtilities.TextureManager TextureManager;
+ public static Multiplayer multiplayer;
+ bool serverHack;
+
public static string ContentDirectory;
public override void Entry(IModHelper helper)
{
@@ -51,18 +57,88 @@ namespace StardustCore
SerializationManager.initializeDefaultSuportedTypes();
TextureManager = new TextureManager();
-
+ TextureManager.addTexture("Test1.png", new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test1.png")));
StardewModdingAPI.Events.ControlEvents.KeyPressed += ControlEvents_KeyPressed;
StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
+ serverHack = false;
+
+ }
+
+ ///
+ /// Returns the value of the data snagged by reflection.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static object GetInstanceField(Type type, object instance, string fieldName)
+ {
+ BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static;
+ FieldInfo field = type.GetField(fieldName, bindFlags);
+ /*
+ FieldInfo[] meh = type.GetFields(bindFlags);
+ foreach(var v in meh)
+ {
+ if (v.Name == null)
+ {
+ continue;
+ }
+ Monitor.Log(v.Name);
+ }
+ */
+ return field.GetValue(instance);
+ }
+
+ public static void SetInstanceField(Type type, object instance, object value, string fieldName)
+ {
+ BindingFlags bindFlags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic
+ | BindingFlags.Static;
+ FieldInfo field = type.GetField(fieldName, bindFlags);
+ field.SetValue(instance, value);
+ return;
}
private void GameEvents_UpdateTick(object sender, EventArgs e)
{
+ if (Game1.activeClickableMenu != null)
+ {
+ if(Game1.activeClickableMenu is StardewValley.Menus.TitleMenu)
+ {
+ if (TitleMenu.subMenu == null) return;
+ if (TitleMenu.subMenu.GetType() == typeof(FarmhandMenu))
+ {
+ if ((TitleMenu.subMenu as FarmhandMenu).client.GetType() != typeof(ModdedClient))
+ {
+ ModCore.ModMonitor.Log("OK!");
+ multiplayer = (Multiplayer)GetInstanceField(typeof(Game1), Program.gamePtr, "multiplayer");
+ ModCore.ModMonitor.Log("CODE!!!!!!!");
+ string address = (string)GetInstanceField(typeof(LidgrenClient), (TitleMenu.subMenu as FarmhandMenu).client, "address");
+ (TitleMenu.subMenu as FarmhandMenu).client = new NetCode.ModdedClient(address);
+ }
+ }
+ }
+ }
+ if (Game1.server!=null&& serverHack==false)
+ {
+ ModCore.ModMonitor.Log("OK!");
+ multiplayer = (Multiplayer)GetInstanceField(typeof(Game1), Program.gamePtr, "multiplayer");
+ //List servers = Helper.Reflection.GetField>(Game1.server, "servers", true).GetValue();
+ NetCode.GameServer server = new NetCode.GameServer();
+ Game1.server.stopServer();
+ Game1.server = server;
+ server.startServer();
+
+ serverHack = true;
+ }
+ if (Game1.client !=null && serverHack == false)
+ {
+
+ }
}
private void ControlEvents_KeyPressed(object sender, StardewModdingAPI.Events.EventArgsKeyPressed e)
@@ -95,6 +171,7 @@ namespace StardustCore
// Game1.player.addItemToInventory(collection);
CoreObject tile1 = new CoreObject(new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test1.png")),3, Vector2.Zero,9);
+
tile1.description = "Hello";
tile1.Name = "test";
tile1.displayName = "test";
diff --git a/GeneralMods/StardustCore/NetCode/ModdedClient.cs b/GeneralMods/StardustCore/NetCode/ModdedClient.cs
new file mode 100644
index 00000000..23f5bdcd
--- /dev/null
+++ b/GeneralMods/StardustCore/NetCode/ModdedClient.cs
@@ -0,0 +1,165 @@
+using System;
+using System.IO;
+using Lidgren.Network;
+using StardewValley;
+using StardewValley.Network;
+
+namespace StardustCore.NetCode
+{
+ public class ModdedClient : Client
+ {
+ private string address;
+ private NetClient client;
+ private bool serverDiscovered;
+
+ public ModdedClient(string address)
+ {
+ this.address = address;
+ }
+
+ public override string getUserID()
+ {
+ return "";
+ }
+
+ protected override string getHostUserName()
+ {
+ return this.client.ServerConnection.RemoteEndPoint.Address.ToString();
+ }
+
+ protected override void connectImpl()
+ {
+ NetPeerConfiguration config = new NetPeerConfiguration("StardewValley");
+ config.EnableMessageType(NetIncomingMessageType.DiscoveryResponse);
+ config.ConnectionTimeout = 30f;
+ config.PingInterval = 5f;
+ config.MaximumTransmissionUnit = 1200;
+ this.client = new NetClient(config);
+ this.client.Start();
+ int serverPort = 24642;
+ if (this.address.Contains(":"))
+ {
+ string[] strArray = this.address.Split(':');
+ this.address = strArray[0];
+ serverPort = Convert.ToInt32(strArray[1]);
+ }
+ this.client.DiscoverKnownPeer(this.address, serverPort);
+ }
+
+ public override void disconnect(bool neatly = true)
+ {
+ if (this.client.ConnectionStatus != NetConnectionStatus.Disconnected && this.client.ConnectionStatus != NetConnectionStatus.Disconnecting)
+ {
+ if (neatly)
+ this.sendMessage(new OutgoingMessage((byte)19, Game1.player, new object[0]));
+ this.client.FlushSendQueue();
+ this.client.Disconnect("");
+ this.client.FlushSendQueue();
+ }
+ this.connectionMessage = (string)null;
+ }
+
+ protected virtual bool validateProtocol(string version)
+ {
+ return version ==ModCore.multiplayer.protocolVersion;
+ }
+
+ protected override void receiveMessagesImpl()
+ {
+ NetIncomingMessage netIncomingMessage;
+ while ((netIncomingMessage = this.client.ReadMessage()) != null)
+ {
+ switch (netIncomingMessage.MessageType)
+ {
+ case NetIncomingMessageType.StatusChanged:
+ this.statusChanged(netIncomingMessage);
+ continue;
+ case NetIncomingMessageType.Data:
+ this.parseDataMessageFromServer(netIncomingMessage);
+ continue;
+ case NetIncomingMessageType.DiscoveryResponse:
+ Console.WriteLine("Found server at " + (object)netIncomingMessage.SenderEndPoint);
+ if (this.validateProtocol(netIncomingMessage.ReadString()))
+ {
+ this.serverName = netIncomingMessage.ReadString();
+ this.receiveHandshake(netIncomingMessage);
+ this.serverDiscovered = true;
+ continue;
+ }
+ this.connectionMessage = "Strings\\UI:CoopMenu_FailedProtocolVersion";
+ this.client.Disconnect("");
+ continue;
+ case NetIncomingMessageType.DebugMessage:
+ case NetIncomingMessageType.WarningMessage:
+ case NetIncomingMessageType.ErrorMessage:
+ string str = netIncomingMessage.ReadString();
+ Console.WriteLine("{0}: {1}", (object)netIncomingMessage.MessageType, (object)str);
+ Game1.debugOutput = str;
+ continue;
+ default:
+ continue;
+ }
+ }
+ if (this.client.ServerConnection == null || DateTime.Now.Second % 2 != 0)
+ return;
+ Game1.debugOutput = "Ping: " + (object)(float)((double)this.client.ServerConnection.AverageRoundtripTime * 1000.0) + "ms";
+ }
+
+ private void receiveHandshake(NetIncomingMessage msg)
+ {
+ this.client.Connect(msg.SenderEndPoint.Address.ToString(), msg.SenderEndPoint.Port);
+ }
+
+ private void statusChanged(NetIncomingMessage message)
+ {
+ switch ((NetConnectionStatus)message.ReadByte())
+ {
+ case NetConnectionStatus.Disconnecting:
+ case NetConnectionStatus.Disconnected:
+ this.clientRemotelyDisconnected();
+ break;
+ }
+ }
+
+ private void clientRemotelyDisconnected()
+ {
+ this.timedOut = true;
+ }
+
+ public override void sendMessage(OutgoingMessage message)
+ {
+ NetOutgoingMessage message1 = this.client.CreateMessage();
+ using (NetBufferWriteStream bufferWriteStream = new NetBufferWriteStream((NetBuffer)message1))
+ {
+ using (BinaryWriter writer = new BinaryWriter((Stream)bufferWriteStream))
+ message.Write(writer);
+ }
+ int num = (int)this.client.SendMessage(message1, NetDeliveryMethod.ReliableOrdered);
+ }
+
+ private void parseDataMessageFromServer(NetIncomingMessage dataMsg)
+ {
+ using (IncomingMessage message = new IncomingMessage())
+ {
+ using (NetBufferReadStream bufferReadStream = new NetBufferReadStream((NetBuffer)dataMsg))
+ {
+ using (BinaryReader reader = new BinaryReader((Stream)bufferReadStream))
+ {
+ while ((long)dataMsg.LengthBits - dataMsg.Position >= 8L)
+ {
+ message.Read(reader);
+ try
+ {
+ this.processIncomingMessage(message);
+ }
+ catch(Exception err)
+ {
+
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/GeneralMods/StardustCore/NetCode/ModdedGameServer.cs b/GeneralMods/StardustCore/NetCode/ModdedGameServer.cs
new file mode 100644
index 00000000..6868e7fd
--- /dev/null
+++ b/GeneralMods/StardustCore/NetCode/ModdedGameServer.cs
@@ -0,0 +1,424 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Xml.Serialization;
+using Microsoft.Xna.Framework;
+using Netcode;
+using StardewValley;
+using StardewValley.Buildings;
+using StardewValley.Locations;
+using StardewValley.Minigames;
+using StardewValley.Network;
+
+namespace StardustCore.NetCode
+{
+ public class GameServer : IGameServer
+ {
+ public List servers = new List();
+ public List pendingGameAvailableActions = new List();
+
+ public GameServer()
+ {
+ this.servers.Add(ModCore.multiplayer.InitServer((Server)new LidgrenServer((IGameServer)this)));
+ if (Program.sdk.Networking == null)
+ return;
+ this.servers.Add(Program.sdk.Networking.CreateServer((IGameServer)this));
+ }
+
+ public int connectionsCount
+ {
+ get
+ {
+ return this.servers.Sum((Func)(s => s.connectionsCount));
+ }
+ }
+
+ public string getInviteCode()
+ {
+ foreach (Server server in this.servers)
+ {
+ string inviteCode = server.getInviteCode();
+ if (inviteCode != null)
+ return inviteCode;
+ }
+ return (string)null;
+ }
+
+ public string getUserName(long farmerId)
+ {
+ foreach (Server server in this.servers)
+ {
+ if (server.getUserName(farmerId) != null)
+ return server.getUserName(farmerId);
+ }
+ return (string)null;
+ }
+
+ protected void initialize()
+ {
+ foreach (Server server in this.servers)
+ server.initialize();
+ this.updateLobbyData();
+ }
+
+ public void setPrivacy(ServerPrivacy privacy)
+ {
+ foreach (Server server in this.servers)
+ server.setPrivacy(privacy);
+ }
+
+ public void stopServer()
+ {
+ foreach (Server server in this.servers)
+ server.stopServer();
+ }
+
+ public void receiveMessages()
+ {
+ foreach (Server server in this.servers)
+ {
+ if (server == null)
+ {
+ ModCore.ModMonitor.Log("ERROR");
+ continue;
+ }
+ server.receiveMessages();
+ }
+ if (!this.isGameAvailable())
+ return;
+ foreach (Action gameAvailableAction in this.pendingGameAvailableActions)
+ gameAvailableAction();
+ this.pendingGameAvailableActions.Clear();
+ }
+
+ public void sendMessage(long peerId, OutgoingMessage message)
+ {
+ foreach (Server server in this.servers)
+ server.sendMessage(peerId, message);
+ }
+
+ public bool canAcceptIPConnections()
+ {
+ return this.servers.Select((Func)(s => s.canAcceptIPConnections())).Aggregate(false, (Func)((a, b) => a | b));
+ }
+
+ public bool canOfferInvite()
+ {
+ return this.servers.Select((Func)(s => s.canOfferInvite())).Aggregate(false, (Func)((a, b) => a | b));
+ }
+
+ public void offerInvite()
+ {
+ foreach (Server server in this.servers)
+ {
+ if (server.canOfferInvite())
+ server.offerInvite();
+ }
+ }
+
+ public bool connected()
+ {
+ foreach (Server server in this.servers)
+ {
+ if (!server.connected())
+ return false;
+ }
+ return true;
+ }
+
+ public void sendMessage(long peerId, byte messageType, Farmer sourceFarmer, params object[] data)
+ {
+ this.sendMessage(peerId, new OutgoingMessage(messageType, sourceFarmer, data));
+ }
+
+ public void sendMessages()
+ {
+ foreach (Farmer farmer in (IEnumerable)Game1.otherFarmers.Values)
+ {
+ foreach (OutgoingMessage message in (IEnumerable)farmer.messageQueue)
+ this.sendMessage(farmer.UniqueMultiplayerID, message);
+ farmer.messageQueue.Clear();
+ }
+ }
+
+ public void startServer()
+ {
+ Console.WriteLine("Starting server. Protocol version: " + ModCore.multiplayer.protocolVersion);
+ this.initialize();
+ if ((NetFieldBase>)Game1.serverHost == (NetRef)null)
+ Game1.serverHost = new NetFarmerRoot();
+ Game1.serverHost.Value = Game1.player;
+ Game1.serverHost.MarkClean();
+ Game1.serverHost.Clock.InterpolationTicks = ModCore.multiplayer.defaultInterpolationTicks;
+ if ((NetFieldBase>)Game1.netWorldState == (NetRef)null)
+ Game1.netWorldState = new NetRoot((IWorldState)new NetWorldState());
+ Game1.netWorldState.Clock.InterpolationTicks = 0;
+ Game1.netWorldState.Value.UpdateFromGame1();
+ }
+
+ public void sendServerIntroduction(long peer)
+ {
+ this.sendLocation(peer, (GameLocation)Game1.getFarm());
+ this.sendLocation(peer, Game1.getLocationFromName("FarmHouse"));
+ ModCore.SerializationManager.cleanUpInventory();
+ ModCore.SerializationManager.cleanUpWorld();
+ ModCore.SerializationManager.cleanUpStorageContainers();
+ ModCore.ModMonitor.Log("HELLO LOVE!!!");
+ this.sendMessage(peer, new OutgoingMessage((byte)1, Game1.serverHost.Value, new object[3]
+ {
+ (object)ModCore.multiplayer.writeObjectFullBytes((NetRoot)Game1.serverHost, new long?(peer)),
+ (object)ModCore.multiplayer.writeObjectFullBytes(Game1.player.teamRoot, new long?(peer)),
+ (object)ModCore.multiplayer.writeObjectFullBytes(Game1.netWorldState, new long?(peer))
+ }));
+ foreach (KeyValuePair> root in Game1.otherFarmers.Roots)
+ {
+ if (root.Key != Game1.player.UniqueMultiplayerID && root.Key != peer)
+ this.sendMessage(peer, new OutgoingMessage((byte)2, root.Value.Value, new object[2]
+ {
+ (object)this.getUserName(root.Value.Value.UniqueMultiplayerID),
+ (object)ModCore.multiplayer.writeObjectFullBytes(root.Value, new long?(peer))
+ }));
+ }
+ ModCore.SerializationManager.restoreAllModObjects(ModCore.SerializationManager.trackedObjectList);
+ }
+
+ public void playerDisconnected(long disconnectee)
+ {
+ Farmer sourceFarmer = (Farmer)null;
+ Game1.otherFarmers.TryGetValue(disconnectee, out sourceFarmer);
+ ModCore.multiplayer.playerDisconnected(disconnectee);
+ if (sourceFarmer == null)
+ return;
+ OutgoingMessage message = new OutgoingMessage((byte)19, sourceFarmer, new object[0]);
+ foreach (long key in (IEnumerable)Game1.otherFarmers.Keys)
+ {
+ if (key != disconnectee)
+ this.sendMessage(key, message);
+ }
+ }
+
+ public bool isGameAvailable()
+ {
+ bool flag1 = Game1.currentMinigame is Intro || Game1.Date.DayOfMonth == 0;
+ bool flag2 = Game1.CurrentEvent != null && Game1.CurrentEvent.isWedding;
+ bool flag3 = Game1.newDaySync != null && !Game1.newDaySync.hasFinished();
+ bool flag4 = Game1.player.team.buildingLock.IsLocked();
+ if (!Game1.isFestival() && !flag2 && (!flag1 && !flag3))
+ return !flag4;
+ return false;
+ }
+
+ public bool whenGameAvailable(Action action)
+ {
+ if (this.isGameAvailable())
+ {
+ action();
+ return true;
+ }
+ this.pendingGameAvailableActions.Add(action);
+ return false;
+ }
+
+ private void rejectFarmhandRequest(string userID, NetFarmerRoot farmer, Action sendMessage)
+ {
+ this.sendAvailableFarmhands(userID, sendMessage);
+ Console.WriteLine("Rejected request for farmhand " + (farmer.Value != null ? farmer.Value.UniqueMultiplayerID.ToString() : "???"));
+ }
+
+ private IEnumerable cabins()
+ {
+ if (Game1.getFarm() != null)
+ {
+ foreach (Building building in Game1.getFarm().buildings)
+ {
+ if ((int)((NetFieldBase)building.daysOfConstructionLeft) <= 0 && building.indoors.Value is Cabin)
+ yield return building.indoors.Value as Cabin;
+ }
+ }
+ }
+
+ private bool authCheck(string userID, Farmer farmhand)
+ {
+ if (!Game1.options.enableFarmhandCreation && !(bool)((NetFieldBase)farmhand.isCustomized))
+ return false;
+ if (!(userID == "") && !(farmhand.userID.Value == ""))
+ return farmhand.userID.Value == userID;
+ return true;
+ }
+
+ private Cabin findCabin(Farmer farmhand)
+ {
+ foreach (Cabin cabin in this.cabins())
+ {
+ if (cabin.getFarmhand().Value.UniqueMultiplayerID == farmhand.UniqueMultiplayerID)
+ return cabin;
+ }
+ return (Cabin)null;
+ }
+
+ private Farmer findOriginalFarmhand(Farmer farmhand)
+ {
+ return this.findCabin(farmhand)?.getFarmhand().Value;
+ }
+
+ public void checkFarmhandRequest(string userID, NetFarmerRoot farmer, Action sendMessage, Action approve)
+ {
+ if (farmer.Value == null)
+ {
+ this.rejectFarmhandRequest(userID, farmer, sendMessage);
+ }
+ else
+ {
+ long id = farmer.Value.UniqueMultiplayerID;
+ if (this.whenGameAvailable((Action)(() =>
+ {
+ Farmer originalFarmhand = this.findOriginalFarmhand(farmer.Value);
+ if (originalFarmhand == null)
+ {
+ Console.WriteLine("Rejected request for farmhand " + (object)id + ": doesn't exist");
+ this.rejectFarmhandRequest(userID, farmer, sendMessage);
+ }
+ else if (!this.authCheck(userID, originalFarmhand))
+ {
+ Console.WriteLine("Rejected request for farmhand " + (object)id + ": authorization failure");
+ this.rejectFarmhandRequest(userID, farmer, sendMessage);
+ }
+ else if (Game1.otherFarmers.ContainsKey(id) && !ModCore.multiplayer.isDisconnecting(id) || Game1.serverHost.Value.UniqueMultiplayerID == id)
+ {
+ Console.WriteLine("Rejected request for farmhand " + (object)id + ": already in use");
+ this.rejectFarmhandRequest(userID, farmer, sendMessage);
+ }
+ else if (this.findCabin(farmer.Value).isInventoryOpen())
+ {
+ Console.WriteLine("Rejected request for farmhand " + (object)id + ": inventory in use");
+ this.rejectFarmhandRequest(userID, farmer, sendMessage);
+ }
+ else
+ {
+ Console.WriteLine("Approved request for farmhand " + (object)id);
+ approve();
+ ModCore.multiplayer.addPlayer(farmer);
+ ModCore.multiplayer.broadcastPlayerIntroduction(farmer);
+ this.sendServerIntroduction(id);
+ this.updateLobbyData();
+ }
+ })))
+ return;
+ Console.WriteLine("Postponing request for farmhand " + (object)id);
+ sendMessage(new OutgoingMessage((byte)11, Game1.player, new object[1]
+ {
+ (object)"Strings\\UI:Client_WaitForHostAvailability"
+ }));
+ }
+ }
+
+ public void sendAvailableFarmhands(string userID, Action sendMessage)
+ {
+ List> netRefList = new List>();
+ Game1.getFarm();
+ foreach (Cabin cabin in this.cabins())
+ {
+ NetRef farmhand = cabin.getFarmhand();
+ if ((!farmhand.Value.isActive() || ModCore.multiplayer.isDisconnecting(farmhand.Value.UniqueMultiplayerID)) && (this.authCheck(userID, farmhand.Value) && !cabin.isInventoryOpen()))
+ netRefList.Add(farmhand);
+ }
+ using (MemoryStream memoryStream = new MemoryStream())
+ {
+ using (BinaryWriter writer = new BinaryWriter((Stream)memoryStream))
+ {
+ writer.Write(Game1.year);
+ writer.Write(Utility.getSeasonNumber(Game1.currentSeason));
+ writer.Write(Game1.dayOfMonth);
+ writer.Write((byte)netRefList.Count);
+ foreach (NetRef netRef in netRefList)
+ {
+ try
+ {
+ netRef.Serializer = SaveGame.farmerSerializer;
+ netRef.WriteFull(writer);
+ }
+ finally
+ {
+ netRef.Serializer = (XmlSerializer)null;
+ }
+ }
+ memoryStream.Seek(0L, SeekOrigin.Begin);
+ sendMessage(new OutgoingMessage((byte)9, Game1.player, new object[1]
+ {
+ (object)memoryStream.ToArray()
+ }));
+ }
+ }
+ }
+
+ private void sendLocation(long peer, GameLocation location)
+ {
+ this.sendMessage(peer, (byte)3, Game1.serverHost.Value, (object)ModCore.multiplayer.writeObjectFullBytes(ModCore.multiplayer.locationRoot(location), new long?(peer)));
+ }
+
+ private void warpFarmer(Farmer farmer, short x, short y, string name, bool isStructure)
+ {
+ GameLocation locationFromName = Game1.getLocationFromName(name, isStructure);
+ locationFromName.hostSetup();
+ farmer.currentLocation = locationFromName;
+ farmer.Position = new Vector2((float)((int)x * 64), (float)((int)y * 64 - (farmer.Sprite.getHeight() - 32) + 16));
+ this.sendLocation(farmer.UniqueMultiplayerID, locationFromName);
+ }
+
+ public void processIncomingMessage(IncomingMessage message)
+ {
+ switch (message.MessageType)
+ {
+ case 2:
+ message.Reader.ReadString();
+ ModCore.multiplayer.processIncomingMessage(message);
+ break;
+ case 5:
+ this.warpFarmer(message.SourceFarmer, message.Reader.ReadInt16(), message.Reader.ReadInt16(), message.Reader.ReadString(), message.Reader.ReadByte() == (byte)1);
+ break;
+ default:
+ ModCore.multiplayer.processIncomingMessage(message);
+ break;
+ }
+ if (!ModCore.multiplayer.isClientBroadcastType(message.MessageType))
+ return;
+ this.rebroadcastClientMessage(message);
+ }
+
+ private void rebroadcastClientMessage(IncomingMessage message)
+ {
+ OutgoingMessage message1 = new OutgoingMessage(message);
+ foreach (long key in (IEnumerable)Game1.otherFarmers.Keys)
+ {
+ if (key != message.FarmerID)
+ this.sendMessage(key, message1);
+ }
+ }
+
+ private void setLobbyData(string key, string value)
+ {
+ foreach (Server server in this.servers)
+ server.setLobbyData(key, value);
+ }
+
+ private bool unclaimedFarmhandsExist()
+ {
+ foreach (Cabin cabin in this.cabins())
+ {
+ if (cabin.farmhand.Value == null || cabin.farmhand.Value.userID.Value == "")
+ return true;
+ }
+ return false;
+ }
+
+ public void updateLobbyData()
+ {
+ this.setLobbyData("farmName", Game1.player.farmName.Value);
+ this.setLobbyData("farmType", Convert.ToString(Game1.whichFarm));
+ this.setLobbyData("date", Convert.ToString(new WorldDate(Game1.year, Game1.currentSeason, Game1.dayOfMonth).TotalDays));
+ this.setLobbyData("farmhands", string.Join(",", Game1.getAllFarmhands().Select((Func)(farmhand => farmhand.userID.Value)).Where((Func)(user => user != ""))));
+ this.setLobbyData("newFarmhands", Convert.ToString(Game1.options.enableFarmhandCreation && this.unclaimedFarmhandsExist()));
+ }
+ }
+}
diff --git a/GeneralMods/StardustCore/NetCode/NetBufferReadStream.cs b/GeneralMods/StardustCore/NetCode/NetBufferReadStream.cs
new file mode 100644
index 00000000..0b24e59a
--- /dev/null
+++ b/GeneralMods/StardustCore/NetCode/NetBufferReadStream.cs
@@ -0,0 +1,99 @@
+using System;
+using System.IO;
+using Lidgren.Network;
+
+namespace StardustCore.NetCode
+{
+ public class NetBufferReadStream : Stream
+ {
+ private long offset;
+ public NetBuffer Buffer;
+
+ public NetBufferReadStream(NetBuffer buffer)
+ {
+ this.Buffer = buffer;
+ this.offset = buffer.Position;
+ }
+
+ public override bool CanRead
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override bool CanSeek
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override bool CanWrite
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override long Length
+ {
+ get
+ {
+ return ((long)this.Buffer.LengthBits - this.offset) / 8L;
+ }
+ }
+
+ public override long Position
+ {
+ get
+ {
+ return (this.Buffer.Position - this.offset) / 8L;
+ }
+ set
+ {
+ this.Buffer.Position = this.offset + value * 8L;
+ }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ this.Buffer.ReadBytes(buffer, offset, count);
+ return count;
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ this.Position = offset;
+ break;
+ case SeekOrigin.Current:
+ this.Position += offset;
+ break;
+ case SeekOrigin.End:
+ this.Position = this.Length + offset;
+ break;
+ }
+ return this.Position;
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException();
+ }
+ }
+}
diff --git a/GeneralMods/StardustCore/NetCode/NetBufferWriteStream.cs b/GeneralMods/StardustCore/NetCode/NetBufferWriteStream.cs
new file mode 100644
index 00000000..e3b62d41
--- /dev/null
+++ b/GeneralMods/StardustCore/NetCode/NetBufferWriteStream.cs
@@ -0,0 +1,97 @@
+using System;
+using System.IO;
+using Lidgren.Network;
+
+namespace StardustCore.NetCode
+{
+ public class NetBufferWriteStream : Stream
+ {
+ private int offset;
+ public NetBuffer Buffer;
+
+ public NetBufferWriteStream(NetBuffer buffer)
+ {
+ this.Buffer = buffer;
+ this.offset = buffer.LengthBits;
+ }
+
+ public override bool CanRead
+ {
+ get
+ {
+ return false;
+ }
+ }
+
+ public override bool CanSeek
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override bool CanWrite
+ {
+ get
+ {
+ return true;
+ }
+ }
+
+ public override long Length
+ {
+ get
+ {
+ throw new NotSupportedException();
+ }
+ }
+
+ public override long Position
+ {
+ get
+ {
+ return (long)((this.Buffer.LengthBits - this.offset) / 8);
+ }
+ set
+ {
+ this.Buffer.LengthBits = (int)((long)this.offset + value * 8L);
+ }
+ }
+
+ public override void Flush()
+ {
+ }
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override long Seek(long offset, SeekOrigin origin)
+ {
+ switch (origin)
+ {
+ case SeekOrigin.Begin:
+ this.Position = offset;
+ break;
+ case SeekOrigin.Current:
+ this.Position += offset;
+ break;
+ case SeekOrigin.End:
+ throw new NotSupportedException();
+ }
+ return this.Position;
+ }
+
+ public override void SetLength(long value)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override void Write(byte[] buffer, int offset, int count)
+ {
+ this.Buffer.Write(buffer, offset, count);
+ }
+ }
+}
diff --git a/GeneralMods/StardustCore/NetCode/NetCoreObject.cs b/GeneralMods/StardustCore/NetCode/NetCoreObject.cs
index 653102fe..47bfdf7f 100644
--- a/GeneralMods/StardustCore/NetCode/NetCoreObject.cs
+++ b/GeneralMods/StardustCore/NetCode/NetCoreObject.cs
@@ -63,7 +63,7 @@ namespace StardustCore.NetCode
{
texture = new NetTexture2DExtended(Value.getExtendedTexture());
- texture.WriteFull(writer);
+ texture.Write(writer);
which = new NetInt(Value.ParentSheetIndex);
which.Write(writer);
diff --git a/GeneralMods/StardustCore/NetCode/NetTexure2DExtended.cs b/GeneralMods/StardustCore/NetCode/NetTexure2DExtended.cs
index 47d8cfe6..4b3905f9 100644
--- a/GeneralMods/StardustCore/NetCode/NetTexure2DExtended.cs
+++ b/GeneralMods/StardustCore/NetCode/NetTexure2DExtended.cs
@@ -38,86 +38,20 @@ namespace StardustCore.NetCode
protected override void ReadDelta(BinaryReader reader, NetVersion version)
{
-
- NetInt Width = new NetInt();
- Width.Read(reader,version);
- int width = Width.Value;
-
- NetInt Height = new NetInt();
- Height.Read(reader, version);
- int height = Height.Value;
-
-
NetString name = new NetString();
name.Read(reader, version);
- NetString path = new NetString();
- path.Read(reader, version);
-
-
- NetInt count = new NetInt();
- count.Read(reader, version);
-
- List bytes = new List();
- //colorsOne = reader.ReadBytes();
-
- for(int i=0; i < count.Value; i++)
- {
- NetColor col = new NetColor();
- col.Read(reader, version);
- bytes.Add(col.Value);
- }
-
- ModCore.ModMonitor.Log("Finished length: "+bytes.Count.ToString());
- ModCore.ModMonitor.Log("W: " + width.ToString());
- ModCore.ModMonitor.Log("H: " + height.ToString());
//Texture2D texture = new Texture2D(Game1.graphics.GraphicsDevice,width,height);
- Texture2DExtended texture = new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test1.png"));
+ Texture2DExtended texture = ModCore.TextureManager.getTexture(name.Value);
this.Value = texture;
-
- //texture.SetData(bytes.ToArray());
-
- //Value.Name = name.Value;
- //Value.path = path.Value;
- //Value.setTexure(texture);
}
protected override void WriteDelta(BinaryWriter writer)
{
-
- int size = Value.getTexture().Width * Value.getTexture().Height;
- NetInt Width = new NetInt(Value.getTexture().Width);
- Width.Write(writer);
-
- NetInt Height = new NetInt(Value.getTexture().Height);
- Height.Write(writer);
-
-
NetString name = new NetString(Value.Name);
name.Write(writer);
-
- NetString path = new NetString(Value.path);
- path.Write(writer);
- //writer.Write(size);
-
- Texture2D texture = Value.getTexture();
- Color[] colorsOne = new Color[size]; //The hard to read,1D array
-
- texture.GetData(colorsOne);
-
- NetInt count = new NetInt(colorsOne.Length);
- count.Write(writer);
-
- ModCore.ModMonitor.Log("Color length:" + count.ToString());
-
- foreach(var v in colorsOne)
- {
- NetColor col = new NetColor(v);
- col.Write(writer);
- }
-
}
diff --git a/GeneralMods/StardustCore/Objects/CoreObject.cs b/GeneralMods/StardustCore/Objects/CoreObject.cs
index f83f6d6f..19abd983 100644
--- a/GeneralMods/StardustCore/Objects/CoreObject.cs
+++ b/GeneralMods/StardustCore/Objects/CoreObject.cs
@@ -1,6 +1,7 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Netcode;
+using Newtonsoft.Json;
using StardewModdingAPI;
using StardewValley;
using StardewValley.Locations;
@@ -11,6 +12,7 @@ using StardustCore.Interfaces;
using StardustCore.UIUtilities;
using System;
using System.Collections.Generic;
+using System.IO;
using System.Xml.Serialization;
namespace StardustCore
@@ -42,7 +44,7 @@ namespace StardustCore
public string description;
- [XmlIgnore]
+
protected Texture2DExtended TextureSheet;
public new bool flipped;
@@ -80,6 +82,7 @@ namespace StardustCore
public string serializationName;
+ public string textureName;
public override string Name
{
@@ -130,10 +133,6 @@ namespace StardustCore
public CoreObject(Texture2DExtended texture,int which, Vector2 Tile, int InventoryMaxSize):base()
{
var ok=Game1.getAllFarmers();
- foreach (var v in ok){
- this.owner.Value = v.UniqueMultiplayerID;
- break;
- }
this.Type = "Not Sure";
this.CanBeSetDown = true;
this.CanBeGrabbed = true;
@@ -1223,6 +1222,66 @@ namespace StardustCore
{
this.TextureSheet = texture;
}
+
+
+ ///
+ /// Serializes the said item properly.
+ ///
+ ///
+ public static void Serialize(Item I)
+ {
+ String savePath = ModCore.SerializationManager.playerInventoryPath;
+ String fileName = I.Name + ".json";
+ String resultPath = Path.Combine(savePath, fileName);
+ int count = 0;
+ while (File.Exists(resultPath))
+ {
+ resultPath = Serialization.SerializationManager.getValidSavePathIfDuplicatesExist(I, savePath, count);
+ count++;
+ }
+ JsonSerializerSettings settings = new JsonSerializerSettings();
+ settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+ (I as CoreObject).textureName = (I as CoreObject).TextureSheet.Name;
+ string json = JsonConvert.SerializeObject(I, Formatting.Indented,settings);
+ System.IO.File.WriteAllText(resultPath, json);
+ //StardustCore.ModCore.ModHelper.WriteJsonFile(resultPath, (CoreObject)I);
+ }
+
+ ///
+ /// Serializes the said item to a chest.
+ ///
+ ///
+ ///
+ public static void SerializeToContainer(Item I, string s)
+ {
+ String savePath = s;
+ String fileName = I.Name + ".json";
+ String resultPath = Path.Combine(savePath, fileName);
+ int count = 0;
+ while (File.Exists(resultPath))
+ {
+ resultPath = Serialization.SerializationManager.getValidSavePathIfDuplicatesExist(I, savePath, count);
+ count++;
+ }
+ JsonSerializerSettings settings = new JsonSerializerSettings();
+ settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
+ (I as CoreObject).textureName = (I as CoreObject).TextureSheet.Name;
+ string json = JsonConvert.SerializeObject(I, Formatting.Indented, settings);
+ System.IO.File.WriteAllText(resultPath, json);
+ //StardustCore.ModCore.ModHelper.WriteJsonFile(resultPath, (CoreObject)I);
+ }
+
+ ///
+ /// Deserializes the object from a .json.
+ ///
+ ///
+ ///
+ public static CoreObject Deserialize(string data)
+ {
+ CoreObject obj = ModCore.ModHelper.ReadJsonFile(data);
+ obj.TextureSheet = ModCore.TextureManager.getTexture(obj.textureName);
+ return obj;
+ }
}
}
diff --git a/GeneralMods/StardustCore/Serialization/Serialization.cs b/GeneralMods/StardustCore/Serialization/Serialization.cs
index f59e351b..1b858e0b 100644
--- a/GeneralMods/StardustCore/Serialization/Serialization.cs
+++ b/GeneralMods/StardustCore/Serialization/Serialization.cs
@@ -842,6 +842,12 @@ public string ParseXMLType(string path)
public void initializeDefaultSuportedTypes()
{
initializeSupportedToolTypes();
+ initializeSupportedObjectTypes();
+ }
+
+ private void initializeSupportedObjectTypes()
+ {
+ this.acceptedTypes.Add(typeof(CoreObject).ToString(), new SerializerDataNode(CoreObject.Serialize, CoreObject.Deserialize, new SerializerDataNode.WorldParsingFunction(CoreObject.Serialize), new SerializerDataNode.SerializingToContainerFunction(CoreObject.SerializeToContainer)));
}
///
diff --git a/GeneralMods/StardustCore/StardustCore.csproj b/GeneralMods/StardustCore/StardustCore.csproj
index fd8c09bd..e07c8a51 100644
--- a/GeneralMods/StardustCore/StardustCore.csproj
+++ b/GeneralMods/StardustCore/StardustCore.csproj
@@ -71,6 +71,10 @@
MinimumRecommendedRules.ruleset
+
+ False
+ ..\..\..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Stardew Valley\Lidgren.Network.dll
+
..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
@@ -89,6 +93,10 @@
+
+
+
+
diff --git a/GeneralMods/StardustCore/UIUtilities/Texture2DExtended.cs b/GeneralMods/StardustCore/UIUtilities/Texture2DExtended.cs
index 49de1b8b..08a31641 100644
--- a/GeneralMods/StardustCore/UIUtilities/Texture2DExtended.cs
+++ b/GeneralMods/StardustCore/UIUtilities/Texture2DExtended.cs
@@ -12,7 +12,7 @@ namespace StardustCore.UIUtilities
public class Texture2DExtended
{
public string Name;
- private Texture2D texture;
+ public Texture2D texture;
public string path;
IModHelper helper;
diff --git a/GeneralMods/StardustCore/UIUtilities/TextureManager.cs b/GeneralMods/StardustCore/UIUtilities/TextureManager.cs
index c4c0402a..33071a4d 100644
--- a/GeneralMods/StardustCore/UIUtilities/TextureManager.cs
+++ b/GeneralMods/StardustCore/UIUtilities/TextureManager.cs
@@ -29,7 +29,7 @@ namespace StardustCore.UIUtilities
{
foreach(var v in textures)
{
- if (v.Key == name) return v.Value;
+ if (v.Key == name) return v.Value.Copy();
}
return null;
}