Tears, sweat, and lots of code hacks later, StardustCore supports multiplayer custom objects and tools.....
This commit is contained in:
parent
9c070e91c5
commit
644e95f3b4
|
@ -3,7 +3,9 @@ using Microsoft.Xna.Framework.Input;
|
||||||
using StardewModdingAPI;
|
using StardewModdingAPI;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Menus;
|
using StardewValley.Menus;
|
||||||
|
using StardewValley.Network;
|
||||||
using StardustCore.ModInfo;
|
using StardustCore.ModInfo;
|
||||||
|
using StardustCore.NetCode;
|
||||||
using StardustCore.Objects;
|
using StardustCore.Objects;
|
||||||
using StardustCore.Objects.Tools;
|
using StardustCore.Objects.Tools;
|
||||||
using StardustCore.Serialization;
|
using StardustCore.Serialization;
|
||||||
|
@ -13,6 +15,7 @@ using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
@ -25,6 +28,9 @@ namespace StardustCore
|
||||||
public static Serialization.SerializationManager SerializationManager;
|
public static Serialization.SerializationManager SerializationManager;
|
||||||
public static UIUtilities.TextureManager TextureManager;
|
public static UIUtilities.TextureManager TextureManager;
|
||||||
|
|
||||||
|
public static Multiplayer multiplayer;
|
||||||
|
bool serverHack;
|
||||||
|
|
||||||
public static string ContentDirectory;
|
public static string ContentDirectory;
|
||||||
public override void Entry(IModHelper helper)
|
public override void Entry(IModHelper helper)
|
||||||
{
|
{
|
||||||
|
@ -51,18 +57,88 @@ namespace StardustCore
|
||||||
|
|
||||||
SerializationManager.initializeDefaultSuportedTypes();
|
SerializationManager.initializeDefaultSuportedTypes();
|
||||||
TextureManager = new TextureManager();
|
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.ControlEvents.KeyPressed += ControlEvents_KeyPressed;
|
||||||
|
|
||||||
|
|
||||||
StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
|
StardewModdingAPI.Events.GameEvents.UpdateTick += GameEvents_UpdateTick;
|
||||||
|
serverHack = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the value of the data snagged by reflection.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="type"></param>
|
||||||
|
/// <param name="instance"></param>
|
||||||
|
/// <param name="fieldName"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
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)
|
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<Server> servers = Helper.Reflection.GetField<List<Server>>(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)
|
private void ControlEvents_KeyPressed(object sender, StardewModdingAPI.Events.EventArgsKeyPressed e)
|
||||||
|
@ -95,6 +171,7 @@ namespace StardustCore
|
||||||
|
|
||||||
// Game1.player.addItemToInventory(collection);
|
// Game1.player.addItemToInventory(collection);
|
||||||
CoreObject tile1 = new CoreObject(new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test1.png")),3, Vector2.Zero,9);
|
CoreObject tile1 = new CoreObject(new Texture2DExtended(ModCore.ModHelper, Path.Combine("Content", "Graphics", "MultiTest", "Test1.png")),3, Vector2.Zero,9);
|
||||||
|
|
||||||
tile1.description = "Hello";
|
tile1.description = "Hello";
|
||||||
tile1.Name = "test";
|
tile1.Name = "test";
|
||||||
tile1.displayName = "test";
|
tile1.displayName = "test";
|
||||||
|
|
|
@ -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)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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<Server> servers = new List<Server>();
|
||||||
|
public List<Action> pendingGameAvailableActions = new List<Action>();
|
||||||
|
|
||||||
|
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<Server>((Func<Server, int>)(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<Server, bool>((Func<Server, bool>)(s => s.canAcceptIPConnections())).Aggregate<bool, bool>(false, (Func<bool, bool, bool>)((a, b) => a | b));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool canOfferInvite()
|
||||||
|
{
|
||||||
|
return this.servers.Select<Server, bool>((Func<Server, bool>)(s => s.canOfferInvite())).Aggregate<bool, bool>(false, (Func<bool, bool, bool>)((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<Farmer>)Game1.otherFarmers.Values)
|
||||||
|
{
|
||||||
|
foreach (OutgoingMessage message in (IEnumerable<OutgoingMessage>)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<Farmer, NetRef<Farmer>>)Game1.serverHost == (NetRef<Farmer>)null)
|
||||||
|
Game1.serverHost = new NetFarmerRoot();
|
||||||
|
Game1.serverHost.Value = Game1.player;
|
||||||
|
Game1.serverHost.MarkClean();
|
||||||
|
Game1.serverHost.Clock.InterpolationTicks = ModCore.multiplayer.defaultInterpolationTicks;
|
||||||
|
if ((NetFieldBase<IWorldState, NetRef<IWorldState>>)Game1.netWorldState == (NetRef<IWorldState>)null)
|
||||||
|
Game1.netWorldState = new NetRoot<IWorldState>((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<Farmer>((NetRoot<Farmer>)Game1.serverHost, new long?(peer)),
|
||||||
|
(object)ModCore.multiplayer.writeObjectFullBytes<FarmerTeam>(Game1.player.teamRoot, new long?(peer)),
|
||||||
|
(object)ModCore.multiplayer.writeObjectFullBytes<IWorldState>(Game1.netWorldState, new long?(peer))
|
||||||
|
}));
|
||||||
|
foreach (KeyValuePair<long, NetRoot<Farmer>> 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<Farmer>(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<long>)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<OutgoingMessage> sendMessage)
|
||||||
|
{
|
||||||
|
this.sendAvailableFarmhands(userID, sendMessage);
|
||||||
|
Console.WriteLine("Rejected request for farmhand " + (farmer.Value != null ? farmer.Value.UniqueMultiplayerID.ToString() : "???"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private IEnumerable<Cabin> cabins()
|
||||||
|
{
|
||||||
|
if (Game1.getFarm() != null)
|
||||||
|
{
|
||||||
|
foreach (Building building in Game1.getFarm().buildings)
|
||||||
|
{
|
||||||
|
if ((int)((NetFieldBase<int, NetInt>)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<bool, NetBool>)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<OutgoingMessage> 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<OutgoingMessage> sendMessage)
|
||||||
|
{
|
||||||
|
List<NetRef<Farmer>> netRefList = new List<NetRef<Farmer>>();
|
||||||
|
Game1.getFarm();
|
||||||
|
foreach (Cabin cabin in this.cabins())
|
||||||
|
{
|
||||||
|
NetRef<Farmer> 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<Farmer> 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<GameLocation>(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<long>)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<Farmer, string>((Func<Farmer, string>)(farmhand => farmhand.userID.Value)).Where<string>((Func<string, bool>)(user => user != ""))));
|
||||||
|
this.setLobbyData("newFarmhands", Convert.ToString(Game1.options.enableFarmhandCreation && this.unclaimedFarmhandsExist()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,7 +63,7 @@ namespace StardustCore.NetCode
|
||||||
{
|
{
|
||||||
|
|
||||||
texture = new NetTexture2DExtended(Value.getExtendedTexture());
|
texture = new NetTexture2DExtended(Value.getExtendedTexture());
|
||||||
texture.WriteFull(writer);
|
texture.Write(writer);
|
||||||
|
|
||||||
which = new NetInt(Value.ParentSheetIndex);
|
which = new NetInt(Value.ParentSheetIndex);
|
||||||
which.Write(writer);
|
which.Write(writer);
|
||||||
|
|
|
@ -38,87 +38,21 @@ namespace StardustCore.NetCode
|
||||||
|
|
||||||
protected override void ReadDelta(BinaryReader reader, NetVersion version)
|
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();
|
NetString name = new NetString();
|
||||||
name.Read(reader, version);
|
name.Read(reader, version);
|
||||||
NetString path = new NetString();
|
|
||||||
path.Read(reader, version);
|
|
||||||
|
|
||||||
|
|
||||||
NetInt count = new NetInt();
|
|
||||||
count.Read(reader, version);
|
|
||||||
|
|
||||||
List<Color> bytes = new List<Color>();
|
|
||||||
//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);
|
//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;
|
this.Value = texture;
|
||||||
|
|
||||||
//texture.SetData(bytes.ToArray());
|
|
||||||
|
|
||||||
//Value.Name = name.Value;
|
|
||||||
//Value.path = path.Value;
|
|
||||||
//Value.setTexure(texture);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void WriteDelta(BinaryWriter writer)
|
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);
|
NetString name = new NetString(Value.Name);
|
||||||
name.Write(writer);
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
using Netcode;
|
using Netcode;
|
||||||
|
using Newtonsoft.Json;
|
||||||
using StardewModdingAPI;
|
using StardewModdingAPI;
|
||||||
using StardewValley;
|
using StardewValley;
|
||||||
using StardewValley.Locations;
|
using StardewValley.Locations;
|
||||||
|
@ -11,6 +12,7 @@ using StardustCore.Interfaces;
|
||||||
using StardustCore.UIUtilities;
|
using StardustCore.UIUtilities;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
using System.Xml.Serialization;
|
using System.Xml.Serialization;
|
||||||
|
|
||||||
namespace StardustCore
|
namespace StardustCore
|
||||||
|
@ -42,7 +44,7 @@ namespace StardustCore
|
||||||
|
|
||||||
public string description;
|
public string description;
|
||||||
|
|
||||||
[XmlIgnore]
|
|
||||||
protected Texture2DExtended TextureSheet;
|
protected Texture2DExtended TextureSheet;
|
||||||
|
|
||||||
public new bool flipped;
|
public new bool flipped;
|
||||||
|
@ -80,6 +82,7 @@ namespace StardustCore
|
||||||
|
|
||||||
public string serializationName;
|
public string serializationName;
|
||||||
|
|
||||||
|
public string textureName;
|
||||||
|
|
||||||
public override string Name
|
public override string Name
|
||||||
{
|
{
|
||||||
|
@ -130,10 +133,6 @@ namespace StardustCore
|
||||||
public CoreObject(Texture2DExtended texture,int which, Vector2 Tile, int InventoryMaxSize):base()
|
public CoreObject(Texture2DExtended texture,int which, Vector2 Tile, int InventoryMaxSize):base()
|
||||||
{
|
{
|
||||||
var ok=Game1.getAllFarmers();
|
var ok=Game1.getAllFarmers();
|
||||||
foreach (var v in ok){
|
|
||||||
this.owner.Value = v.UniqueMultiplayerID;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
this.Type = "Not Sure";
|
this.Type = "Not Sure";
|
||||||
this.CanBeSetDown = true;
|
this.CanBeSetDown = true;
|
||||||
this.CanBeGrabbed = true;
|
this.CanBeGrabbed = true;
|
||||||
|
@ -1223,6 +1222,66 @@ namespace StardustCore
|
||||||
{
|
{
|
||||||
this.TextureSheet = texture;
|
this.TextureSheet = texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serializes the said item properly.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="I"></param>
|
||||||
|
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<CoreObject>(resultPath, (CoreObject)I);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serializes the said item to a chest.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="I"></param>
|
||||||
|
/// <param name="s"></param>
|
||||||
|
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<CoreObject>(resultPath, (CoreObject)I);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Deserializes the object from a .json.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="s"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static CoreObject Deserialize(string data)
|
||||||
|
{
|
||||||
|
CoreObject obj = ModCore.ModHelper.ReadJsonFile<CoreObject>(data);
|
||||||
|
obj.TextureSheet = ModCore.TextureManager.getTexture(obj.textureName);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -842,6 +842,12 @@ public string ParseXMLType(string path)
|
||||||
public void initializeDefaultSuportedTypes()
|
public void initializeDefaultSuportedTypes()
|
||||||
{
|
{
|
||||||
initializeSupportedToolTypes();
|
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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -71,6 +71,10 @@
|
||||||
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Reference Include="Lidgren.Network, Version=3.6.0.1625, Culture=neutral, processorArchitecture=MSIL">
|
||||||
|
<SpecificVersion>False</SpecificVersion>
|
||||||
|
<HintPath>..\..\..\..\..\..\..\..\..\Program Files (x86)\Steam\steamapps\common\Stardew Valley\Lidgren.Network.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||||
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
<HintPath>..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
@ -89,6 +93,10 @@
|
||||||
<Compile Include="Interfaces\IToolSerializer.cs" />
|
<Compile Include="Interfaces\IToolSerializer.cs" />
|
||||||
<Compile Include="Math\Hex.cs" />
|
<Compile Include="Math\Hex.cs" />
|
||||||
<Compile Include="Math\Hex32.cs" />
|
<Compile Include="Math\Hex32.cs" />
|
||||||
|
<Compile Include="NetCode\ModdedClient.cs" />
|
||||||
|
<Compile Include="NetCode\ModdedGameServer.cs" />
|
||||||
|
<Compile Include="NetCode\NetBufferReadStream.cs" />
|
||||||
|
<Compile Include="NetCode\NetBufferWriteStream.cs" />
|
||||||
<Compile Include="NetCode\NetCoreObject.cs" />
|
<Compile Include="NetCode\NetCoreObject.cs" />
|
||||||
<Compile Include="NetCode\NetTexure2DExtended.cs" />
|
<Compile Include="NetCode\NetTexure2DExtended.cs" />
|
||||||
<Compile Include="Objects\MultiTileComponent.cs" />
|
<Compile Include="Objects\MultiTileComponent.cs" />
|
||||||
|
|
|
@ -12,7 +12,7 @@ namespace StardustCore.UIUtilities
|
||||||
public class Texture2DExtended
|
public class Texture2DExtended
|
||||||
{
|
{
|
||||||
public string Name;
|
public string Name;
|
||||||
private Texture2D texture;
|
public Texture2D texture;
|
||||||
public string path;
|
public string path;
|
||||||
IModHelper helper;
|
IModHelper helper;
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ namespace StardustCore.UIUtilities
|
||||||
{
|
{
|
||||||
foreach(var v in textures)
|
foreach(var v in textures)
|
||||||
{
|
{
|
||||||
if (v.Key == name) return v.Value;
|
if (v.Key == name) return v.Value.Copy();
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue