예제 #1
0
        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);
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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);
        }
예제 #6
0
        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);
        }
예제 #7
0
        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);
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
 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;
 }
예제 #10
0
        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));
        }
예제 #11
0
        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;
                }
            }
        }
예제 #12
0
        //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;
                }
            }
        }
예제 #13
0
        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);
        }
예제 #14
0
        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);
                        }
                    }
                }
            }
        }
예제 #15
0
 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);
         }
     }
 }
예제 #16
0
        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];
            }
        }
예제 #17
0
        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));
                }
            }
        }
예제 #18
0
        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)]);
        }
예제 #19
0
        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
            }));
        }
예제 #20
0
 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;
                         }
                     }
                 }
             }
         }
     }
 }