public ServerChunk GetChunk(int x, int y, int z) { x = x / chunksize; y = y / chunksize; z = z / chunksize; ServerChunk chunk = GetChunkValid(x, y, z); if (chunk == null) { wasChunkGenerated = true; byte[] serializedChunk = ChunkDb.GetChunk(d_ChunkDb, x, y, z); if (serializedChunk != null) { SetChunkValid(x, y, z, DeserializeChunk(serializedChunk)); //todo get heightmap from disk UpdateChunkHeight(x, y, z); return(GetChunkValid(x, y, z)); } // get chunk ushort[] newchunk = new ushort[chunksize * chunksize * chunksize]; for (int i = 0; i < server.modEventHandlers.getchunk.Count; i++) { server.modEventHandlers.getchunk[i](x, y, z, newchunk); } SetChunkValid(x, y, z, new ServerChunk() { data = newchunk }); GetChunkValid(x, y, z).DirtyForSaving = true; UpdateChunkHeight(x, y, z); return(GetChunkValid(x, y, z)); } return(chunk); }
void OnUseWithTool(int player, int x, int y, int z, int tool) { if (server.modManager.GetBlockName(tool) == "Sign") { ServerChunk c = server.d_Map.GetChunk(x, y, z); if (c == null) { return; } if (!server.CheckBuildPrivileges(player, x, y, z)) { return; } ServerEntity e = new ServerEntity(); e.position = new ServerEntityPositionAndOrientation(); e.position.x = x + one / 2; e.position.y = z; e.position.z = y + one / 2; e.position.heading = EntityHeading.GetHeading(server.modManager.GetPlayerPositionX(player), server.modManager.GetPlayerPositionY(player), e.position.x, e.position.z); e.sign = new ServerEntitySign(); e.sign.text = "Hello world!"; server.AddEntity(x, y, z, e); } }
public void SetChunks(int offsetX, int offsetY, int offsetZ, Dictionary <Xyz, ushort[]> chunks) { if (chunks.Count == 0) { return; } foreach (var k in chunks) { if (k.Value == null) { continue; } // TODO: check bounds. ServerChunk c = d_Map.GetChunkValid(k.Key.X + offsetX, k.Key.Y + offsetY, k.Key.Z + offsetZ); if (c == null) { c = new ServerChunk(); } c.data = k.Value; c.DirtyForSaving = true; d_Map.SetChunkValid(k.Key.X + offsetX, k.Key.Y + offsetY, k.Key.Z + offsetZ, c); } // update related chunk at clients foreach (var k in clients) { //TODO wrong //k.Value.chunksseen.Clear(); Array.Clear(k.Value.chunksseen, 0, k.Value.chunksseen.Length); } }
public ushort[] GetChunkFromDatabase(int x, int y, int z, string filename) { if (MapUtil.IsValidPos(d_Map, x, y, z)) { if (!GameStorePath.IsValidName(filename)) { Console.WriteLine("Invalid backup filename: " + filename); return(null); } if (!Directory.Exists(GameStorePath.gamepathbackup)) { Directory.CreateDirectory(GameStorePath.gamepathbackup); } string finalFilename = Path.Combine(GameStorePath.gamepathbackup, filename + MapManipulator.BinSaveExtension); x = x / chunksize; y = y / chunksize; z = z / chunksize; byte[] serializedChunk = ChunkDb.GetChunkFromFile(d_ChunkDb, x, y, z, finalFilename); if (serializedChunk != null) { ServerChunk c = DeserializeChunk(serializedChunk); return(c.data); } } return(null); }
public Dictionary <Xyz, ushort[]> GetChunksFromDatabase(List <Xyz> chunks, string filename) { if (chunks == null) { return(null); } if (!GameStorePath.IsValidName(filename)) { Console.WriteLine("Invalid backup filename: " + filename); return(null); } if (!Directory.Exists(GameStorePath.gamepathbackup)) { Directory.CreateDirectory(GameStorePath.gamepathbackup); } string finalFilename = Path.Combine(GameStorePath.gamepathbackup, filename + MapManipulator.BinSaveExtension); Dictionary <Xyz, ushort[]> deserializedChunks = new Dictionary <Xyz, ushort[]>(); Dictionary <Xyz, byte[]> serializedChunks = ChunkDb.GetChunksFromFile(d_ChunkDb, chunks, finalFilename); foreach (var k in serializedChunks) { ServerChunk c = null; if (k.Value != null) { c = DeserializeChunk(k.Value); } deserializedChunks.Add(k.Key, c.data); } return(deserializedChunks); }
void ChunkUpdate(Server server, Vector3i p, long lastupdate) { unchecked { if (server.config.Monsters) { AddMonsters(server, p); } var bt = server.modEventHandlers.blockticks; var btCount = bt.Count; ServerChunk chunk = server.d_Map.GetChunk(p.x, p.y, p.z); for (int xx = 0; xx < Server.chunksize; xx++) { int px = xx + p.x; for (int yy = 0; yy < Server.chunksize; yy++) { int py = yy + p.y; for (int zz = 0; zz < Server.chunksize; zz++) { int pz = zz + p.z; //int block = chunk.data[MapUtilCi.Index3d(xx, yy, zz, Server.chunksize, Server.chunksize)]; for (int i = 0; i < btCount; i++) { bt[i](px, py, pz); } } } } } }
void OnUseWithTool(int player, int x, int y, int z, int tool) { if (server.modManager.GetBlockName(tool) == "PermissionSign") { ServerChunk c = server.d_Map.GetChunk(x, y, z); if (c == null) { return; } if (!server.CheckBuildPrivileges(player, x, y, z)) { return; } if (!server.PlayerHasPrivilege(player, ServerClientMisc.Privilege.area_add)) { server.SendMessage(player, server.colorError + server.language.Get("Server_CommandInsufficientPrivileges")); return; } ServerEntity e = new ServerEntity(); e.position = new ServerEntityPositionAndOrientation(); e.position.x = x + one / 2; e.position.y = z; e.position.z = y + one / 2; e.position.heading = EntityHeading.GetHeading(server.modManager.GetPlayerPositionX(player), server.modManager.GetPlayerPositionY(player), e.position.x, e.position.z); e.permissionSign = new ServerEntityPermissionSign(); e.permissionSign.name = "Admin"; e.permissionSign.type = PermissionSignType.Group; server.AddEntity(x, y, z, e); } }
public override void Update(Server server, float dt) { int sizexchunks = server.mapsizexchunks(); int sizeychunks = server.mapsizeychunks(); int sizezchunks = server.mapsizezchunks(); for (int i = 0; i < 100; i++) { MapUtilCi.PosInt(CompressUnusedIteration, sizexchunks, sizeychunks, chunkpos); ServerChunk c = server.d_Map.GetChunkValid(chunkpos.X, chunkpos.Y, chunkpos.Z); bool stop = false; if (c != null) { var globalpos = new Vector3i(chunkpos.X * Server.chunksize, chunkpos.Y * Server.chunksize, chunkpos.Z * Server.chunksize); bool unload = true; foreach (var k in server.clients) { if (k.Value.IsBot) { // don't hold chunks in memory for bots continue; } // unload distance = view distance + 60% (prevents chunks from being unloaded too early (square loading vs. circular unloading)) int viewdist = (int)(server.chunkdrawdistance * Server.chunksize * 1.8f); if (server.DistanceSquared(server.PlayerBlockPosition(k.Value), globalpos) <= viewdist * viewdist) { //System.Console.WriteLine("No Unload: {0},{1},{2}", chunkpos.X, chunkpos.Y, chunkpos.Z); unload = false; } } if (unload) { // unload if chunk isn't seen by anyone if (c.DirtyForSaving) { // save changes to disk if necessary server.DoSaveChunk(chunkpos.X, chunkpos.Y, chunkpos.Z, c); } server.d_Map.SetChunkValid(chunkpos.X, chunkpos.Y, chunkpos.Z, null); foreach (var client in server.clients) { // mark chunks unseen for all players server.ClientSeenChunkRemove(client.Key, chunkpos.X, chunkpos.Y, chunkpos.Z); } stop = true; } } CompressUnusedIteration++; if (CompressUnusedIteration >= sizexchunks * sizeychunks * sizezchunks) { CompressUnusedIteration = 0; } if (stop) { // only unload one chunk at a time return; } } }
public void SetBlockNotMakingDirty(int x, int y, int z, int tileType) { ServerChunk chunk = GetChunk(x, y, z); chunk.data[MapUtilCi.Index3d(x % chunksize, y % chunksize, z % chunksize, chunksize, chunksize)] = (ushort)tileType; chunk.DirtyForSaving = true; UpdateColumnHeight(x, y); }
private void SpawnSeeds(ServerChunk chunk, TreeSoul soul) { // TODO: check other constraints (season, maxseeds etc) var seeds = chunk.Entities.OfType <TreeGrowingEntity>().Count(e => e.TreeTypeId == soul.TreeTypeId); if (seeds == 0) { var pos = new Vector2I(_fastRandom.Next(chunk.BlockData.ChunkSize.X), _fastRandom.Next(chunk.BlockData.ChunkSize.Z)); var metaData = chunk.BlockData.GetColumnInfo(pos); var cursor = _server.LandscapeManager.GetCursor(BlockHelper.ConvertToGlobal(chunk.Position, new Vector3I(pos.X, metaData.MaxGroundHeight + 1, pos.Y))); while (cursor.GlobalPosition.Y > 0) { var val = cursor.PeekValue(Vector3I.Down); if (val != WorldConfiguration.CubeId.Air) { break; } cursor.Move(Vector3I.Down); } if (cursor.Read() != WorldConfiguration.CubeId.Air) { return; } if (cursor.GlobalPosition.Y == 0) { return; } var config = _server.EntityFactory.Config; var treeBp = config.TreeBluePrintsDico[soul.TreeTypeId]; var treeSeed = _server.EntityFactory.CreateEntity <TreeGrowingEntity>(); treeSeed.TreeTypeId = soul.TreeTypeId; treeSeed.TreeRndSeed = _fastRandom.Next(); treeSeed.ModelName = treeBp.SeedModel; treeSeed.Name = "Seed of " + treeBp.Name; treeSeed.IsPickable = true; treeSeed.IsPlayerCollidable = true; treeSeed.CollisionType = Entity.EntityCollisionType.Model; treeSeed.MountPoint = BlockFace.Top; treeSeed.Position = cursor.GlobalPosition + new Vector3D(0.5, 0, 0.5); treeSeed.LinkedCube = cursor.GlobalPosition - Vector3I.Up; treeSeed.BlockFaceCentered = true; treeSeed.GrowingSeasons = config.TreeBluePrintsDico[soul.TreeTypeId].GrowingSeasons; treeSeed.GrowingBlocks = config.TreeBluePrintsDico[soul.TreeTypeId].GrowingBlocks; cursor.AddEntity(treeSeed); } }
public void LoadChunk(int cx, int cy, int cz) { ServerChunk chunk = GetChunkValid(cx, cy, cz); if (chunk == null) { GetChunk(cx * chunksize, cy * chunksize, cz * chunksize); } }
public override void SetBlock(int x, int y, int z, int tileType) { ServerChunk chunk = GetChunk(x, y, z); chunk.data[MapUtilCi.Index3d(x % chunksize, y % chunksize, z % chunksize, chunksize, chunksize)] = (ushort)tileType; chunk.LastChange = d_CurrentTime.GetSimulationCurrentFrame(); chunk.DirtyForSaving = true; UpdateColumnHeight(x, y); }
public void SetChunkValid(int cx, int cy, int cz, ServerChunk chunk) { ServerChunk[] column = chunks[MapUtilCi.Index2d(cx, cy, MapSizeX / chunksize)]; if (column == null) { column = new ServerChunk[MapSizeZ / chunksize]; chunks[MapUtilCi.Index2d(cx, cy, MapSizeX / chunksize)] = column; } column[cz] = chunk; }
public override int GetBlock(int x, int y, int z) { ServerChunk chunk = GetChunk(x, y, z); //return chunk.data[MapUtilCi.Index3d(x % chunksize, y % chunksize, z % chunksize, chunksize, chunksize)]; unchecked { return(chunk.data[MapUtilCi.Index3d(moduloChunk(x), moduloChunk(y), moduloChunk(z), chunksize, chunksize)]); } }
private void TreeIntegrity(ServerChunk chunk, TreeSoul soul) { if (!soul.IsDamaged) { return; } // the tree will regenerate or die after one day if ((_server.Clock.Now - soul.LastUpdate) < UtopiaTimeSpan.FromDays(1)) { return; } var config = _server.EntityFactory.Config; var treeBp = config.TreeBluePrintsDico[soul.TreeTypeId]; var treeBlocks = _treeLSystem.Generate(soul.TreeRndSeed, new Vector3I(), treeBp); var cursor = _server.LandscapeManager.GetCursor(soul.Position); if (soul.IsDying) { // remove the tree using (cursor.TransactionScope()) { foreach (var blockWithPosition in treeBlocks) { cursor.GlobalPosition = (Vector3I)soul.Position + blockWithPosition.WorldPosition; if (cursor.Read() == blockWithPosition.BlockId) { cursor.Write(WorldConfiguration.CubeId.Air); } } } chunk.Entities.Remove(soul); } else { // restore the tree using (cursor.TransactionScope()) { foreach (var blockWithPosition in treeBlocks) { cursor.GlobalPosition = (Vector3I)soul.Position + blockWithPosition.WorldPosition; if (cursor.Read() == WorldConfiguration.CubeId.Air) { cursor.Write(blockWithPosition.BlockId); } } } soul.IsDamaged = false; } }
} //10 minutes void ChunkSimulation(Server server) { unchecked { foreach (var k in server.clients) { var pos = server.PlayerBlockPosition(k.Value); long oldesttime = long.MaxValue; Vector3i oldestpos = new Vector3i(); foreach (var p in ChunksAroundPlayer(server, pos)) { if (!MapUtil.IsValidPos(server.d_Map, p.x, p.y, p.z)) { continue; } ServerChunk c = server.d_Map.GetChunkValid(server.invertChunk(p.x), server.invertChunk(p.y), server.invertChunk(p.z)); //ServerChunk c = server.d_Map.GetChunkValid(p.x / Server.chunksize, p.y / Server.chunksize, p.z / Server.chunksize); if (c == null) { continue; } if (c.data == null) { continue; } if (c.LastUpdate > server.simulationcurrentframe) { c.LastUpdate = server.simulationcurrentframe; } if (c.LastUpdate < oldesttime) { oldesttime = c.LastUpdate; oldestpos = p; } if (!c.IsPopulated) { PopulateChunk(server, p); c.IsPopulated = true; } } if (server.simulationcurrentframe - oldesttime > chunksimulation_every(server)) { ChunkUpdate(server, oldestpos, oldesttime); ServerChunk c = server.d_Map.GetChunkValid(server.invertChunk(oldestpos.x), server.invertChunk(oldestpos.y), server.invertChunk(oldestpos.z)); //ServerChunk c = server.d_Map.GetChunkValid(oldestpos.x / Server.chunksize, oldestpos.y / Server.chunksize, oldestpos.z / Server.chunksize); c.LastUpdate = (int)server.simulationcurrentframe; return; } } } }
private void TreeSoulUpdate(ServerChunk chunk) { foreach (var soul in chunk.Entities.OfType <TreeSoul>().ToList()) { TreeIntegrity(chunk, soul); if (!soul.IsDamaged) { SpawnSeeds(chunk, soul); SpawnTreeEntities(chunk, soul); } } }
public void SetChunkValid(int cx, int cy, int cz, ServerChunk chunk) { unchecked { ServerChunk[] column = chunks[MapUtilCi.Index2d(cx, cy, invertChunk(MapSizeX))]; if (column == null) { column = new ServerChunk[invertChunk(MapSizeZ)]; chunks[MapUtilCi.Index2d(cx, cy, invertChunk(MapSizeX))] = column; } column[cz] = chunk; } }
public void SaveChunksToDatabase(List <Vector3i> chunkPositions, string filename) { if (!GameStorePath.IsValidName(filename)) { Console.WriteLine("Invalid backup filename: " + filename); return; } if (!Directory.Exists(GameStorePath.gamepathbackup)) { Directory.CreateDirectory(GameStorePath.gamepathbackup); } string finalFilename = Path.Combine(GameStorePath.gamepathbackup, filename + MapManipulator.BinSaveExtension); List <DbChunk> dbchunks = new List <DbChunk>(); foreach (Vector3i pos in chunkPositions) { int dx = pos.x / chunksize; int dy = pos.y / chunksize; int dz = pos.z / chunksize; ServerChunk cc = new ServerChunk() { data = this.GetChunk(pos.x, pos.y, pos.z) }; MemoryStream ms = new MemoryStream(); Serializer.Serialize(ms, cc); dbchunks.Add(new DbChunk() { Position = new Xyz() { X = dx, Y = dy, Z = dz }, Chunk = ms.ToArray() }); } if (dbchunks.Count != 0) { IChunkDb d_ChunkDb = new ChunkDbCompressed() { d_ChunkDb = new ChunkDbSqlite(), d_Compression = new CompressionGzip() }; d_ChunkDb.SetChunksToFile(dbchunks, finalFilename); } else { Console.WriteLine(string.Format("0 chunks selected. Nothing to do.")); } Console.WriteLine(string.Format("Saved {0} chunk(s) to database.", dbchunks.Count)); }
private ServerChunk DeserializeChunk(byte[] serializedChunk) { ServerChunk c = Serializer.Deserialize <ServerChunk>(new MemoryStream(serializedChunk)); //convert savegame to new format if (c.dataOld != null) { c.data = new ushort[chunksize * chunksize * chunksize]; for (int i = 0; i < c.dataOld.Length; i++) { c.data[i] = c.dataOld[i]; } c.dataOld = null; } return(c); }
public void ProtoContainerTest() { EntityFactory.InitializeProtobufInheritanceHierarchy(); var chunk = new ServerChunk(); var container = new Container(); container.Content.PutItem(new Food(), 1); chunk.Entities.Add(container); var data = chunk.Compress(); var nChunk = new ServerChunk(); nChunk.Decompress(data); }
public void AddMonsters(Server server, Vector3i p) { ServerChunk chunk = server.d_Map.GetChunkValid(p.x / Server.chunksize, p.y / Server.chunksize, p.z / Server.chunksize); int tries = 0; while (chunk.Monsters.Count < 1) { int xx = server.rnd.Next(Server.chunksize); int yy = server.rnd.Next(Server.chunksize); int zz = server.rnd.Next(Server.chunksize); int px = p.x + xx; int py = p.y + yy; int pz = p.z + zz; if ((!MapUtil.IsValidPos(server.d_Map, px, py, pz)) || (!MapUtil.IsValidPos(server.d_Map, px, py, pz + 1)) || (!MapUtil.IsValidPos(server.d_Map, px, py, pz - 1))) { continue; } int type; int height = MapUtil.blockheight(server.d_Map, 0, px, py); if (pz >= height) { type = MonsterTypesOnGround[server.rnd.Next(MonsterTypesOnGround.Length)]; } else { type = MonsterTypesUnderground[server.rnd.Next(MonsterTypesUnderground.Length)]; } if (server.d_Map.GetBlock(px, py, pz) == 0 && server.d_Map.GetBlock(px, py, pz + 1) == 0 && server.d_Map.GetBlock(px, py, pz - 1) != 0 && (!server.BlockTypes[server.d_Map.GetBlock(px, py, pz - 1)].IsFluid())) { chunk.Monsters.Add(new Monster() { X = px, Y = py, Z = pz, Id = NewMonsterId(server), Health = 20, MonsterType = type }); } if (tries++ > 500) { break; } } }
public void SetChunk(int x, int y, int z, ushort[] data) { if (MapUtil.IsValidPos(d_Map, x, y, z)) { x = x / chunksize; y = y / chunksize; z = z / chunksize; ServerChunk c = d_Map.GetChunkValid(x, y, z); if (c == null) { c = new ServerChunk(); } c.data = data; c.DirtyForSaving = true; d_Map.SetChunkValid(x, y, z, c); // update related chunk at clients foreach (var k in clients) { //todo wrong //k.Value.chunksseen.Clear(); Array.Clear(k.Value.chunksseen, 0, k.Value.chunksseen.Length); } } }
void ChunkUpdate(Server server, Vector3i p, long lastupdate) { if (server.config.Monsters) { AddMonsters(server, p); } ServerChunk chunk = server.d_Map.GetChunk(p.x, p.y, p.z); for (int xx = 0; xx < Server.chunksize; xx++) { for (int yy = 0; yy < Server.chunksize; yy++) { for (int zz = 0; zz < Server.chunksize; zz++) { int block = chunk.data[MapUtilCi.Index3d(xx, yy, zz, Server.chunksize, Server.chunksize)]; for (int i = 0; i < server.modEventHandlers.blockticks.Count; i++) { server.modEventHandlers.blockticks[i](p.x + xx, p.y + yy, p.z + zz); } } } } }
void NotifyEntities(Server server, int clientid, float dt) { ClientOnServer c = server.clients[clientid]; c.notifyEntitiesAccum += dt; if (c.notifyEntitiesAccum < (one / EntityPositionUpdatesPerSecond)) { return; } c.notifyEntitiesAccum = 0; // find nearest entities int max = SpawnMaxEntities; ServerEntityId[] nearestEntities = new ServerEntityId[max]; FindNearEntities(server, c, max, nearestEntities); // update entities for (int i = 0; i < max; i++) { ServerEntityId e = nearestEntities[i]; if (e == null) { continue; } for (int k = 0; k < server.modEventHandlers.onupdateentity.Count; k++) { server.modEventHandlers.onupdateentity[k](e.chunkx, e.chunky, e.chunkz, e.id); } } // despawn old entities for (int i = 0; i < c.spawnedEntitiesCount; i++) { ServerEntityId e = c.spawnedEntities[i]; if (e == null) { continue; } if (!Contains(nearestEntities, max, e)) { int onClientId = i; c.spawnedEntities[onClientId] = null; server.SendPacket(clientid, ServerPackets.EntityDespawn(64 + onClientId)); } } // spawn new entities for (int i = 0; i < max; i++) { ServerEntityId e = nearestEntities[i]; if (e == null) { continue; } if (!Contains(c.spawnedEntities, max, e)) { int onClientId = IndexOfNull(c.spawnedEntities, c.spawnedEntitiesCount); c.spawnedEntities[onClientId] = e.Clone(); ServerChunk chunk = server.d_Map.GetChunk(e.chunkx * Server.chunksize, e.chunky * Server.chunksize, e.chunkz * Server.chunksize); ServerEntity ee = chunk.Entities[e.id]; Packet_ServerEntity ne = ToNetworkEntity(server.serverPlatform, ee); server.SendPacket(clientid, ServerPackets.EntitySpawn(64 + onClientId, ne)); } } for (int i = 0; i < max; i++) { if (c.updateEntity[i]) { c.updateEntity[i] = false; ServerEntityId e = c.spawnedEntities[i]; ServerChunk chunk = server.d_Map.GetChunk(e.chunkx * Server.chunksize, e.chunky * Server.chunksize, e.chunkz * Server.chunksize); ServerEntity ee = chunk.Entities[e.id]; Packet_ServerEntity ne = ToNetworkEntity(server.serverPlatform, ee); server.SendPacket(clientid, ServerPackets.EntitySpawn(64 + i, ne)); } } }
public void SendChunk(Server server, int clientid, Vector3i globalpos, Vector3i chunkpos) { ClientOnServer c = server.clients[clientid]; ServerChunk chunk = server.d_Map.GetChunk(globalpos.x, globalpos.y, globalpos.z); server.ClientSeenChunkSet(clientid, chunkpos.x, chunkpos.y, chunkpos.z, (int)server.simulationcurrentframe); //sent++; byte[] compressedchunk; if (MapUtil.IsSolidChunk(chunk.data) && chunk.data[0] == 0) { //don't send empty chunk. compressedchunk = null; } else { compressedchunk = server.CompressChunkNetwork(chunk.data); //todo! //commented because it was being sent too early, before full column was generated. //if (!c.heightmapchunksseen.ContainsKey(new Vector2i(v.x, v.y))) { byte[] heightmapchunk = Misc.UshortArrayToByteArray(server.d_Map.GetHeightmapChunk(globalpos.x, globalpos.y)); byte[] compressedHeightmapChunk = server.d_NetworkCompression.Compress(heightmapchunk); Packet_ServerHeightmapChunk p1 = new Packet_ServerHeightmapChunk() { X = globalpos.x, Y = globalpos.y, SizeX = Server.chunksize, SizeY = Server.chunksize, CompressedHeightmap = compressedHeightmapChunk, }; server.SendPacket(clientid, server.Serialize(new Packet_Server() { Id = Packet_ServerIdEnum.HeightmapChunk, HeightmapChunk = p1 })); c.heightmapchunksseen[new Vector2i(globalpos.x, globalpos.y)] = (int)server.simulationcurrentframe; } } if (compressedchunk != null) { foreach (byte[] part in Server.Parts(compressedchunk, 1024)) { Packet_ServerChunkPart p1 = new Packet_ServerChunkPart() { CompressedChunkPart = part, }; server.SendPacket(clientid, server.Serialize(new Packet_Server() { Id = Packet_ServerIdEnum.ChunkPart, ChunkPart = p1 })); } } Packet_ServerChunk p = new Packet_ServerChunk() { X = globalpos.x, Y = globalpos.y, Z = globalpos.z, SizeX = Server.chunksize, SizeY = Server.chunksize, SizeZ = Server.chunksize, }; server.SendPacket(clientid, server.Serialize(new Packet_Server() { Id = Packet_ServerIdEnum.Chunk_, Chunk_ = p })); }
void FindNearEntities(Server server, ClientOnServer c, int maxCount, ServerEntityId[] ret) { List <ServerEntityId> list = new List <ServerEntityId>(); int playerx = c.PositionMul32GlX / 32; int playery = c.PositionMul32GlZ / 32; int playerz = c.PositionMul32GlY / 32; // Find all entities in 3x3x3 chunks around player. for (int xx = -1; xx < 2; xx++) { for (int yy = -1; yy < 2; yy++) { for (int zz = -1; zz < 2; zz++) { int chunkx = playerx / Server.chunksize + xx; int chunky = playery / Server.chunksize + yy; int chunkz = playerz / Server.chunksize + zz; if (!MapUtil.IsValidChunkPos(server.d_Map, chunkx, chunky, chunkz, Server.chunksize)) { continue; } ServerChunk chunk = server.d_Map.GetChunk(chunkx * Server.chunksize, chunky * Server.chunksize, chunkz * Server.chunksize); if (chunk == null) { continue; } if (chunk.Entities == null) { continue; } for (int i = 0; i < chunk.EntitiesCount; i++) { if (chunk.Entities[i] == null) { continue; } if (chunk.Entities[i].position == null) { continue; } ServerEntityId id = new ServerEntityId(); id.chunkx = chunkx; id.chunky = chunky; id.chunkz = chunkz; id.id = i; list.Add(id); } } } } // Return maxCount of entities nearest to player. list.Sort((a, b) => { var entityA = server.d_Map.GetChunk(a.chunkx * Server.chunksize, a.chunky * Server.chunksize, a.chunkz * Server.chunksize).Entities[a.id]; var entityB = server.d_Map.GetChunk(b.chunkx * Server.chunksize, b.chunky * Server.chunksize, b.chunkz * Server.chunksize).Entities[b.id]; Vector3i posA = new Vector3i((int)entityA.position.x, (int)entityA.position.y, (int)entityA.position.z); Vector3i posB = new Vector3i((int)entityB.position.x, (int)entityB.position.y, (int)entityB.position.z); Vector3i posPlayer = new Vector3i(c.PositionMul32GlX / 32, c.PositionMul32GlY / 32, c.PositionMul32GlZ / 32); return(server.DistanceSquared(posA, posPlayer).CompareTo(server.DistanceSquared(posB, posPlayer))); } ); int retCount = maxCount; if (list.Count < maxCount) { retCount = list.Count; } for (int i = 0; i < retCount; i++) { ret[i] = list[i]; } }
public void SetChunkValid(int cx, int cy, int cz, ServerChunk chunk) { unchecked { ServerChunk[] column = chunks[MapUtilCi.Index2d(cx, cy, invertChunk(MapSizeX))]; if (column == null) { column = new ServerChunk[invertChunk(MapSizeZ)]; chunks[MapUtilCi.Index2d(cx, cy, invertChunk( MapSizeX))] = column; } column[cz] = chunk; } }
void OnPermission(PermissionArgs args) { for (int x = 0; x < 3; x++) { for (int y = 0; y < 3; y++) { for (int z = 0; z < 3; z++) { int cx = args.GetX() / Server.chunksize + x - 1; int cy = args.GetY() / Server.chunksize + y - 1; int cz = args.GetZ() / Server.chunksize + z - 1; if (!MapUtil.IsValidChunkPos(server.d_Map, cx, cy, cz, Server.chunksize)) { continue; } ServerChunk c = server.d_Map.GetChunk_(cx, cy, cz); if (c == null) { return; } for (int i = 0; i < c.EntitiesCount; i++) { ServerEntity e = c.Entities[i]; if (e == null) { continue; } if (e.permissionSign == null) { continue; } if (e.drawArea == null) { continue; } if (!InArea(args.GetX(), args.GetY(), args.GetZ(), e.drawArea.x, e.drawArea.z, e.drawArea.y, e.drawArea.sizex, e.drawArea.sizez, e.drawArea.sizey)) { continue; } if (e.permissionSign.type == PermissionSignType.Group) { if (e.permissionSign.name == server.clients[args.GetPlayer()].clientGroup.Name) { args.SetAllowed(true); return; } } if (e.permissionSign.type == PermissionSignType.Player) { if (e.permissionSign.name == server.clients[args.GetPlayer()].playername) { args.SetAllowed(true); return; } } } } } } }
public void SaveChunksToDatabase(List<Vector3i> chunkPositions, string filename) { if (!GameStorePath.IsValidName(filename)) { Console.WriteLine("Invalid backup filename: " + filename); return; } if (!Directory.Exists(GameStorePath.gamepathbackup)) { Directory.CreateDirectory(GameStorePath.gamepathbackup); } string finalFilename = Path.Combine(GameStorePath.gamepathbackup, filename + MapManipulator.BinSaveExtension); List<DbChunk> dbchunks = new List<DbChunk>(); foreach (Vector3i pos in chunkPositions) { int dx = pos.x / chunksize; int dy = pos.y / chunksize; int dz = pos.z / chunksize; ServerChunk cc = new ServerChunk() { data = this.GetChunk(pos.x, pos.y, pos.z) }; MemoryStream ms = new MemoryStream(); Serializer.Serialize(ms, cc); dbchunks.Add(new DbChunk() { Position = new Xyz() { X = dx, Y = dy, Z = dz }, Chunk = ms.ToArray() }); } if (dbchunks.Count != 0) { IChunkDb d_ChunkDb = new ChunkDbCompressed() { d_ChunkDb = new ChunkDbSqlite(), d_Compression = new CompressionGzip() }; d_ChunkDb.SetChunksToFile(dbchunks, finalFilename); } else { Console.WriteLine(string.Format("0 chunks selected. Nothing to do.")); } Console.WriteLine(string.Format("Saved {0} chunk(s) to database.", dbchunks.Count)); }
/// <summary> /// Grow at a season /// </summary> private bool GrowSeasonLogic(GrowingEntity entity, Season season, UtopiaTimeSpan passedTime, Random random, ServerChunk chunk, out bool rotten) { bool updated = false; rotten = false; // constranits check if (entity.GrowingSeasons.Count > 0 && !entity.GrowingSeasons.Contains(season.Name)) { return(false); } if (entity.GrowingBlocks.Count > 0 && _server != null) { if (entity.Linked) { var cursor = _server.LandscapeManager.GetCursor(entity.LinkedCube); if (!entity.GrowingBlocks.Contains(cursor.Read())) { return(false); } } else { var cursor = _server.LandscapeManager.GetCursor(entity.Position); if (!entity.GrowingBlocks.Contains(cursor.PeekValue(Vector3I.Down))) { return(false); } } } // TODO: check light constraint when implemented entity.CurrentGrowTime += passedTime; var plant = entity as PlantGrowingEntity; if (plant != null) { // update entity to the actual state while (!plant.IsLastGrowLevel) { var currentLevel = plant.CurrentGrowLevel; if (plant.CurrentGrowTime < currentLevel.GrowTime) { break; } if (plant.CurrentGrowLevelIndex == 0 && plant.RottenChance != 0f) { if (random.NextDouble() < plant.RottenChance) { if (chunk != null) { chunk.Entities.RemoveById(plant.StaticId); } rotten = true; return(true); } } plant.CurrentGrowTime -= currentLevel.GrowTime; plant.CurrentGrowLevelIndex++; updated = true; } } var tree = entity as TreeGrowingEntity; if (tree != null) { // the seed will not grow if there is a tree nearby foreach (var checkChunk in _server.LandscapeManager.AroundChunks(tree.Position)) { if (checkChunk.Entities.OfType <TreeSoul>().Any(s => Vector3D.Distance(s.Position, tree.Position) < 16)) { return(false); } if (checkChunk.Entities.OfType <TreeGrowingEntity>().Any(t => t != tree && t.Scale > 0.1 && Vector3D.Distance(t.Position, tree.Position) < 16)) { return(false); } } updated = true; } return(updated); }
public void SetChunks(int offsetX, int offsetY, int offsetZ, Dictionary<Xyz, ushort[]> chunks) { if (chunks.Count == 0) { return; } foreach (var k in chunks) { if (k.Value == null) { continue; } // TODO: check bounds. ServerChunk c = d_Map.GetChunkValid(k.Key.X + offsetX, k.Key.Y + offsetY, k.Key.Z + offsetZ); if (c == null) { c = new ServerChunk(); } c.data = k.Value; c.DirtyForSaving = true; d_Map.SetChunkValid(k.Key.X + offsetX, k.Key.Y + offsetY, k.Key.Z + offsetZ, c); } // update related chunk at clients foreach (var k in clients) { //TODO wrong //k.Value.chunksseen.Clear(); Array.Clear(k.Value.chunksseen, 0, k.Value.chunksseen.Length); } }
public void EntityGrowCheck(UtopiaTime now, GrowingEntity entity, ServerChunk chunk, Random random) { if (entity.LastGrowUpdate.IsZero) { return; } var checkTimeSpan = now - entity.LastGrowUpdate; bool updated; bool rotten; // grow time left at the current season var tillTheEndOfSeason = UtopiaTimeSpan.FromSeasons(1d - entity.LastGrowUpdate.TotalSeasons % 1d); if (checkTimeSpan <= tillTheEndOfSeason) { // small grow update updated = GrowSeasonLogic(entity, now.Season, checkTimeSpan, random, chunk, out rotten); if (rotten) { return; } } else { // grow at the end of the first season updated = GrowSeasonLogic(entity, now.Season, tillTheEndOfSeason, random, chunk, out rotten); if (rotten) { return; } // align time to the beginning of next season checkTimeSpan -= tillTheEndOfSeason; while (checkTimeSpan.TotalSeconds > 0) { var seasonCheckSpan = checkTimeSpan.TotalSeasons > 0 ? UtopiaTimeSpan.FromSeasons(1) : checkTimeSpan; updated = GrowSeasonLogic(entity, (now - checkTimeSpan).Season, seasonCheckSpan, random, chunk, out rotten) || updated; if (rotten) { return; } checkTimeSpan -= seasonCheckSpan; } } if (updated) { if (entity is PlantGrowingEntity) { if (chunk != null) { chunk.Entities.RemoveById(entity.StaticId); chunk.Entities.Add(entity); } } var tree = entity as TreeGrowingEntity; if (tree != null) { var treeBlueprint = _server.EntityFactory.Config.TreeBluePrintsDico[tree.TreeTypeId]; if (tree.CurrentGrowTime > treeBlueprint.GrowTime) { // the tree is ready var model = VoxelModel.GenerateTreeModel(tree.TreeRndSeed, treeBlueprint); // create tree blocks var rootOffset = model.States[0].PartsStates[0].Translation; var cursor = _server.LandscapeManager.GetCursor(tree.Position); var frame = model.Frames[0]; var range = new Range3I(new Vector3I(), frame.BlockData.ChunkSize); using (cursor.TransactionScope()) { foreach (var position in range) { var value = frame.BlockData.GetBlock(position); if (value == 0) { continue; } var blockType = value == 1 ? treeBlueprint.TrunkBlock : treeBlueprint.FoliageBlock; var worldPos = (Vector3I)(tree.Position + rootOffset) + position; cursor.GlobalPosition = worldPos; if (cursor.Read() == WorldConfiguration.CubeId.Air) { cursor.Write(blockType); } } } // create tree soul var soul = _server.EntityFactory.CreateEntity <TreeSoul>(); soul.Position = tree.Position; soul.TreeRndSeed = tree.TreeRndSeed; soul.TreeTypeId = tree.TreeTypeId; chunk.Entities.Add(soul); // remove the growing tree chunk.Entities.RemoveById(tree.StaticId); } else { // just make the model bigger tree.Scale = (float)tree.CurrentGrowTime.TotalSeconds / treeBlueprint.GrowTime.TotalSeconds; chunk.Entities.RemoveById(tree.StaticId); chunk.Entities.Add(tree); } } } }