using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using ServerCore; using ServerBase; using ServerCommon; using ServerCommon.BusinessLogDomain; using MetaAssets; namespace GameServer; public class PropGroup { public int PropGroupId { get; set; } public DateTime LatestRespawnTime { get; set; } public List AnchorGuids { get; set; } = new(); } internal class PropGroupManager { Dictionary m_prop_groups = new(); public bool init(Map map) { foreach (var prop_group in m_prop_groups.Values) { if (!MetaData.Instance._PropGroupMetaTable.TryGetValue(prop_group.PropGroupId, out var prop_group_data)) { Log.getLogger().error($"Failed to MetaData.TryGetValue() !!! : propGroupMetaId:{prop_group.PropGroupId}"); continue; } if (prop_group_data.prop_order_data.Count <= 0) { Log.getLogger().error($"PropGroupData.prop_order_data.Count <= 0 !!! : {prop_group.PropGroupId}"); continue; } // GroupProp 기본값 세팅 foreach (var anchor_guid in prop_group.AnchorGuids) { if (!map.getAnchors().TryGetValue(anchor_guid, out var anchor_info)) continue; anchor_info.AnchorProp.TableId = prop_group_data.prop_order_data[0].prop_id; } int spawn_count = 0; while (spawn_count < prop_group_data.max_spawn_quantity) { var spawn_prop_id = getSpawnPropId(prop_group_data); var index = RandomHelper.next(0, prop_group.AnchorGuids.Count); string activation_anchor_guid = prop_group.AnchorGuids[index]; if (false == map.getAnchors().TryGetValue(activation_anchor_guid, out var activation_anchor_info)) return false; if (activation_anchor_info.PropState == PropState.Activation) continue; activation_anchor_info.AnchorProp.TableId = spawn_prop_id; activation_anchor_info.PropState = PropState.Activation; spawn_count++; } } return true; } int getSpawnPropId(PropGroupData propGroupData) { int spawn_prop_id = -1; int low_spawn_weight = 0; int high_spawn_weight = 0; var prop_spawn_weight = RandomHelper.next(0, propGroupData.max_prop_spawn_weight); foreach (var prop_order in propGroupData.prop_order_data) { low_spawn_weight = high_spawn_weight; high_spawn_weight += prop_order.prop_spawn_weight; if (low_spawn_weight <= prop_spawn_weight && prop_spawn_weight < high_spawn_weight) { spawn_prop_id = prop_order.prop_id; break; } } return spawn_prop_id; } public bool addAnchor(AnchorInfo anchorInfo) { if (!MapHelper.isGroupProp(anchorInfo.AnchorGuid)) return false; if (!MapDataTable.Instance.getAnchor(anchorInfo.AnchorGuid, out var anchor)) return false; if (!m_prop_groups.TryGetValue(anchor.TableID, out var prop_group)) { prop_group = new(); prop_group.PropGroupId = anchor.TableID; if (!m_prop_groups.TryAdd(anchor.TableID, prop_group)) { Log.getLogger().error($"Failed to PropGroup Add !!! : propGroupMetaId:{anchor.TableID}"); return false; } } prop_group.AnchorGuids.Add(anchorInfo.AnchorGuid); return true; } public void checkRespawnPropGroup(Map map) { foreach (var prop_group_id in m_prop_groups.Keys) { respawnPropGroup(map, prop_group_id); } } bool respawnPropGroup(Map map, int propGroupId) { var err_msg = string.Empty; if (!MetaData.Instance._PropGroupMetaTable.TryGetValue(propGroupId, out var prop_group_data)) { err_msg = $"Failed to MetaData.TryGetValue() !!! : propGroupMetaId:{propGroupId}"; Log.getLogger().error(err_msg); return false; } if (!m_prop_groups.TryGetValue(propGroupId, out var prop_group)) return false; int activationAndRespawningCount = 0; List deactivateAnchorGuids = new(); foreach (var anchor_guid in prop_group.AnchorGuids) { if (false == map.getAnchors().TryGetValue(anchor_guid, out var anchor_info)) continue; if (anchor_info.PropState == PropState.Activation || anchor_info.PropState == PropState.Respawning) { activationAndRespawningCount++; continue; } deactivateAnchorGuids.Add((anchor_guid)); } if (activationAndRespawningCount >= prop_group_data.max_spawn_quantity) return false; int respwan_prop_id = getSpawnPropId(prop_group_data); var index = RandomHelper.next(0, deactivateAnchorGuids.Count); string respwan_anchor_guid = deactivateAnchorGuids[index]; if (false == map.getAnchors().TryGetValue(respwan_anchor_guid, out var respwan_anchor_info)) return false; var respwan_time = prop_group.LatestRespawnTime > DateTime.UtcNow ? prop_group.LatestRespawnTime : DateTime.UtcNow; respwan_time = respwan_time.AddSeconds(prop_group_data.group_respawn_time); prop_group.LatestRespawnTime = respwan_time; respwan_anchor_info.AnchorProp.TableId = respwan_prop_id; respwan_anchor_info.PropState = PropState.Respawning; respwan_anchor_info.respawnTime = respwan_time.ToTimestamp(); return true; } }