Track LocalMods as part of monolith
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
using Barotrauma.MoreLevelContent.Shared.Utils;
|
||||
using MoreLevelContent.Shared;
|
||||
using Barotrauma.MoreLevelContent.Shared.Config;
|
||||
using MoreLevelContent;
|
||||
using Barotrauma.Networking;
|
||||
using MoreLevelContent.Networking;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System;
|
||||
// ISSUE WITH LEVEL GEN, IT'S THE RUIN MOVE
|
||||
namespace Barotrauma.MoreLevelContent.Config
|
||||
{
|
||||
/// <summary>
|
||||
/// Server
|
||||
/// </summary>
|
||||
partial class ConfigManager : Singleton<ConfigManager>
|
||||
{
|
||||
private void SetupServer()
|
||||
{
|
||||
NetUtil.Register(NetEvent.CONFIG_WRITE_SERVER, ServerRead);
|
||||
NetUtil.Register(NetEvent.CONFIG_REQUEST, ConfigRequest);
|
||||
// Always init the server with a default config, the first client to join with admin perms will set the config
|
||||
// This was due to some issue with reading the config file on the server iirc
|
||||
// Maybe revist this in the future?
|
||||
Log.Debug("Setting up server config...");
|
||||
|
||||
// Only setup default config on non-dedicated servers, on servers hosted through
|
||||
// the in game menu, the owner of the server will send the config to use
|
||||
// where as on dedicated servers they will never get a config sent and thus will
|
||||
// always have the default config loaded
|
||||
if (!Main.IsDedicatedServer)
|
||||
{
|
||||
DefaultConfig();
|
||||
} else
|
||||
{
|
||||
LoadConfig();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private readonly List<AccountId> correctInstalls = new List<AccountId>();
|
||||
|
||||
#region Networking
|
||||
private void ServerRead(object[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
IReadMessage inMsg = (IReadMessage)args[0];
|
||||
Client c = (Client)args[1];
|
||||
Log.Debug($"Got config from client {c.Name}");
|
||||
if (!c.HasPermission(ClientPermissions.ManageSettings))
|
||||
{
|
||||
Log.Error("No Perms!");
|
||||
return;
|
||||
}
|
||||
if (!CheckClientVersion(c, inMsg.ReadString()))
|
||||
{
|
||||
Log.Debug($"Ignored config from {c.Name} due to them using the wrong version!");
|
||||
return;
|
||||
}
|
||||
ReadNetConfig(ref inMsg);
|
||||
ServerWrite();
|
||||
} catch(Exception err)
|
||||
{
|
||||
Log.Debug(err.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void ServerWrite()
|
||||
{
|
||||
Log.Debug("Propagating config to all clients...");
|
||||
IWriteMessage outMsg = NetUtil.CreateNetMsg(NetEvent.CONFIG_WRITE_CLIENT);
|
||||
WriteConfig(ref outMsg);
|
||||
NetUtil.SendAll(outMsg);
|
||||
}
|
||||
|
||||
private void ConfigRequest(object[] args)
|
||||
{
|
||||
IReadMessage inMsg = (IReadMessage)args[0];
|
||||
Client c = (Client)args[1];
|
||||
string version = inMsg.ReadString();
|
||||
if (!CheckClientVersion(c, version)) return; // Exit if the client doesn't have the right version
|
||||
IWriteMessage outMsg = NetUtil.CreateNetMsg(NetEvent.CONFIG_WRITE_CLIENT);
|
||||
WriteConfig(ref outMsg);
|
||||
NetUtil.SendClient(outMsg, c.Connection);
|
||||
Log.Debug($"Sent config to client {c.Name}");
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private bool CheckClientVersion(Client client, string clientVersion)
|
||||
{
|
||||
if (!client.AccountId.TryUnwrap(out AccountId account)) return false;
|
||||
if (correctInstalls.Contains(account)) return true;
|
||||
|
||||
if (clientVersion != Main.Version)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(
|
||||
TextManager.GetServerMessage($"mlc.server.wrongversionclient~[clientversion]={clientVersion}~[serverversion]={Main.Version}").Value,
|
||||
client,
|
||||
ChatMessageType.ServerMessageBox);
|
||||
GameMain.Server.SendChatMessage(TextManager.GetServerMessage($"mlc.server.wrongversion~[client]={client.Name}~[clientversion]={clientVersion}~[serverversion]={Main.Version}").Value);
|
||||
return false;
|
||||
}
|
||||
|
||||
GameMain.Server.SendChatMessage(TextManager.GetServerMessage($"mlc.server.installed~[client]={client.Name}").Value);
|
||||
correctInstalls.Add(account);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using Barotrauma;
|
||||
using Barotrauma.MoreLevelContent.Shared.Utils;
|
||||
using Barotrauma.Networking;
|
||||
using MoreLevelContent.Networking;
|
||||
using MoreLevelContent.Shared.Data;
|
||||
using MoreLevelContent.Shared.Generation.Pirate;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace MoreLevelContent.Shared.Generation
|
||||
{
|
||||
// Server
|
||||
public partial class MapDirector : Singleton<MapDirector>
|
||||
{
|
||||
partial void SetupProjSpecific()
|
||||
{
|
||||
NetUtil.Register(NetEvent.MAP_CONNECTION_EQUALITYCHECK_REQUEST, RequestConnectionEquality);
|
||||
NetUtil.Register(NetEvent.MAP_REQUEST_STATE, RespondToMapStateRequest);
|
||||
}
|
||||
|
||||
private void RespondToMapStateRequest(object[] args)
|
||||
{
|
||||
Client client = (Client)args[1];
|
||||
IWriteMessage outMsg = NetUtil.CreateNetMsg(NetEvent.MAP_SEND_STATE);
|
||||
|
||||
WriteMsg();
|
||||
|
||||
NetUtil.SendClient(outMsg, client.Connection);
|
||||
Log.Debug($"Sent map state request to {client.Name}");
|
||||
|
||||
|
||||
void WriteMsg()
|
||||
{
|
||||
if (GameMain.GameSession.Campaign is not MultiPlayerCampaign campaign)
|
||||
{
|
||||
outMsg.WriteByte((byte)MapSyncState.NotCampaign);
|
||||
return;
|
||||
}
|
||||
if (campaign.Map == null)
|
||||
{
|
||||
outMsg.WriteByte((byte)MapSyncState.MapNotCreated);
|
||||
return;
|
||||
}
|
||||
outMsg.WriteByte((byte)MapSyncState.MapSynced);
|
||||
var activeDistressBeacons = campaign.Map.Connections.Where(c => c.LevelData.MLC().HasDistress);
|
||||
var count = activeDistressBeacons.Count();
|
||||
if (count > byte.MaxValue)
|
||||
{
|
||||
DebugConsole.ThrowError("More Level Content detected more than 255 active distress beacons when trying to respond to a client map state request, what did you do??? This won't work, please reduce the numer!");
|
||||
return;
|
||||
}
|
||||
outMsg.WriteByte((byte)count);
|
||||
foreach (var connection in activeDistressBeacons)
|
||||
{
|
||||
int id = ConnectionIdLookup[connection];
|
||||
outMsg.WriteInt16((short)id);
|
||||
outMsg.WriteByte((byte)connection.LevelData.MLC().DistressStepsLeft);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyMapFeatureRevealed(LocationConnection con, MapFeatureData feature)
|
||||
{
|
||||
foreach (Client client in GameMain.Server.ConnectedClients)
|
||||
{
|
||||
NotifyMapFeatureRevealed(client, con, feature);
|
||||
}
|
||||
}
|
||||
|
||||
internal partial void RoundEnd(CampaignMode.TransitionType transitionType) { }
|
||||
|
||||
private void NotifyMapFeatureRevealed(Client client, LocationConnection con, MapFeatureData feature)
|
||||
{
|
||||
Int32 conId = MapDirector.ConnectionIdLookup[con];
|
||||
var msg = NetUtil.CreateNetMsg(NetEvent.EVENT_REVEALMAPFEATURE);
|
||||
msg.WriteIdentifier(feature.Name);
|
||||
msg.WriteInt32(conId);
|
||||
NetUtil.SendClient(msg, client.Connection);
|
||||
}
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma;
|
||||
using MoreLevelContent.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MoreLevelContent.Shared.Data;
|
||||
using Barotrauma.MoreLevelContent.Config;
|
||||
|
||||
namespace MoreLevelContent.Shared.Generation
|
||||
{
|
||||
// Server
|
||||
internal partial class OldDistressMapModule
|
||||
{
|
||||
protected override void InitProjSpecific() => NetUtil.Register(NetEvent.COMMAND_CREATEDISTRESS, Command_CreateDistress);
|
||||
|
||||
internal void Command_CreateDistress(object[] args)
|
||||
{
|
||||
Log.Debug("Got command");
|
||||
ForceDistress();
|
||||
}
|
||||
}
|
||||
|
||||
internal partial class DistressMapModule : TimedEventMapModule
|
||||
{
|
||||
protected override void InitProjSpecific() { }
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MoreLevelContent.Shared.Generation
|
||||
{
|
||||
// Server
|
||||
internal partial class LostCargoMapModule : TimedEventMapModule
|
||||
{
|
||||
protected override void InitProjSpecific() { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using Barotrauma;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using MoreLevelContent.Shared;
|
||||
using MoreLevelContent.Shared.Utils;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace MoreLevelContent.Items
|
||||
{
|
||||
// Server
|
||||
internal partial class SimpleStore : Powered, IServerSerializable, IClientSerializable
|
||||
{
|
||||
public void ServerEventRead(IReadMessage msg, Client c)
|
||||
{
|
||||
uint recipeHash = msg.ReadUInt32();
|
||||
int amountToFabricate = msg.ReadRangedInteger(1, MaxAmountToFabricate);
|
||||
item.CreateServerEvent(this);
|
||||
|
||||
if (!item.CanClientAccess(c)) { return; }
|
||||
|
||||
AmountToFabricate = amountToFabricate;
|
||||
if (recipeHash == 0)
|
||||
{
|
||||
CancelFabricating(c.Character);
|
||||
}
|
||||
else
|
||||
{
|
||||
//if already fabricating the selected item, return
|
||||
if (fabricatedItem != null && fabricatedItem.RecipeHash == recipeHash) { return; }
|
||||
if (recipeHash == 0) { return; }
|
||||
|
||||
amountRemaining = AmountToFabricate;
|
||||
|
||||
StartFabricating(fabricationRecipes[recipeHash], c.Character);
|
||||
}
|
||||
}
|
||||
|
||||
private ulong serverEventId = 0;
|
||||
|
||||
private readonly struct EventData : IEventData
|
||||
{
|
||||
public readonly ulong ServerEventId;
|
||||
public readonly SimpleStoreState State;
|
||||
|
||||
public EventData(ulong serverEventId, SimpleStoreState state)
|
||||
{
|
||||
//ensuring the uniqueness of this event is
|
||||
//required for the fabricator to sync correctly;
|
||||
//otherwise, the event manager would incorrectly
|
||||
//assume that the client actually has the latest state
|
||||
ServerEventId = serverEventId;
|
||||
State = state;
|
||||
}
|
||||
}
|
||||
|
||||
public override IEventData ServerGetEventData()
|
||||
=> new EventData(serverEventId, State);
|
||||
|
||||
public override bool ValidateEventData(NetEntityEvent.IData data)
|
||||
=> TryExtractEventData<EventData>(data, out _);
|
||||
|
||||
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData = null)
|
||||
{
|
||||
var componentData = ExtractEventData<EventData>(extraData);
|
||||
msg.WriteByte((byte)componentData.State);
|
||||
msg.WriteRangedInteger(AmountToFabricate, 0, MaxAmountToFabricate);
|
||||
msg.WriteRangedInteger(amountRemaining, 0, MaxAmountToFabricate);
|
||||
msg.WriteSingle(timeUntilReady);
|
||||
uint recipeHash = fabricatedItem?.RecipeHash ?? 0;
|
||||
msg.WriteUInt32(recipeHash);
|
||||
UInt16 userId = fabricatedItem is null || user is null ? (UInt16)0 : user.ID;
|
||||
msg.WriteUInt16(userId);
|
||||
|
||||
msg.WriteUInt16((ushort)fabricationLimits.Count);
|
||||
foreach (var kvp in fabricationLimits)
|
||||
{
|
||||
msg.WriteUInt32(kvp.Key);
|
||||
msg.WriteUInt32((uint)kvp.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
using Barotrauma;
|
||||
using Barotrauma.Networking;
|
||||
using HarmonyLib;
|
||||
using MoreLevelContent.Networking;
|
||||
using MoreLevelContent.Shared;
|
||||
using MoreLevelContent.Shared.Generation;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace MoreLevelContent
|
||||
{
|
||||
// Server
|
||||
partial class Main
|
||||
{
|
||||
public static bool IsDedicatedServer => GameMain.Server.OwnerConnection == null;
|
||||
public static bool CurrentGameModeValid = true;
|
||||
public void InitServer()
|
||||
{
|
||||
Log.Debug("Init Server");
|
||||
Harmony.Patch(AccessTools.PropertySetter(typeof(NetLobbyScreen), nameof(NetLobbyScreen.SelectedModeIndex)), postfix: new HarmonyMethod(AccessTools.Method(typeof(Main), nameof(Main.OnGameModeChange))));
|
||||
OnGameModeChange(GameMain.NetLobbyScreen);
|
||||
if (PreventRoundEnd)
|
||||
{
|
||||
Main.Harmony.Patch(AccessTools.Method(typeof(GameServer), nameof(GameServer.Update)), transpiler: new HarmonyMethod(AccessTools.Method(typeof(Main), nameof(Main.PatchEndRound))));
|
||||
}
|
||||
}
|
||||
|
||||
static IEnumerable<CodeInstruction> PatchEndRound(IEnumerable<CodeInstruction> instructions, ILGenerator il)
|
||||
{
|
||||
Log.Debug(">>>> Starting end round transpile");
|
||||
var code = new List<CodeInstruction>(instructions);
|
||||
for (int i = 0; i < code.Count; i++)
|
||||
{
|
||||
if (i >= 514 && i <= 519)
|
||||
{
|
||||
Log.Debug($"nop {i}");
|
||||
code[i].opcode = OpCodes.Nop;
|
||||
}
|
||||
|
||||
yield return code[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void OnGameModeChange(NetLobbyScreen __instance)
|
||||
{
|
||||
var gameMode = __instance.GameModes[__instance.SelectedModeIndex];
|
||||
CurrentGameModeValid = gameMode.GameModeType == typeof(MultiPlayerCampaign);
|
||||
var validClients = GameMain.Server.ConnectedClients.Where(c => c.HasPermission(ClientPermissions.SelectMode));
|
||||
if (!CurrentGameModeValid)
|
||||
{
|
||||
foreach (var client in validClients)
|
||||
{
|
||||
GameMain.Server.SendDirectChatMessage(
|
||||
TextManager.GetServerMessage($"mlc.gamemodewarning.description").Value,
|
||||
client,
|
||||
ChatMessageType.ServerMessageBox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void SetRoundEndDelay()
|
||||
{
|
||||
Log.Debug("called");
|
||||
var endRoundDelay = AccessTools.PropertySetter(typeof(GameServer), nameof(GameServer.EndRoundDelay));
|
||||
var endRoundTimer = AccessTools.PropertySetter(typeof(GameServer), nameof(GameServer.EndRoundTimer));
|
||||
endRoundTimer.Invoke(GameMain.Server, new object[] { 0 });
|
||||
endRoundDelay.Invoke(GameMain.Server, new object[] { 1000f });
|
||||
Log.Debug($"{GameMain.Server.EndRoundDelay} {GameMain.Server.EndRoundTimer}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Barotrauma;
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MoreLevelContent.Missions
|
||||
{
|
||||
// Server
|
||||
internal partial class CablePuzzleMission : Mission
|
||||
{
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
using Barotrauma;
|
||||
using Barotrauma.Networking;
|
||||
using MoreLevelContent.Shared.Data;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MoreLevelContent.Missions
|
||||
{
|
||||
// Server
|
||||
partial class DistressEscortMission : DistressMission
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
base.ServerWriteInitial(msg, c);
|
||||
missionNPCs.Write(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
using Barotrauma.Networking;
|
||||
using MoreLevelContent.Shared;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MoreLevelContent.Missions
|
||||
{
|
||||
partial class DistressGhostshipMission
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
base.ServerWriteInitial(msg, c);
|
||||
missionNPCs.Write(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
using Barotrauma.Networking;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace MoreLevelContent.Missions
|
||||
{
|
||||
// Server
|
||||
partial class DistressSubmarineMission : DistressMission
|
||||
{
|
||||
public override void ServerWriteInitial(IWriteMessage msg, Client c)
|
||||
{
|
||||
base.ServerWriteInitial(msg, c);
|
||||
missionNPCs.Write(msg);
|
||||
foreach (var character in rewardLookup.Keys)
|
||||
{
|
||||
msg.WriteUInt16((ushort)rewardLookup[character]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using Barotrauma.Networking;
|
||||
using Barotrauma;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using MoreLevelContent.Shared.Data;
|
||||
|
||||
namespace MoreLevelContent.Missions
|
||||
{
|
||||
// Server
|
||||
partial class MissionNPCCollection
|
||||
{
|
||||
internal void Write(IWriteMessage msg)
|
||||
{
|
||||
msg.WriteBoolean(characters.Count > 0);
|
||||
if (characters.Count == 0) return;
|
||||
|
||||
msg.WriteByte((byte)characters.Count);
|
||||
foreach (Character character in characters)
|
||||
{
|
||||
character.WriteSpawnData(msg, character.ID, restrictMessageSize: false);
|
||||
msg.WriteBoolean(character.MLC().NPCElement.GetAttributeBool("allowordering", false));
|
||||
msg.WriteUInt16((ushort)characterItems[character].Count());
|
||||
foreach (Item item in characterItems[character])
|
||||
{
|
||||
item.WriteSpawnData(msg, item.ID, item.ParentInventory?.Owner?.ID ?? Entity.NullEntityID, 0, item.ParentInventory?.FindIndex(item) ?? -1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Barotrauma;
|
||||
|
||||
namespace MoreLevelContent.Missions
|
||||
{
|
||||
// Server
|
||||
internal partial class TriangulationMission : Mission
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
using Barotrauma;
|
||||
using Barotrauma.Networking;
|
||||
|
||||
namespace MoreLevelContent.Networking
|
||||
{
|
||||
/// <summary>
|
||||
/// Server
|
||||
/// </summary>
|
||||
public static partial class NetUtil
|
||||
{
|
||||
/// <summary>
|
||||
/// Send a message to the specified client
|
||||
/// </summary>
|
||||
/// <param name="outMsg"></param>
|
||||
/// <param name="connection"></param>
|
||||
/// <param name="deliveryMethod"></param>
|
||||
internal static void SendClient(IWriteMessage outMsg, NetworkConnection connection, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable)
|
||||
{
|
||||
if (GameMain.IsSingleplayer) return;
|
||||
GameMain.LuaCs.Networking.Send(outMsg, connection, deliveryMethod);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Send message to all connected clients
|
||||
/// </summary>
|
||||
/// <param name="outMsg"></param>
|
||||
/// <param name="deliveryMethod"></param>
|
||||
internal static void SendAll(IWriteMessage outMsg, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable)
|
||||
{
|
||||
if (GameMain.IsSingleplayer) return;
|
||||
GameMain.LuaCs.Networking.Send(outMsg, null, deliveryMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user