mirror of
https://github.com/Campofinale/CampofinaleBackup.git
synced 2025-12-12 22:54:37 +00:00
another try to improve entity spawning and fix loading but still loading issues
This commit is contained in:
parent
f47ec48073
commit
35f8fbb2b2
@ -4,10 +4,12 @@ using Campofinale.Packets.Sc;
|
||||
using Campofinale.Resource;
|
||||
using Campofinale.Resource.Dynamic;
|
||||
using MongoDB.Bson.Serialization.Attributes;
|
||||
using System;
|
||||
using System.Text.Json.Serialization;
|
||||
using static Campofinale.Resource.Dynamic.SpawnerConfig;
|
||||
using static Campofinale.Resource.ResourceManager;
|
||||
using static Campofinale.Resource.ResourceManager.LevelScene.LevelData;
|
||||
using static Campofinale.Resource.ResourceManager.LevelScene.LevelData.LevelFunctionAreaData;
|
||||
|
||||
namespace Campofinale.Game
|
||||
{
|
||||
@ -235,7 +237,6 @@ namespace Campofinale.Game
|
||||
{
|
||||
if (scene != null)
|
||||
{
|
||||
scene.alreadyLoaded = false;
|
||||
scene.Unload();
|
||||
}
|
||||
}
|
||||
@ -256,11 +257,11 @@ namespace Campofinale.Game
|
||||
[BsonIgnore,JsonIgnore]
|
||||
public List<Entity> entities = new();
|
||||
[BsonIgnore, JsonIgnore]
|
||||
public bool alreadyLoaded = false;
|
||||
[BsonIgnore, JsonIgnore]
|
||||
public List<ulong> activeScripts = new();
|
||||
|
||||
public List<LevelScript> scripts = new();
|
||||
[BsonIgnore, JsonIgnore]
|
||||
private LevelFunctionRangeData currentAreaRange = new();
|
||||
public int GetCollection(string id)
|
||||
{
|
||||
if (collections.ContainsKey(id))
|
||||
@ -367,17 +368,12 @@ namespace Campofinale.Game
|
||||
entities.Add(entity);
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
UpdateShowEntities();
|
||||
}
|
||||
|
||||
public void SpawnEntity(Entity en,bool spawnedCheck=true)
|
||||
{
|
||||
|
||||
en.spawned = true;
|
||||
|
||||
GetOwner().Send(new PacketScObjectEnterView(GetOwner(), new List<Entity>() { en }));
|
||||
}
|
||||
public bool GetActiveScript(ulong id)
|
||||
@ -392,10 +388,22 @@ namespace Campofinale.Game
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateArea()
|
||||
{
|
||||
LevelScene lv_scene = ResourceManager.GetLevelData(sceneNumId);
|
||||
lv_scene.levelData.functionArea.ranges.ForEach(range =>
|
||||
{
|
||||
if (range.IsObjectInside(GetOwner().position))
|
||||
{
|
||||
currentAreaRange=range;
|
||||
}
|
||||
});
|
||||
}
|
||||
//Bug on scene 101: spawning entities in this way make the game break if you try to load another scene from scene 101
|
||||
public async void UpdateShowEntities()
|
||||
{
|
||||
|
||||
UpdateArea();
|
||||
List<Entity> toSpawn = new();
|
||||
List<Entity> toCheck = GetEntityExcludingChar().FindAll(e => e.spawned == false);
|
||||
toCheck.Sort((a, b) => a.Position.Distance(GetOwner().position).CompareTo(b.Position.Distance(GetOwner().position)));
|
||||
@ -404,6 +412,7 @@ namespace Campofinale.Game
|
||||
|
||||
if(e.spawned==false && (GetActiveScript(e.belongLevelScriptId) || e.belongLevelScriptId==0))
|
||||
{
|
||||
if(currentAreaRange.IsObjectInside(e.Position))
|
||||
if (!e.defaultHide)
|
||||
{
|
||||
toSpawn.Add(e);
|
||||
@ -423,34 +432,18 @@ namespace Campofinale.Game
|
||||
GetOwner().Send(new PacketScObjectEnterView(GetOwner(), chunk));
|
||||
}
|
||||
}
|
||||
List<ulong> toDespawn=new();
|
||||
foreach(Entity en in GetEntityExcludingChar().FindAll(e=> e.spawned==true))
|
||||
{
|
||||
if (!currentAreaRange.IsObjectInside(en.Position))
|
||||
{
|
||||
toDespawn.Add(en.guid);
|
||||
en.spawned = false;
|
||||
}
|
||||
|
||||
/* foreach(Entity en in GetEntityExcludingChar())
|
||||
{
|
||||
float minDis = 100;
|
||||
|
||||
//todo new system
|
||||
if (en.Position.DistanceXZ(GetOwner().position) < minDis)
|
||||
{
|
||||
if (!en.spawned)
|
||||
{
|
||||
SpawnEntity(en);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
/*if (en.spawned)
|
||||
{
|
||||
|
||||
en.spawned = false;
|
||||
GetOwner().Send(new PacketScObjectLeaveView(GetOwner(), new List<ulong>() { en.guid }));
|
||||
en.Position=en.BornPos;
|
||||
en.Rotation = en.Rotation;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
if(toDespawn.Count > 0)
|
||||
GetOwner().Send(new PacketScObjectLeaveView(GetOwner(), toDespawn));
|
||||
}
|
||||
|
||||
public Player GetOwner()
|
||||
|
||||
@ -11,7 +11,7 @@ namespace Campofinale.Packets.Cs
|
||||
{
|
||||
CsSceneMoveStateSet req = packet.DecodeBody<CsSceneMoveStateSet>();
|
||||
//req.
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
using Campofinale.Network;
|
||||
using Campofinale.Protocol;
|
||||
using Campofinale.Utils;
|
||||
|
||||
namespace Campofinale.Packets.Cs
|
||||
{
|
||||
@ -26,6 +27,9 @@ namespace Campofinale.Packets.Cs
|
||||
}
|
||||
else
|
||||
{
|
||||
uint unixTimestamp = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
|
||||
var generator = new SnowflakeIdGenerator(machineId: 1);
|
||||
long id = generator.GenerateId();
|
||||
ScSceneTeleport t = new()
|
||||
{
|
||||
TeleportReason = req.TeleportReason,
|
||||
@ -33,6 +37,8 @@ namespace Campofinale.Packets.Cs
|
||||
Position = req.Position,
|
||||
Rotation = req.Rotation,
|
||||
SceneNumId = req.SceneNumId,
|
||||
ServerTime = unixTimestamp,
|
||||
TpUuid= (ulong)id
|
||||
};
|
||||
session.curSceneNumId = t.SceneNumId;
|
||||
session.Send(ScMsgId.ScSceneTeleport, t);
|
||||
|
||||
@ -2,6 +2,8 @@
|
||||
using Campofinale.Resource.Json;
|
||||
using Campofinale.Resource.Table;
|
||||
using Newtonsoft.Json;
|
||||
using System.Numerics;
|
||||
using System;
|
||||
using static Campofinale.Resource.ResourceManager.LevelScene;
|
||||
|
||||
namespace Campofinale.Resource
|
||||
@ -549,6 +551,7 @@ namespace Campofinale.Resource
|
||||
public List<WorldWayPointSets> worldWayPointSets = new();
|
||||
public List<LevelFactoryRegionData> factoryRegions = new();
|
||||
public List<LevelSpawnerData> spawners = new();
|
||||
public LevelFunctionAreaData functionArea = new();
|
||||
public void Merge(LevelData other)
|
||||
{
|
||||
this.sceneId = other.sceneId;
|
||||
@ -560,6 +563,7 @@ namespace Campofinale.Resource
|
||||
this.worldWayPointSets.AddRange(other.worldWayPointSets);
|
||||
this.factoryRegions.AddRange(other.factoryRegions);
|
||||
this.spawners.AddRange(other.spawners);
|
||||
this.functionArea.ranges.AddRange(other.functionArea.ranges);
|
||||
}
|
||||
|
||||
public class WorldWayPointSets
|
||||
@ -567,6 +571,26 @@ namespace Campofinale.Resource
|
||||
public int id;
|
||||
public Dictionary<string, int> pointIdToIndex = new();
|
||||
}
|
||||
|
||||
public class LevelFunctionAreaData
|
||||
{
|
||||
public List<LevelFunctionRangeData> ranges = new();
|
||||
|
||||
public class LevelFunctionRangeData
|
||||
{
|
||||
public Vector3f m_center = new();
|
||||
public Vector3f m_size = new();
|
||||
|
||||
public bool IsObjectInside(Vector3f position)
|
||||
{
|
||||
Vector3f halfSize = m_size * 0.5f;
|
||||
|
||||
return Math.Abs(position.x - m_center.x) <= halfSize.x &&
|
||||
Math.Abs(position.y - m_center.y) <= halfSize.y &&
|
||||
Math.Abs(position.z - m_center.z) <= halfSize.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
public class LevelSpawnerData
|
||||
{
|
||||
public ulong spawnerId;
|
||||
@ -949,6 +973,10 @@ namespace Campofinale.Resource
|
||||
public Vector3f()
|
||||
{
|
||||
|
||||
}
|
||||
public static Vector3f operator *(Vector3f v, float scalar)
|
||||
{
|
||||
return new Vector3f(v.x * scalar, v.y * scalar, v.z * scalar);
|
||||
}
|
||||
public Vector3f(float x, float y, float z)
|
||||
{
|
||||
|
||||
56
Campofinale/Utils/SnowflakeIdGenerator.cs
Normal file
56
Campofinale/Utils/SnowflakeIdGenerator.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Campofinale.Utils
|
||||
{
|
||||
public class SnowflakeIdGenerator
|
||||
{
|
||||
private static readonly DateTime Epoch = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc);
|
||||
|
||||
private readonly int _machineId; // es. 0–31 (5 bit)
|
||||
private int _sequence = 0;
|
||||
private long _lastTimestamp = -1L;
|
||||
|
||||
private readonly object _lock = new object();
|
||||
|
||||
public SnowflakeIdGenerator(int machineId)
|
||||
{
|
||||
_machineId = machineId & 0x1F; // 5 bit
|
||||
}
|
||||
|
||||
public long GenerateId()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
long timestamp = GetCurrentTimestamp();
|
||||
|
||||
if (timestamp == _lastTimestamp)
|
||||
{
|
||||
_sequence = (_sequence + 1) & 0xFFF; // 12 bit
|
||||
if (_sequence == 0)
|
||||
{
|
||||
// Attendi il prossimo millisecondo
|
||||
while ((timestamp = GetCurrentTimestamp()) <= _lastTimestamp) ;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_sequence = 0;
|
||||
}
|
||||
|
||||
_lastTimestamp = timestamp;
|
||||
|
||||
return ((timestamp << 22) | ((long)_machineId << 12) | (long)_sequence);
|
||||
}
|
||||
}
|
||||
|
||||
private long GetCurrentTimestamp()
|
||||
{
|
||||
return (long)(DateTime.UtcNow - Epoch).TotalMilliseconds;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user