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, Packet_BlockSetModeEnum.Create)) { 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 = GetHeadingLookAt(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 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); }
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); }
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 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); }
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 LoadChunk(int cx, int cy, int cz) { ServerChunk chunk = GetChunkValid(cx, cy, cz); if (chunk == null) { GetChunk(cx * chunksize, cy * chunksize, cz * chunksize); } }
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 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)); }
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; } } }
//10 minutes void ChunkSimulation(Server server) { 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(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(oldestpos.x / Server.chunksize, oldestpos.y / Server.chunksize, oldestpos.z / Server.chunksize); c.LastUpdate = (int)server.simulationcurrentframe; return; } } }
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); }
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); } } } } }
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 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(chunkx, chunky, chunkz, 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]; } }
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.onentityupdate.Count; k++) { server.modEventHandlers.onentityupdate[k](e); } } // 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 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)]); }
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 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; } } } } } } }