Skip to content

Commit

Permalink
Add beta lgv races (#57)
Browse files Browse the repository at this point in the history
* Add chat commands

* Update settings after namespace changes, add ZoneId to config

* Add basic AreaVisualData

* Update grpc stream

* Allow checking if entity is scoped per player, automounting vehicles

* Fix typos

* Add lgv races, update naming in repulsor

* Handle adding personal map markers

* Update field name

* Fix CI warnings

* Update AeroMessages

* Increase scoping of finish line to fix sh -> copa
  • Loading branch information
SzymonKaminski authored Dec 30, 2024
1 parent dca7d76 commit 528b04a
Show file tree
Hide file tree
Showing 38 changed files with 1,302 additions and 119 deletions.
1 change: 1 addition & 0 deletions UdpHosts/GameServer/App.Default.config
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<add key="Port" value="25001"/>
<add key="GrpcChannelAddress" value="http://localhost:5201"/>
<add key="StaticDBPath" value="C:\Program Files\Steam\steamapps\common\Firefall\system\db\clientdb.sd2"/>
<add key="ZoneId" value="448"/>
<add key="MapsPath" value=""/>
<add key="LoadMapsCollision" value="false"/>
<add key="LoadZoneEntities" value="true"/>
Expand Down
13 changes: 11 additions & 2 deletions UdpHosts/GameServer/Controllers/Character/BaseController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@
using GameServer.Data;
using GameServer.Data.SDB;
using GameServer.Data.SDB.Records.customdata;
using GameServer.Entities;
using GameServer.Entities.Character;
using GameServer.Entities.Turret;
using GameServer.Entities.Vehicle;
using GameServer.Enums.GSS.Character;
using GameServer.Extensions;
using GameServer.Packets;
using GameServer.Systems.Encounters;
using Serilog;
using static AeroMessages.GSS.V66.Character.Command.NonDevDebugCommand;
using LoadoutVisualType = AeroMessages.GSS.V66.Character.LoadoutConfig_Visual.LoadoutVisualType;
Expand Down Expand Up @@ -371,12 +373,13 @@ public void ExitAttachmentRequest(INetworkClient client, IPlayer player, ulong e
}

var character = player.CharacterEntity;
var entity = character.AttachedToEntity;

if (character.AttachedToEntity is VehicleEntity vehicle)
if (entity is VehicleEntity vehicle)
{
vehicle.RemoveOccupant(character);
}
else if (character.AttachedToEntity is TurretEntity turret)
else if (entity is TurretEntity turret)
{
if (turret.Parent is VehicleEntity parentVehicle)
{
Expand All @@ -393,6 +396,12 @@ public void ExitAttachmentRequest(INetworkClient client, IPlayer player, ulong e
var response = new ExitingAttachment() { Direction = new Vector3(-0.5f, -0.5f, -0.47f) };

client.NetChannels[ChannelType.ReliableGss].SendMessage(response, character.EntityId);

if (entity is BaseEntity { Encounter.Instance: IExitAttachmentHandler handler } baseEntity
&& baseEntity.Encounter.Handles(EncounterComponent.Event.ExitAttachment))
{
handler.OnExitAttachment(baseEntity, (INetworkPlayer)player);
}
}

[MessageID((byte)Commands.SeatChangeRequest)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using AeroMessages.Common;
using AeroMessages.GSS.V66.AreaVisualData.View;

namespace GameServer.Entities.AreaVisualData;

public sealed class AreaVisualDataEntity : BaseEntity
{
public AreaVisualDataEntity(IShard shard, ulong eid)
: base(shard, eid)
{
AeroEntityId = new EntityId() { Backing = EntityId, ControllerId = Controller.AreaVisualData };
InitFields();
InitViews();
}

public ObserverView AreaVisualData_ObserverView { get; set; }
public ParticleEffectsView AreaVisualData_ParticleEffectsView { get; set; }
public MapMarkerView AreaVisualData_MapMarkerView { get; set; }
public TinyObjectView AreaVisualData_TinyObjectView { get; set; }
public LootObjectView AreaVisualData_LootObjectView { get; set; }
public ForceShieldView AreaVisualData_ForceShieldView { get; set; }

private void InitFields()
{
}

private void InitViews()
{
AreaVisualData_ObserverView = new ObserverView() { PositionProp = Position };
AreaVisualData_ParticleEffectsView = new ParticleEffectsView();
}
}
57 changes: 56 additions & 1 deletion UdpHosts/GameServer/Entities/Character/CharacterEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using GameServer.Data.SDB;
using GameServer.Data.SDB.Records.customdata;
using GameServer.Enums;
using GameServer.Systems.Encounters;
using GameServer.Test;
using GrpcGameServerAPIClient;
using LoadoutVisualType = AeroMessages.GSS.V66.Character.LoadoutConfig_Visual.LoadoutVisualType;
Expand All @@ -22,8 +23,11 @@ namespace GameServer.Entities.Character;
/// <summary>
/// Base Character
/// </summary>
public partial class CharacterEntity : BaseAptitudeEntity, IAptitudeTarget
public sealed partial class CharacterEntity : BaseAptitudeEntity, IAptitudeTarget
{
public const byte MaxMapMarkerCount = 64;
private MapMarkerState[] MapMarkers = new MapMarkerState[MaxMapMarkerCount];

public CharacterEntity(IShard shard, ulong eid)
: base(shard, eid)
{
Expand Down Expand Up @@ -1043,6 +1047,51 @@ public void HackClearAllStatusEffects()
Shard.EntityMan.FlushChanges(this);
}

public void AddMapMarker(ulong encounterId, PersonalMapMarkerData data)
{
byte firstFreeIndex = InvalidIndex;
for (byte i = 0; i < MaxMapMarkerCount; i++)
{
if (MapMarkers[i] == null)
{
firstFreeIndex = i;
break;
}
}

if (firstFreeIndex == InvalidIndex)
{
Console.WriteLine("AddMapMarkers but there are too many active map markers!");
firstFreeIndex = MaxMapMarkerCount - 1; // Lets not crash
}

var state = new MapMarkerState
{
EncounterId = data.EncounterId,
EncounterMarkerId = data.EncounterMarkerId,
};

MapMarkers[firstFreeIndex] = state;

SetMapMarker(firstFreeIndex, data);
}

public void RemoveEncounterMapMarkers(ulong encounterId)
{
for (byte i = 0; i < MapMarkers.Length; i++)
{
if (MapMarkers[i] == null)
{
continue;
}

if (MapMarkers[i].EncounterId.Backing == encounterId)
{
SetMapMarker(i, null);
}
}
}

public void SetCombatFlags(CombatFlagsData value)
{
Character_CombatController.CombatFlagsProp = value;
Expand Down Expand Up @@ -1551,6 +1600,12 @@ private ulong GetCurrentPermissionsValue()
return result;
}

private void SetMapMarker(byte index, PersonalMapMarkerData? data)
{
Character_MissionAndMarkerController?.GetType().GetProperty($"PersonalMapMarkers_{index}Prop")
?.SetValue(Character_MissionAndMarkerController, data);
}

public class ActiveStatModifier
{
public StatModifierIdentifier Stat { get; set; }
Expand Down
5 changes: 5 additions & 0 deletions UdpHosts/GameServer/Entities/EncounterComponent.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using GameServer.StaticDB.Records.customdata.Encounters;
using GameServer.Systems.Encounters;

namespace GameServer.Entities;
Expand All @@ -11,10 +12,14 @@ public enum Event : uint
Signal = 1 << 0,
Interaction = 1 << 1,
Donation = 1 << 2,
ExitAttachment = 1 << 3,
Proximity = 1 << 4,
}

public ulong EncounterId { get; set; }
public IEncounter Instance { get; set; }
public uint ProximityDistance { get; set; } = 0;
public IEncounterDef SpawnDef { get; set; }
public Event Events { get; set; }
public bool Handles(Event type) => Events.HasFlag(type);
public void StartHandling(Event type) => Events |= type;
Expand Down
7 changes: 6 additions & 1 deletion UdpHosts/GameServer/Entities/Vehicle/VehicleEntity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ public class SeatConfig
public byte TurretIndex;
}

public class VehicleEntity : BaseAptitudeEntity, IAptitudeTarget
public sealed class VehicleEntity : BaseAptitudeEntity, IAptitudeTarget
{
public VehicleEntity(IShard shard, ulong eid)
: base(shard, eid)
Expand Down Expand Up @@ -503,6 +503,11 @@ public bool IsEntitySeated(IEntity entity)

public override bool IsInteractable()
{
if (Encounter != null && !Encounter.Handles(EncounterComponent.Event.Interaction))
{
return false;
}

foreach (var seat in Occupants.Values)
{
if (seat.Occupant == null && seat.Role != AttachmentRole.None)
Expand Down
2 changes: 1 addition & 1 deletion UdpHosts/GameServer/Enums/GSS/Character/Commands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ internal enum Commands : byte
RequestTeleport = 210,
RequestFrameLevelReset = 211,
LeaveEncounterParty = 212,
JoinSquadLeadersAr = 213,
JoinSquadLeadersArc = 213,
LeaveArc = 214,
JobLedgerOperation = 215,
SeatChangeRequest = 216,
Expand Down
2 changes: 1 addition & 1 deletion UdpHosts/GameServer/Enums/GSS/Character/Events.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ internal enum Events
ResourceNodeCompletedEvent = 137,
FoundResourceAreas = 138,
GeographicalReportResponse = 139,
ResourceLocationInfosRespons = 140,
ResourceLocationInfosResponse = 140,
UiNamedVariableUpdate = 141,
DuelNotification = 142,
NewUiQuery = 143,
Expand Down
125 changes: 65 additions & 60 deletions UdpHosts/GameServer/GRPC/GRPCService.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
using GameServer.GRPC.EventHandlers;
using Grpc.Core;
Expand All @@ -11,6 +13,7 @@ public static class GRPCService
{
private static GrpcChannel _channel;
private static GameServerAPI.GameServerAPIClient _client;
private static AsyncDuplexStreamingCall<Command, Event> _stream;

public static void Init(string address)
{
Expand All @@ -28,71 +31,73 @@ public static async Task<CharacterAndBattleframeVisuals> GetCharacterAndBattlefr
return await _client.GetCharacterAndBattleframeVisualsAsync(new CharacterID { ID = characterId });
}

public static async Task<Empty> SaveCharacterSessionDataAsync(ulong characterId, uint zoneId, uint outpostId, uint timePlayed)
public static async Task SaveCharacterSessionDataAsync(ulong characterId, uint zoneId, uint outpostId, uint timePlayed)
{
return await _client.SaveCharacterGameSessionDataAsync(new GameSessionData()
{
CharacterId = characterId,
ZoneId = zoneId,
OutpostId = outpostId,
TimePlayed = timePlayed
});
var data = new SaveGameSessionData()
{
CharacterId = characterId, ZoneId = zoneId, OutpostId = outpostId, TimePlayed = timePlayed
};

await SendCommandAsync(new Command() { SaveGameSessionData = data });
}

public static async Task ListenAsync(ConcurrentDictionary<uint, INetworkPlayer> clientMap)
public static async Task SendCommandAsync(Command command)
{
using var listen = _client.Listen(new Empty());
await _stream.RequestStream.WriteAsync(command);
}

var reader =
Task.Run(async () =>
{
await foreach (var evt in listen.ResponseStream.ReadAllAsync())
{
switch (evt.SubtypeCase)
{
case Event.SubtypeOneofCase.ArmyApplicationApproved:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationApproved, clientMap);
break;
case Event.SubtypeOneofCase.ArmyApplicationReceived:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationReceived, clientMap);
break;
case Event.SubtypeOneofCase.ArmyApplicationRejected:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationRejected, clientMap);
break;
case Event.SubtypeOneofCase.ArmyApplicationsUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationsUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyIdChanged:
ArmyEventHandler.HandleEvent(evt.ArmyIdChanged, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInfoUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyInfoUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInviteApproved:
ArmyEventHandler.HandleEvent(evt.ArmyInviteApproved, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInviteReceived:
ArmyEventHandler.HandleEvent(evt.ArmyInviteReceived, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInviteRejected:
ArmyEventHandler.HandleEvent(evt.ArmyInviteRejected, clientMap);
break;
case Event.SubtypeOneofCase.ArmyMembersUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyMembersUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyRanksUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyRanksUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyTagUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyTagUpdated, clientMap);
break;
case Event.SubtypeOneofCase.CharacterVisualsUpdated:
CharacterEventHandler.HandleEvent(evt.CharacterVisualsUpdated, clientMap);
break;
}
}
});
public static async Task ListenAsync(ConcurrentDictionary<uint, INetworkPlayer> clientMap, CancellationToken ct)
{
_stream = _client.Stream();

await reader;
await foreach (var evt in _stream.ResponseStream.ReadAllAsync(ct))
{
Console.WriteLine(evt);
switch (evt.SubtypeCase)
{
case Event.SubtypeOneofCase.ArmyApplicationApproved:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationApproved, clientMap);
break;
case Event.SubtypeOneofCase.ArmyApplicationReceived:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationReceived, clientMap);
break;
case Event.SubtypeOneofCase.ArmyApplicationRejected:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationRejected, clientMap);
break;
case Event.SubtypeOneofCase.ArmyApplicationsUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyApplicationsUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyIdChanged:
ArmyEventHandler.HandleEvent(evt.ArmyIdChanged, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInfoUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyInfoUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInviteApproved:
ArmyEventHandler.HandleEvent(evt.ArmyInviteApproved, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInviteReceived:
ArmyEventHandler.HandleEvent(evt.ArmyInviteReceived, clientMap);
break;
case Event.SubtypeOneofCase.ArmyInviteRejected:
ArmyEventHandler.HandleEvent(evt.ArmyInviteRejected, clientMap);
break;
case Event.SubtypeOneofCase.ArmyMembersUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyMembersUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyRanksUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyRanksUpdated, clientMap);
break;
case Event.SubtypeOneofCase.ArmyTagUpdated:
ArmyEventHandler.HandleEvent(evt.ArmyTagUpdated, clientMap);
break;
case Event.SubtypeOneofCase.CharacterVisualsUpdated:
CharacterEventHandler.HandleEvent(evt.CharacterVisualsUpdated, clientMap);
break;
case Event.SubtypeOneofCase.None:
default:
break;
}
}
}
}
Loading

0 comments on commit 528b04a

Please sign in to comment.