Пример #1
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);
    }
Пример #2
0
    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);
        }
    }
Пример #3
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);
        }
    }
Пример #4
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);
    }
Пример #5
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);
    }
Пример #6
0
    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);
                        }
                    }
                }
            }
        }
    }
Пример #7
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))
            {
                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);
        }
    }
Пример #8
0
    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;
            }
        }
    }
Пример #9
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);
    }
Пример #10
0
        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);
            }
        }
Пример #11
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);
        }
    }
Пример #12
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);
    }
Пример #13
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;
 }
Пример #14
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)];
        unchecked
        {
            return(chunk.data[MapUtilCi.Index3d(moduloChunk(x), moduloChunk(y), moduloChunk(z), chunksize, chunksize)]);
        }
    }
Пример #15
0
        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;
            }
        }
Пример #16
0
    }                     //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;
                }
            }
        }
    }
Пример #17
0
 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);
         }
     }
 }
Пример #18
0
 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;
     }
 }
Пример #19
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));
    }
Пример #20
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);
    }
Пример #21
0
        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);
        }
Пример #22
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;
            }
        }
    }
Пример #23
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);
         }
     }
 }
Пример #24
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);
                    }
                }
            }
        }
    }
Пример #25
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.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));
            }
        }
    }
Пример #26
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
        }));
    }
Пример #27
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();
                        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];
        }
    }
Пример #28
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);
         }
     }
 }
Пример #29
0
 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;
     }
 }
Пример #30
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;
                         }
                     }
                 }
             }
         }
     }
 }
Пример #31
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));
    }
Пример #32
0
        /// <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);
        }
Пример #33
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);
        }
    }
Пример #34
0
        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);
                    }
                }
            }
        }