Init Homebase
This commit is contained in:
@@ -34,6 +34,12 @@ namespace ProjectM.Server
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
var spawner = SystemAPI.GetSingleton<PlayerSpawner>();
|
||||
|
||||
// M5 home base: re-root the spawn ring on the baked BaseAnchor when present; fall back
|
||||
// to the spawner's SpawnPoint if the base subscene hasn't streamed in yet.
|
||||
var center = spawner.SpawnPoint;
|
||||
if (SystemAPI.TryGetSingleton<BaseAnchor>(out var baseAnchor))
|
||||
center = BaseGridMath.PlotCenter(baseAnchor);
|
||||
var ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||
|
||||
foreach (var (receive, requestEntity) in
|
||||
@@ -45,7 +51,7 @@ namespace ProjectM.Server
|
||||
var networkId = SystemAPI.GetComponent<NetworkId>(connection);
|
||||
|
||||
var player = ecb.Instantiate(spawner.PlayerPrefab);
|
||||
ecb.SetComponent(player, LocalTransform.FromPosition(spawner.SpawnPoint + PlayerSpawnMath.SpawnOffset(networkId.Value, spawner.SpawnRingRadius, spawner.RingSlots)));
|
||||
ecb.SetComponent(player, LocalTransform.FromPosition(center + PlayerSpawnMath.SpawnOffset(networkId.Value, spawner.SpawnRingRadius, spawner.RingSlots)));
|
||||
ecb.SetComponent(player, new GhostOwner { NetworkId = networkId.Value });
|
||||
|
||||
// Auto-despawn the player when its owning connection is removed.
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b28010c047f72f4b8d242ee1f4351cd
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,51 @@
|
||||
using ProjectM.Simulation;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.Transforms;
|
||||
|
||||
namespace ProjectM.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Server-only, one-shot spawner for the shared home-base storage container (mirrors
|
||||
/// UpgradePickupSpawnSystem). On its first update it reads the baked <see cref="StorageSpawner"/>
|
||||
/// singleton and the <see cref="BaseAnchor"/>, instantiates the container ghost at the cell center
|
||||
/// (<see cref="BaseGridMath.CellToWorld"/>), then destroys the spawner singleton so the system idles
|
||||
/// (spawned exactly once). Runs in the default SimulationSystemGroup (NOT the prediction loop); the
|
||||
/// container replicates to clients as an ownerless interpolated ghost. The container is intentionally
|
||||
/// NOT linked to any connection's LinkedEntityGroup, so it persists across player disconnects.
|
||||
/// </summary>
|
||||
[BurstCompile]
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
public partial struct SharedStorageSpawnSystem : ISystem
|
||||
{
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
state.RequireForUpdate<StorageSpawner>();
|
||||
state.RequireForUpdate<BaseAnchor>();
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
var spawnerEntity = SystemAPI.GetSingletonEntity<StorageSpawner>();
|
||||
var spawner = SystemAPI.GetComponent<StorageSpawner>(spawnerEntity);
|
||||
var anchor = SystemAPI.GetSingleton<BaseAnchor>();
|
||||
|
||||
var ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||
|
||||
if (spawner.Prefab != Entity.Null)
|
||||
{
|
||||
var container = ecb.Instantiate(spawner.Prefab);
|
||||
var position = BaseGridMath.CellToWorld(anchor, spawner.Cell);
|
||||
ecb.SetComponent(container, LocalTransform.FromPosition(position));
|
||||
}
|
||||
|
||||
// One-shot: remove the spawner so RequireForUpdate fails and the system idles.
|
||||
ecb.DestroyEntity(spawnerEntity);
|
||||
|
||||
ecb.Playback(state.EntityManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c60c2c14e48ea0c45858cf0054c1663f
|
||||
@@ -0,0 +1,54 @@
|
||||
using ProjectM.Simulation;
|
||||
using Unity.Burst;
|
||||
using Unity.Collections;
|
||||
using Unity.Entities;
|
||||
using Unity.NetCode;
|
||||
|
||||
namespace ProjectM.Server
|
||||
{
|
||||
/// <summary>
|
||||
/// Server-authoritative handler for <see cref="StorageOpRequest"/> RPCs (deposit/withdraw on the
|
||||
/// shared storage container). Resolves the single <see cref="SharedStorageContainer"/> as a singleton,
|
||||
/// applies the op to its replicated <see cref="StorageEntry"/> buffer via <see cref="StorageMath"/>,
|
||||
/// and destroys the request entity. Runs in the default SimulationSystemGroup (NOT the prediction
|
||||
/// loop), so a server event is applied exactly once (no rollback double-apply). Op is read as a byte
|
||||
/// (see <see cref="StorageOp"/>); the buffer mutation auto-replicates to all clients via GhostField.
|
||||
/// </summary>
|
||||
[BurstCompile]
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
public partial struct StorageOpReceiveSystem : ISystem
|
||||
{
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
state.RequireForUpdate<SharedStorageContainer>();
|
||||
|
||||
var builder = new EntityQueryBuilder(Allocator.Temp)
|
||||
.WithAll<StorageOpRequest, ReceiveRpcCommandRequest>();
|
||||
state.RequireForUpdate(state.GetEntityQuery(builder));
|
||||
}
|
||||
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
var containerEntity = SystemAPI.GetSingletonEntity<SharedStorageContainer>();
|
||||
var contents = SystemAPI.GetBuffer<StorageEntry>(containerEntity);
|
||||
|
||||
var ecb = new EntityCommandBuffer(Allocator.Temp);
|
||||
|
||||
foreach (var (request, requestEntity) in
|
||||
SystemAPI.Query<RefRO<StorageOpRequest>>().WithAll<ReceiveRpcCommandRequest>().WithEntityAccess())
|
||||
{
|
||||
var op = request.ValueRO;
|
||||
if (op.Op == StorageOp.Withdraw)
|
||||
StorageMath.Withdraw(contents, op.ItemId, op.Count);
|
||||
else
|
||||
StorageMath.Deposit(contents, op.ItemId, op.Count);
|
||||
|
||||
ecb.DestroyEntity(requestEntity);
|
||||
}
|
||||
|
||||
ecb.Playback(state.EntityManager);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6739144c8fa1bd040ad766919f9535f3
|
||||
Reference in New Issue
Block a user