mirror of
https://github.com/misternebula/quantum-space-buddies.git
synced 2025-02-10 03:40:01 +00:00
Merge pull request #163 from Raicuparta/alek/world-object
base class for world objects, wrapper for geysers
This commit is contained in:
commit
3615996e31
@ -1,5 +1,6 @@
|
||||
using QSB.Events;
|
||||
using QSB.Messaging;
|
||||
using QSB.WorldSync;
|
||||
|
||||
namespace QSB.ElevatorSync
|
||||
{
|
||||
@ -9,14 +10,14 @@ namespace QSB.ElevatorSync
|
||||
|
||||
public override void SetupListener()
|
||||
{
|
||||
GlobalMessenger<ElevatorDirection, string>.AddListener(EventNames.QSBStartLift, (direction, elevatorName) => SendEvent(CreateMessage(direction, elevatorName)));
|
||||
GlobalMessenger<int, ElevatorDirection>.AddListener(EventNames.QSBStartLift, (id, direction) => SendEvent(CreateMessage(id, direction)));
|
||||
}
|
||||
|
||||
private ElevatorMessage CreateMessage(ElevatorDirection direction, string elevatorName) => new ElevatorMessage
|
||||
private ElevatorMessage CreateMessage(int id, ElevatorDirection direction) => new ElevatorMessage
|
||||
{
|
||||
SenderId = PlayerRegistry.LocalPlayer.NetId,
|
||||
Direction = direction,
|
||||
ElevatorName = elevatorName
|
||||
ObjectId = id
|
||||
};
|
||||
|
||||
public override void OnReceiveRemote(ElevatorMessage message)
|
||||
@ -25,7 +26,7 @@ namespace QSB.ElevatorSync
|
||||
{
|
||||
return;
|
||||
}
|
||||
PlayerRegistry.GetElevatorController(message.ElevatorName).RemoteCall(message.Direction);
|
||||
WorldRegistry.GetObject<QSBElevator>(message.ObjectId).RemoteCall(message.Direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,34 @@
|
||||
using UnityEngine;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.ElevatorSync
|
||||
{
|
||||
public class ElevatorManager : MonoBehaviour
|
||||
{
|
||||
public static ElevatorManager Instance { get; private set; }
|
||||
|
||||
private List<Elevator> _elevators;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
QSB.Helper.Events.Subscribe<Elevator>(OWML.Common.Events.AfterAwake);
|
||||
QSB.Helper.Events.Event += OnEvent;
|
||||
Instance = this;
|
||||
|
||||
LoadManager.OnCompleteSceneLoad += OnCompleteSceneLoad;
|
||||
|
||||
QSB.Helper.HarmonyHelper.AddPostfix<Elevator>("StartLift", typeof(ElevatorPatches), nameof(ElevatorPatches.StartLift));
|
||||
}
|
||||
|
||||
private void OnEvent(MonoBehaviour behaviour, OWML.Common.Events ev)
|
||||
private void OnCompleteSceneLoad(OWScene oldScene, OWScene newScene)
|
||||
{
|
||||
if (behaviour is Elevator elevator && ev == OWML.Common.Events.AfterAwake)
|
||||
_elevators = Resources.FindObjectsOfTypeAll<Elevator>().ToList();
|
||||
for (var id = 0; id < _elevators.Count; id++)
|
||||
{
|
||||
var elevatorController = gameObject.AddComponent<ElevatorController>();
|
||||
elevatorController.Init(elevator);
|
||||
var elevatorController = new QSBElevator();
|
||||
elevatorController.Init(_elevators[id], id);
|
||||
}
|
||||
}
|
||||
|
||||
public int GetId(Elevator elevator) => _elevators.IndexOf(elevator);
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,22 @@
|
||||
using QSB.Messaging;
|
||||
using QSB.WorldSync;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace QSB.ElevatorSync
|
||||
{
|
||||
public class ElevatorMessage : PlayerMessage
|
||||
public class ElevatorMessage : WorldObjectMessage
|
||||
{
|
||||
public ElevatorDirection Direction { get; set; }
|
||||
public string ElevatorName { get; set; }
|
||||
|
||||
public override void Deserialize(NetworkReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
Direction = (ElevatorDirection)reader.ReadInt32();
|
||||
ElevatorName = reader.ReadString();
|
||||
}
|
||||
|
||||
public override void Serialize(NetworkWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write((int)Direction);
|
||||
writer.Write(ElevatorName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ namespace QSB.ElevatorSync
|
||||
{
|
||||
var isGoingUp = __instance.GetValue<bool>("_goingToTheEnd");
|
||||
var direction = isGoingUp ? ElevatorDirection.Up : ElevatorDirection.Down;
|
||||
GlobalMessenger<ElevatorDirection, string>.FireEvent(EventNames.QSBStartLift, direction, __instance.name);
|
||||
var id = ElevatorManager.Instance.GetId(__instance);
|
||||
GlobalMessenger<int, ElevatorDirection>.FireEvent(EventNames.QSBStartLift, id, direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
using OWML.ModHelper.Events;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.ElevatorSync
|
||||
{
|
||||
public class ElevatorController : MonoBehaviour
|
||||
public class QSBElevator : WorldObject
|
||||
{
|
||||
public string ElevatorName => _elevator.name;
|
||||
|
||||
private Elevator _elevator;
|
||||
private Vector3 _startLocalPos;
|
||||
private Vector3 _endLocalPos;
|
||||
@ -15,10 +15,16 @@ namespace QSB.ElevatorSync
|
||||
private OWAudioSource _owAudioSourceOneShot;
|
||||
private OWAudioSource _owAudioSourceLP;
|
||||
|
||||
public void Init(Elevator elevator)
|
||||
public void Init(Elevator elevator, int id)
|
||||
{
|
||||
PlayerRegistry.ElevatorControllers.Add(this);
|
||||
_elevator = elevator;
|
||||
ObjectId = id;
|
||||
WorldRegistry.WorldObjects.Add(this);
|
||||
UnityHelper.Instance.RunWhen(() => _elevator.GetValue<SingleInteractionVolume>("_interactVolume") != null, InitValues);
|
||||
}
|
||||
|
||||
private void InitValues()
|
||||
{
|
||||
_startLocalPos = _elevator.GetValue<Vector3>("_startLocalPos");
|
||||
_endLocalPos = _elevator.GetValue<Vector3>("_endLocalPos");
|
||||
_interactVolume = _elevator.GetValue<SingleInteractionVolume>("_interactVolume");
|
@ -25,9 +25,6 @@ namespace QSB.Events
|
||||
DebugLog.ToAll(string.Format(deathMessage, playerName));
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(PlayerDeathMessage message)
|
||||
{
|
||||
OnReceiveRemote(message);
|
||||
}
|
||||
public override void OnReceiveLocal(PlayerDeathMessage message) => OnReceiveRemote(message);
|
||||
}
|
||||
}
|
||||
|
@ -32,10 +32,7 @@ namespace QSB.Events
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(PlayerLeaveMessage message)
|
||||
{
|
||||
OnReceiveRemote(message);
|
||||
}
|
||||
public override void OnReceiveLocal(PlayerLeaveMessage message) => OnReceiveRemote(message);
|
||||
|
||||
private void DestroyObject(uint objectId)
|
||||
{
|
||||
|
@ -39,9 +39,6 @@ namespace QSB.Events
|
||||
transformSync.ReferenceTransform = sector.transform;
|
||||
}
|
||||
|
||||
public override void OnReceiveLocal(SectorMessage message)
|
||||
{
|
||||
OnReceiveRemote(message);
|
||||
}
|
||||
public override void OnReceiveLocal(SectorMessage message) => OnReceiveRemote(message);
|
||||
}
|
||||
}
|
||||
|
@ -8,18 +8,15 @@ namespace QSB.GeyserSync
|
||||
{
|
||||
public override MessageType Type => MessageType.Geyser;
|
||||
|
||||
public static SyncObjects ObjectType => SyncObjects.Geysers;
|
||||
|
||||
public override void SetupListener()
|
||||
{
|
||||
GlobalMessenger<GeyserController, bool>.AddListener(EventNames.QSBGeyserState, (controller, state) => SendEvent(CreateMessage(controller, state)));
|
||||
GlobalMessenger<int, bool>.AddListener(EventNames.QSBGeyserState, (id, state) => SendEvent(CreateMessage(id, state)));
|
||||
}
|
||||
|
||||
private GeyserMessage CreateMessage(GeyserController controller, bool state) => new GeyserMessage
|
||||
private GeyserMessage CreateMessage(int id, bool state) => new GeyserMessage
|
||||
{
|
||||
SenderId = PlayerRegistry.LocalPlayer.NetId,
|
||||
ObjectID = WorldRegistry.GetObjectID(ObjectType, controller),
|
||||
ObjectType = ObjectType,
|
||||
ObjectId = id,
|
||||
State = state
|
||||
};
|
||||
|
||||
@ -29,14 +26,8 @@ namespace QSB.GeyserSync
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (message.State)
|
||||
{
|
||||
WorldRegistry.GeyserControllers[message.ObjectID].ActivateGeyser();
|
||||
}
|
||||
else
|
||||
{
|
||||
WorldRegistry.GeyserControllers[message.ObjectID].DeactivateGeyser();
|
||||
}
|
||||
var geyser = WorldRegistry.GetObject<QSBGeyser>(message.ObjectId);
|
||||
geyser.SetState(message.State);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
32
QSB/GeyserSync/GeyserManager.cs
Normal file
32
QSB/GeyserSync/GeyserManager.cs
Normal file
@ -0,0 +1,32 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace QSB.GeyserSync
|
||||
{
|
||||
public class GeyserManager : MonoBehaviour
|
||||
{
|
||||
public static GeyserManager Instance { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
|
||||
LoadManager.OnCompleteSceneLoad += OnCompleteSceneLoad;
|
||||
}
|
||||
|
||||
private void OnCompleteSceneLoad(OWScene oldScene, OWScene newScene)
|
||||
{
|
||||
var geyserControllers = Resources.FindObjectsOfTypeAll<GeyserController>();
|
||||
for (var id = 0; id < geyserControllers.Length; id++)
|
||||
{
|
||||
var geyser = new QSBGeyser();
|
||||
geyser.Init(geyserControllers[id], id);
|
||||
}
|
||||
}
|
||||
|
||||
public void EmptyUpdate()
|
||||
{
|
||||
QSB.Helper.HarmonyHelper.EmptyMethod<GeyserController>("Update");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using QSB.Messaging;
|
||||
using QSB.WorldSync;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace QSB.GeyserSync
|
||||
|
41
QSB/GeyserSync/QSBGeyser.cs
Normal file
41
QSB/GeyserSync/QSBGeyser.cs
Normal file
@ -0,0 +1,41 @@
|
||||
using QSB.Events;
|
||||
using QSB.WorldSync;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace QSB.GeyserSync
|
||||
{
|
||||
public class QSBGeyser : WorldObject
|
||||
{
|
||||
private GeyserController _geyserController;
|
||||
|
||||
public void Init(GeyserController geyserController, int id)
|
||||
{
|
||||
ObjectId = id;
|
||||
WorldRegistry.WorldObjects.Add(this);
|
||||
_geyserController = geyserController;
|
||||
|
||||
geyserController.OnGeyserActivateEvent += () => HandleEvent(true);
|
||||
geyserController.OnGeyserDeactivateEvent += () => HandleEvent(false);
|
||||
}
|
||||
|
||||
private void HandleEvent(bool state)
|
||||
{
|
||||
if (NetworkServer.active)
|
||||
{
|
||||
GlobalMessenger<int, bool>.FireEvent(EventNames.QSBGeyserState, ObjectId, state);
|
||||
}
|
||||
}
|
||||
|
||||
public void SetState(bool state)
|
||||
{
|
||||
if (state)
|
||||
{
|
||||
_geyserController.ActivateGeyser();
|
||||
}
|
||||
else
|
||||
{
|
||||
_geyserController.DeactivateGeyser();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -2,7 +2,6 @@
|
||||
using System.Linq;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Animation;
|
||||
using QSB.ElevatorSync;
|
||||
using QSB.Messaging;
|
||||
|
||||
namespace QSB
|
||||
@ -16,8 +15,6 @@ namespace QSB
|
||||
public static List<TransformSync.TransformSync> LocalTransformSyncs => TransformSyncs.Where(t => t != null && t.hasAuthority).ToList();
|
||||
public static List<AnimationSync> AnimationSyncs { get; } = new List<AnimationSync>();
|
||||
|
||||
public static List<ElevatorController> ElevatorControllers { get; } = new List<ElevatorController>();
|
||||
|
||||
public static PlayerInfo CreatePlayer(uint id)
|
||||
{
|
||||
if (PlayerExists(id))
|
||||
@ -51,7 +48,7 @@ namespace QSB
|
||||
player.IsReady = message.PlayerReady;
|
||||
player.State = message.PlayerState;
|
||||
|
||||
if (LocalPlayer.IsReady == true)
|
||||
if (LocalPlayer.IsReady)
|
||||
{
|
||||
player.UpdateStateObjects();
|
||||
}
|
||||
@ -67,10 +64,5 @@ namespace QSB
|
||||
return AnimationSyncs.FirstOrDefault(x => x != null && x.netId.Value == id);
|
||||
}
|
||||
|
||||
public static ElevatorController GetElevatorController(string name)
|
||||
{
|
||||
return ElevatorControllers.FirstOrDefault(x => x != null && x.ElevatorName == name);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,6 @@ using QSB.GeyserSync;
|
||||
using QSB.Utility;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace QSB
|
||||
{
|
||||
@ -32,11 +31,10 @@ namespace QSB
|
||||
gameObject.AddComponent<DebugActions>();
|
||||
gameObject.AddComponent<UnityHelper>();
|
||||
gameObject.AddComponent<ElevatorManager>();
|
||||
gameObject.AddComponent<GeyserManager>();
|
||||
|
||||
GlobalMessenger.AddListener(EventNames.RestartTimeLoop, OnLoopStart);
|
||||
GlobalMessenger.AddListener(EventNames.WakeUp, OnWakeUp);
|
||||
|
||||
LoadManager.OnCompleteSceneLoad += OnSceneLoad;
|
||||
}
|
||||
|
||||
private void OnWakeUp()
|
||||
@ -50,11 +48,6 @@ namespace QSB
|
||||
WokenUp = false;
|
||||
}
|
||||
|
||||
private void OnSceneLoad(OWScene oldScene, OWScene newScene)
|
||||
{
|
||||
WorldRegistry.GenerateComponentList();
|
||||
}
|
||||
|
||||
public override void Configure(IModConfig config)
|
||||
{
|
||||
DefaultServerIP = config.GetSettingsValue<string>("defaultServerIP");
|
||||
|
@ -83,7 +83,9 @@
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.AnimationModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.AudioModule, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
|
||||
<Reference Include="UnityEngine.AudioModule">
|
||||
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.AudioModule.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="UnityEngine.CoreModule">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>$(GameDir)\OuterWilds_Data\Managed\UnityEngine.CoreModule.dll</HintPath>
|
||||
@ -118,7 +120,7 @@
|
||||
<Compile Include="Animation\AnimFloatParam.cs" />
|
||||
<Compile Include="Animation\AnimTrigger.cs" />
|
||||
<Compile Include="ElevatorSync\ElevatorDirection.cs" />
|
||||
<Compile Include="ElevatorSync\ElevatorController.cs" />
|
||||
<Compile Include="ElevatorSync\QSBElevator.cs" />
|
||||
<Compile Include="ElevatorSync\ElevatorEvent.cs" />
|
||||
<Compile Include="ElevatorSync\ElevatorManager.cs" />
|
||||
<Compile Include="ElevatorSync\ElevatorMessage.cs" />
|
||||
@ -135,7 +137,9 @@
|
||||
<Compile Include="Events\PlayerSuitEvent.cs" />
|
||||
<Compile Include="Events\ServerTimeEvent.cs" />
|
||||
<Compile Include="GeyserSync\GeyserEvent.cs" />
|
||||
<Compile Include="GeyserSync\GeyserManager.cs" />
|
||||
<Compile Include="GeyserSync\GeyserMessage.cs" />
|
||||
<Compile Include="GeyserSync\QSBGeyser.cs" />
|
||||
<Compile Include="Messaging\AnimTriggerMessage.cs" />
|
||||
<Compile Include="Messaging\PlayerDeathMessage.cs" />
|
||||
<Compile Include="Messaging\PlayerLeaveMessage.cs" />
|
||||
@ -145,7 +149,7 @@
|
||||
<Compile Include="Events\QSBEvent.cs" />
|
||||
<Compile Include="Messaging\PlayerJoinMessage.cs" />
|
||||
<Compile Include="Messaging\ToggleMessage.cs" />
|
||||
<Compile Include="Messaging\WorldObjectMessage.cs" />
|
||||
<Compile Include="WorldSync\WorldObjectMessage.cs" />
|
||||
<Compile Include="Tools\QSBFlashlight.cs" />
|
||||
<Compile Include="Tools\QSBProbe.cs" />
|
||||
<Compile Include="Tools\QSBTool.cs" />
|
||||
@ -184,8 +188,8 @@
|
||||
<Compile Include="TransformSync\PlayerTransformSync.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="Utility\UnityHelper.cs" />
|
||||
<Compile Include="WorldRegistry.cs" />
|
||||
<Compile Include="WorldSync\SyncObjects.cs" />
|
||||
<Compile Include="WorldSync\WorldRegistry.cs" />
|
||||
<Compile Include="WorldSync\WorldObject.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="default-config.json" />
|
||||
|
@ -3,6 +3,7 @@ using System.Linq;
|
||||
using OWML.ModHelper.Events;
|
||||
using QSB.Animation;
|
||||
using QSB.Events;
|
||||
using QSB.GeyserSync;
|
||||
using QSB.TimeSync;
|
||||
using QSB.TransformSync;
|
||||
using QSB.Utility;
|
||||
@ -124,7 +125,7 @@ namespace QSB
|
||||
if (NetworkClient.active && !NetworkServer.active)
|
||||
{
|
||||
gameObject.AddComponent<Events.PlayerState>();
|
||||
QSB.Helper.HarmonyHelper.EmptyMethod<GeyserController>("Update");
|
||||
GeyserManager.Instance.EmptyUpdate();
|
||||
}
|
||||
|
||||
_canEditName = false;
|
||||
|
@ -1,39 +0,0 @@
|
||||
using QSB.Events;
|
||||
using QSB.Utility;
|
||||
using QSB.WorldSync;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace QSB
|
||||
{
|
||||
public static class WorldRegistry
|
||||
{
|
||||
public static List<GeyserController> GeyserControllers = new List<GeyserController>();
|
||||
|
||||
public static void GenerateComponentList()
|
||||
{
|
||||
GeyserControllers = Resources.FindObjectsOfTypeAll<GeyserController>().ToList();
|
||||
|
||||
foreach (var component in GeyserControllers)
|
||||
{
|
||||
if (NetworkServer.active)
|
||||
{
|
||||
component.OnGeyserActivateEvent += () => GlobalMessenger<GeyserController, bool>.FireEvent(EventNames.QSBGeyserState, component, true);
|
||||
component.OnGeyserDeactivateEvent += () => GlobalMessenger<GeyserController, bool>.FireEvent(EventNames.QSBGeyserState, component, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetObjectID(SyncObjects type, object component)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case SyncObjects.Geysers:
|
||||
return GeyserControllers.FindIndex(x => x == component);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace QSB.WorldSync
|
||||
{
|
||||
public enum SyncObjects
|
||||
{
|
||||
Geysers
|
||||
}
|
||||
}
|
7
QSB/WorldSync/WorldObject.cs
Normal file
7
QSB/WorldSync/WorldObject.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace QSB.WorldSync
|
||||
{
|
||||
public class WorldObject
|
||||
{
|
||||
public int ObjectId { get; protected set; }
|
||||
}
|
||||
}
|
@ -1,25 +1,22 @@
|
||||
using QSB.WorldSync;
|
||||
using QSB.Messaging;
|
||||
using UnityEngine.Networking;
|
||||
|
||||
namespace QSB.Messaging
|
||||
namespace QSB.WorldSync
|
||||
{
|
||||
public class WorldObjectMessage : PlayerMessage
|
||||
{
|
||||
public SyncObjects ObjectType { get; set; }
|
||||
public int ObjectID { get; set; }
|
||||
public int ObjectId { get; set; }
|
||||
|
||||
public override void Deserialize(NetworkReader reader)
|
||||
{
|
||||
base.Deserialize(reader);
|
||||
ObjectType = (SyncObjects)reader.ReadInt32();
|
||||
ObjectID = reader.ReadInt32();
|
||||
ObjectId = reader.ReadInt32();
|
||||
}
|
||||
|
||||
public override void Serialize(NetworkWriter writer)
|
||||
{
|
||||
base.Serialize(writer);
|
||||
writer.Write((int)ObjectType);
|
||||
writer.Write(ObjectID);
|
||||
writer.Write(ObjectId);
|
||||
}
|
||||
}
|
||||
}
|
15
QSB/WorldSync/WorldRegistry.cs
Normal file
15
QSB/WorldSync/WorldRegistry.cs
Normal file
@ -0,0 +1,15 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace QSB.WorldSync
|
||||
{
|
||||
public static class WorldRegistry
|
||||
{
|
||||
public static List<WorldObject> WorldObjects { get; } = new List<WorldObject>();
|
||||
|
||||
public static T GetObject<T>(int id) where T : WorldObject
|
||||
{
|
||||
return WorldObjects.OfType<T>().FirstOrDefault(x => x.ObjectId == id);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user