Added GameData spawn

This commit is contained in:
AeonLucid committed 2020-10-18 21:17:41 +02:00
1 parent 8392fe4237
commit 5f922f5f83
16 files changed
+492 -88

No files matched your search

@@ -0,0 +1,29 @@
using System.Collections.Generic;
namespace Impostor.Server.GameData
{
public class GameObject
{
public GameObject()
{
Components = new List<object>();
}
protected List<object> Components { get; }
public List<T> GetComponentsInChildren<T>()
{
var result = new List<T>();
foreach (var component in Components)
{
if (component.GetType().IsAssignableTo(typeof(T)))
{
result.Add((T) component);
}
}
return result;
}
}
}
@@ -0,0 +1,19 @@
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData
{
public abstract class InnerNetObject : GameObject
{
public uint NetId { get; set; }
public int OwnerId { get; set; }
public SpawnFlags SpawnFlags { get; internal set; }
public abstract void HandleRpc(byte callId, IMessageReader reader);
public abstract bool Serialize(IMessageWriter writer, bool initialState);
public abstract void Deserialize(IMessageReader reader, bool initialState);
}
}
@@ -0,0 +1,22 @@
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects.Components
{
public class InnerCustomNetworkTransform : InnerNetObject
{
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,22 @@
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects.Components
{
public class InnerPlayerPhysics : InnerNetObject
{
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,22 @@
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects.Components
{
public class InnerVoteBanSystem : InnerNetObject
{
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,34 @@
using Impostor.Server.GameData.Objects.Components;
using Impostor.Server.Games;
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects
{
public class InnerGameData : InnerNetObject
{
private readonly IGame _game;
public InnerGameData(IGame game)
{
_game = game;
Components.Add(this);
Components.Add(new InnerVoteBanSystem());
}
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,32 @@
using Impostor.Server.Games;
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects
{
public class InnerLobbyBehaviour : InnerNetObject
{
private readonly IGame _game;
public InnerLobbyBehaviour(IGame game)
{
_game = game;
Components.Add(this);
}
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,32 @@
using Impostor.Server.Games;
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects
{
public class InnerMeetingHud : InnerNetObject
{
private readonly IGame _game;
public InnerMeetingHud(IGame game)
{
_game = game;
Components.Add(this);
}
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,35 @@
using Impostor.Server.GameData.Objects.Components;
using Impostor.Server.Games;
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects
{
public class InnerPlayerControl : InnerNetObject
{
private readonly IGame _game;
public InnerPlayerControl(IGame game)
{
_game = game;
Components.Add(this);
Components.Add(new InnerPlayerPhysics());
Components.Add(new InnerCustomNetworkTransform());
}
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,32 @@
using Impostor.Server.Games;
using Impostor.Server.Net.Messages;
namespace Impostor.Server.GameData.Objects
{
public class InnerShipStatus : InnerNetObject
{
private readonly IGame _game;
public InnerShipStatus(IGame game)
{
_game = game;
Components.Add(this);
}
public override void HandleRpc(byte callId, IMessageReader reader)
{
throw new System.NotImplementedException();
}
public override bool Serialize(IMessageWriter writer, bool initialState)
{
throw new System.NotImplementedException();
}
public override void Deserialize(IMessageReader reader, bool initialState)
{
throw new System.NotImplementedException();
}
}
}
@@ -0,0 +1,11 @@
using System;
namespace Impostor.Server.GameData
{
[Flags]
public enum SpawnFlags : byte
{
None = 0,
IsClientCharacter = 1,
}
}
+7 -7
View File
@@ -21,16 +21,16 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Impostor.Server.Api\Impostor.Server.Api.csproj"/>
<ProjectReference Include="..\Impostor.Server.Hazel\Impostor.Server.Hazel.csproj"/>
<ProjectReference Include="..\Impostor.Shared\Impostor.Shared.csproj"/>
<ProjectReference Include="..\Impostor.Server.Api\Impostor.Server.Api.csproj" />
<ProjectReference Include="..\Impostor.Server.Hazel\Impostor.Server.Hazel.csproj" />
<ProjectReference Include="..\Impostor.Shared\Impostor.Shared.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.0-rc.1.20451.7"/>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0-rc.1.20451.14"/>
<PackageReference Include="Serilog.Extensions.Hosting" Version="3.1.0"/>
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1"/>
<PackageReference Include="Microsoft.Extensions.Caching.StackExchangeRedis" Version="5.0.0-rc.1.20451.7" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="5.0.0-rc.1.20451.14" />
<PackageReference Include="Serilog.Extensions.Hosting" Version="3.1.0" />
<PackageReference Include="Serilog.Sinks.Console" Version="3.1.1" />
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
+2 -3
View File
@@ -1,11 +1,8 @@
using System;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Hazel;
using Impostor.Server.Data;
using Impostor.Server.Games;
using Impostor.Server.Games.Managers;
using Impostor.Server.Hazel.Messages;
using Impostor.Server.Net.Manager;
using Impostor.Server.Net.Messages;
using Impostor.Shared.Innersloth;
@@ -149,6 +146,8 @@ namespace Impostor.Server.Net
// Handle packet.
var readerCopy = reader.Slice(reader.Position);
// TODO: Return value, either a bool (to cancel) or a writer (to cancel (null) or modify/overwrite).
await Player.Game.HandleGameData(readerCopy, Player, toPlayer);
// Broadcast packet to all other players.
+187
View File
@@ -0,0 +1,187 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Impostor.Server.GameData;
using Impostor.Server.GameData.Objects;
using Impostor.Server.Net.Messages;
using Impostor.Shared.Innersloth.GameData;
using Microsoft.Extensions.DependencyInjection;
namespace Impostor.Server.Net.State
{
internal partial class Game
{
private static readonly Type[] SpawnableObjects =
{
typeof(InnerShipStatus), // ShipStatus
typeof(InnerMeetingHud),
typeof(InnerLobbyBehaviour),
typeof(InnerGameData),
typeof(InnerPlayerControl),
typeof(InnerShipStatus), // HeadQuarters
typeof(InnerShipStatus), // PlanetMap
typeof(InnerShipStatus), // AprilShipStatus
};
private readonly List<InnerNetObject> _allObjects = new List<InnerNetObject>();
private readonly Dictionary<uint, InnerNetObject> _allObjectsFast = new Dictionary<uint, InnerNetObject>();
public async ValueTask HandleGameData(IMessageReader parent, IClientPlayer sender, bool toPlayer)
{
// Find target player.
IClientPlayer target = null;
if (toPlayer)
{
var targetId = parent.ReadPackedInt32();
if (!TryGetPlayer(targetId, out target))
{
// Invalid target.
return;
}
}
// Parse GameData messages.
while (parent.Position < parent.Length)
{
var reader = parent.ReadMessage();
switch (reader.Tag)
{
case GameDataTag.DataFlag:
{
var objectNetId = reader.ReadPackedUInt32();
Logger.Verbose("> Update {0}", objectNetId);
break;
}
case GameDataTag.RpcFlag:
{
var objectNetId = reader.ReadPackedUInt32();
var callId = reader.ReadByte();
Logger.Verbose("> RPC {0} {1}", objectNetId, callId);
break;
}
case GameDataTag.SpawnFlag:
{
var objectId = reader.ReadPackedUInt32();
if (objectId < SpawnableObjects.Length)
{
var innerNetObject = (InnerNetObject) ActivatorUtilities.CreateInstance(_serviceProvider, SpawnableObjects[objectId], this);
var id = reader.ReadPackedInt32();
innerNetObject.SpawnFlags = (SpawnFlags) reader.ReadByte();
var components = innerNetObject.GetComponentsInChildren<InnerNetObject>();
var componentsCount = reader.ReadPackedInt32();
if (componentsCount != components.Count)
{
Logger.Error(
"Children didn't match for spawnable {0}, name {1} ({2} != {3})",
objectId,
innerNetObject.GetType().Name,
componentsCount,
components.Count);
continue;
}
for (var i = 0; i < componentsCount; i++)
{
var obj = components[i];
obj.NetId = reader.ReadPackedUInt32();
obj.OwnerId = id;
if (!AddNetObject(obj))
{
Logger.Verbose("Failed to AddNetObject.");
obj.NetId = uint.MaxValue;
break;
}
var readerSub = reader.ReadMessage();
if (readerSub.Length > 0)
{
obj.Deserialize(readerSub, true);
}
}
if ((innerNetObject.SpawnFlags & SpawnFlags.IsClientCharacter) != SpawnFlags.None)
{
if (TryGetPlayer(id, out var clientById))
{
Logger.Verbose("Spawn character");
}
else
{
Logger.Verbose("Spawn unowned character");
}
}
continue;
}
Logger.Error("Couldn't find spawnable object {0}.", objectId);
break;
}
case GameDataTag.DespawnFlag:
{
var objectNetId = reader.ReadPackedUInt32();
Logger.Verbose("> Destroy {0}", objectNetId);
break;
}
case GameDataTag.SceneChangeFlag:
{
var clientId = reader.ReadPackedInt32();
var targetScene = reader.ReadString();
Logger.Verbose("> Scene {0} to {1}", clientId, targetScene);
break;
}
case GameDataTag.ReadyFlag:
{
var clientId = reader.ReadPackedInt32();
Logger.Verbose("> IsReady {0}", clientId);
break;
}
default:
{
Logger.Debug("Bad GameData tag {0}", reader.Tag);
break;
}
}
}
}
private bool AddNetObject(InnerNetObject obj)
{
if (_allObjectsFast.ContainsKey(obj.NetId))
{
return false;
}
_allObjects.Add(obj);
_allObjectsFast.Add(obj.NetId, obj);
return true;
}
private void RemoveNetObject(InnerNetObject obj)
{
var index = _allObjects.IndexOf(obj);
if (index > -1)
{
_allObjects.RemoveAt(index);
}
_allObjectsFast.Remove(obj.NetId);
obj.NetId = uint.MaxValue;
}
}
}
+1 -77
View File
@@ -1,5 +1,4 @@
using System;
using System.Threading.Tasks;
using System.Threading.Tasks;
using Impostor.Server.Games;
using Impostor.Server.Net.Messages;
using Impostor.Shared.Innersloth.Data;
@@ -195,80 +194,5 @@ namespace Impostor.Server.Net.State
await BroadcastJoinMessage(packet, true, sender);
}
public async ValueTask HandleGameData(IMessageReader parent, IClientPlayer sender, bool toPlayer)
{
// Find target player.
IClientPlayer target = null;
if (toPlayer)
{
var targetId = parent.ReadPackedInt32();
if (!TryGetPlayer(targetId, out target))
{
// Invalid target.
return;
}
}
// Parse GameData messages.
while (parent.Position < parent.Length)
{
var reader = parent.ReadMessage();
switch (reader.Tag)
{
case GameDataTag.DataFlag:
{
var objectNetId = reader.ReadPackedUInt32();
Logger.Verbose("> Update {0}", objectNetId);
break;
}
case GameDataTag.RpcFlag:
{
var objectNetId = reader.ReadPackedUInt32();
var callId = reader.ReadByte();
Logger.Verbose("> RPC {0} {1}", objectNetId, callId);
break;
}
case GameDataTag.SpawnFlag:
{
var objectId = reader.ReadPackedUInt32();
Logger.Verbose("> Spawn {0}", objectId);
break;
}
case GameDataTag.DespawnFlag:
{
var objectNetId = reader.ReadPackedUInt32();
Logger.Verbose("> Destroy {0}", objectNetId);
break;
}
case GameDataTag.SceneChangeFlag:
{
var clientId = reader.ReadPackedInt32();
var targetScene = reader.ReadString();
Logger.Verbose("> Scene {0} to {1}", clientId, targetScene);
break;
}
case GameDataTag.ReadyFlag:
{
var clientId = reader.ReadPackedInt32();
Logger.Verbose("> IsReady {0}", clientId);
break;
}
default:
{
Logger.Debug("Bad GameData tag {0}", reader.Tag);
break;
}
}
}
}
}
}
+5 -1
View File
@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Net;
@@ -19,6 +20,7 @@ namespace Impostor.Server.Net.State
{
private static readonly ILogger Logger = Log.ForContext<Game>();
private readonly IServiceProvider _serviceProvider;
private readonly IGameManager _gameManager;
private readonly IClientManager _clientManager;
private readonly IMatchmaker _matchmaker;
@@ -26,6 +28,7 @@ namespace Impostor.Server.Net.State
private readonly HashSet<IPAddress> _bannedIps;
public Game(
IServiceProvider serviceProvider,
IGameManager gameManager,
INodeLocator nodeLocator,
IPEndPoint publicIp,
@@ -34,6 +37,7 @@ namespace Impostor.Server.Net.State
IMatchmaker matchmaker,
IClientManager clientManager)
{
_serviceProvider = serviceProvider;
_gameManager = gameManager;
_players = new ConcurrentDictionary<int, IClientPlayer>();
_bannedIps = new HashSet<IPAddress>();