Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add beta lgv races #57

Merged
merged 12 commits into from
Dec 30, 2024
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
Loading