Run Re-Do
This commit is contained in:
@@ -20,6 +20,8 @@ namespace ProjectM.Server
|
||||
[WorldSystemFilter(WorldSystemFilterFlags.ServerSimulation)]
|
||||
public partial struct GoInGameServerSystem : ISystem
|
||||
{
|
||||
bool _warnedMetaBlocked; // one-shot: a mis-authored subscene must not silently block spawns forever
|
||||
|
||||
[BurstCompile]
|
||||
public void OnCreate(ref SystemState state)
|
||||
{
|
||||
@@ -33,6 +35,22 @@ namespace ProjectM.Server
|
||||
[BurstCompile]
|
||||
public void OnUpdate(ref SystemState state)
|
||||
{
|
||||
// Step 12a availability guard (review N2/L1-6): the born-correct meta seeding below needs the baked
|
||||
// catalog + the live director's tier record. Both are per-tick-uniform, so guard ONCE at the TOP,
|
||||
// BEFORE the ECB exists — a per-request continue would already have marked the connection in-game.
|
||||
// Nothing is consumed; RequireForUpdate re-passes and the request retries next tick (a ≤1-tick window
|
||||
// in practice — the director spawns at subscene-stream, before any GoInGame round-trip).
|
||||
if (!SystemAPI.TryGetSingleton<MetaUpgradeCatalog>(out var metaCatalog) || !metaCatalog.Value.IsCreated
|
||||
|| !SystemAPI.TryGetSingletonBuffer<MetaTierState>(out var metaRecord, true))
|
||||
{
|
||||
if (!_warnedMetaBlocked)
|
||||
{
|
||||
UnityEngine.Debug.LogWarning("GoInGameServerSystem: player spawn waiting on the meta catalog/director (a mis-authored subscene would block spawns forever).");
|
||||
_warnedMetaBlocked = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var spawner = SystemAPI.GetSingleton<PlayerSpawner>();
|
||||
|
||||
// M5 home base: re-root the spawn ring on the baked BaseAnchor when present; fall back
|
||||
@@ -61,6 +79,34 @@ namespace ProjectM.Server
|
||||
byte classId = ClassTraits.Normalize(goReq.ValueRO.ClassId);
|
||||
ecb.SetComponent(player, new AbilityRef { Id = ClassTraits.AbilityFor(classId) });
|
||||
ClassTraits.AppendSeeds(classId, player, ecb);
|
||||
// Expedition redesign: the server-only class anchor the meta systems key on (born-correct meta
|
||||
// seeding at Step 12a + per-class spend at Step 13 resolve the tier record through this).
|
||||
ecb.AddComponent(player, new PlayerClass { ClassId = classId });
|
||||
// Step 12a: born-correct PERMANENT meta seeding — replay this class's persisted tiers as
|
||||
// meta-band StatModifiers on the just-instantiated player (same ECB as Instantiate, the
|
||||
// ClassTraits idiom). Skip tier 0 / unknown ids (preserve-don't-crash); CLAMP a saved tier above a
|
||||
// rebalanced MaxTier (D-F5). Class gate via BoonMath.MaskFor (ClassId is the normalized
|
||||
// CharacterId 2/3 — a raw 1<<ClassId would compute bits 2/3 and silently skip everything).
|
||||
{
|
||||
ref var metaPool = ref metaCatalog.Value.Value;
|
||||
byte classBit = BoonMath.MaskFor(classId);
|
||||
for (int m = 0; m < metaRecord.Length; m++)
|
||||
{
|
||||
if (metaRecord[m].ClassId != classId || metaRecord[m].Tier == 0) continue;
|
||||
int defIdx = MetaMath.FindDef(ref metaPool, metaRecord[m].UpgradeId);
|
||||
if (defIdx < 0) continue; // unknown id (catalog drift) — preserved on disk, skipped live
|
||||
if ((metaPool.Defs[defIdx].ClassMask & classBit) == 0) continue;
|
||||
byte tier = metaRecord[m].Tier < metaPool.Defs[defIdx].MaxTier
|
||||
? metaRecord[m].Tier : metaPool.Defs[defIdx].MaxTier;
|
||||
ecb.AppendToBuffer(player, new StatModifier
|
||||
{
|
||||
Target = metaPool.Defs[defIdx].Target,
|
||||
Op = metaPool.Defs[defIdx].Op,
|
||||
Value = metaPool.Defs[defIdx].ValuePerTier * tier,
|
||||
SourceId = Tuning.MetaSourceIdBase + metaRecord[m].UpgradeId,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Auto-despawn the player when its owning connection is removed.
|
||||
ecb.AppendToBuffer(connection, new LinkedEntityGroup { Value = player });
|
||||
|
||||
Reference in New Issue
Block a user