Exemple #1
0
        private static EntityModel SaturateBasicItemModel(
            Entity itemEntity,
            EntityData entityData,
            bool toLowercase)
        {
            EntityWorld     world       = itemEntity.EntityWorld;
            EntityDataCache entityDatas = WorldCache.GetCache(world).EntityDatas;
            EntityModel     entityModel = new EntityModel();

            // Get basic item details.
            if (toLowercase)
            {
                entityModel.Name = entityData.Name.ToLower();
            }
            else
            {
                entityModel.Name = entityData.Name;
            }
            entityModel.Id = itemEntity.UniqueId;
            // entityModel.Type = entityDatas.GetBasePrototype(itemEntity).Name;

            // Get quantity.
            EntityStack entityStack = itemEntity.GetComponent <EntityStack>();

            if (entityStack == null)
            {
                entityModel.Quantity = 1;
            }
            else
            {
                entityModel.Quantity = entityStack.Quantity;
            }

            return(entityModel);
        }
Exemple #2
0
            private static IEnumerator ReceivedSettings(ZNetPeer peer)
            {
                int finalHash = GetHashCode(SettingsReceiveBuffer);

                if (finalHash == SettingsReceiveHash)
                {
                    Log($"Settings transfer complete, unpacking them now");

                    var loadingTask = Task.Run(() => {
                        var settingsPkg = new ZPackage(SettingsReceiveBuffer);
                        var settings    = BetterContinentsSettings.Load(settingsPkg);
                        WorldCache.Add(settingsPkg);
                        return(settings);
                    });

                    try
                    {
                        UI.Add("ReceivedSettings", () => UI.DisplayMessage($"Better Continents: initializing from server config"));
                        yield return(new WaitUntil(() => loadingTask.IsCompleted));
                    }
                    finally
                    {
                        UI.Remove("ReceivedSettings");
                    }

                    if (loadingTask.IsFaulted)
                    {
                        LastConnectionError = $"Better Continents: cached world settings failed to load ({loadingTask.Exception.Message}), please reconnect to download them again!";
                        LogError(LastConnectionError);
                        m_connectionStatus.SetValue(null, ZNet.ConnectionStatus.ErrorConnectFailed);
                        ZNet.instance.Disconnect(peer);
                        yield break;
                    }

                    Settings = loadingTask.Result;
                    Settings.Dump();

                    // We only care about server/client version match when the server sends a world that actually uses the mod
                    if (Settings.EnabledForThisWorld && ServerVersion != ModInfo.Version)
                    {
                        LastConnectionError = $"Better Continents: world has Better Continents enabled, but server {ServerVersion} and client {ModInfo.Version} mod versions don't match";
                        LogError(LastConnectionError);
                        m_connectionStatus.SetValue(null, ZNet.ConnectionStatus.ErrorConnectFailed);
                        ZNet.instance.Disconnect(peer);
                    }
                    else if (!Settings.EnabledForThisWorld)
                    {
                        Log($"Server world does not have Better Continents enabled, skipping version check");
                    }

                    peer.m_rpc.Invoke("BetterContinentsReady", 0);
                }
                else
                {
                    LogError($"{LastConnectionError}: hash mismatch, got {finalHash}, expected {SettingsReceiveHash}");
                    m_connectionStatus.SetValue(null, ZNet.ConnectionStatus.ErrorConnectFailed);
                    ZNet.instance.Disconnect(peer);
                }
            }
Exemple #3
0
            private static IEnumerator LoadFromCache(ZNetPeer peer, string id)
            {
                var loadTask = Task.Run <BetterContinentsSettings?>(() =>
                {
                    var package = WorldCache.LoadCacheItem(id);
                    // Recalculate the id again to confirm it really matches
                    string localId = WorldCache.PackageID(package);
                    if (id != localId)
                    {
                        return(null);
                    }
                    return(BetterContinentsSettings.Load(package));
                });

                try
                {
                    UI.Add("LoadingFromCache", () => UI.DisplayMessage($"Better Continents: initializing from cached config"));
                    yield return(new WaitUntil(() => loadTask.IsCompleted));
                }
                finally
                {
                    UI.Remove("LoadingFromCache");
                }

                if (loadTask.IsFaulted || loadTask.Result == null)
                {
                    LastConnectionError = loadTask.Exception != null
                        ? $"Better Continents: cached world settings failed to load ({loadTask.Exception.Message}), please reconnect to download them again!"
                        : $"Better Continents: cached world settings are corrupted, please reconnect to download them again!";

                    LogError(LastConnectionError);
                    m_connectionStatus.SetValue(null, ZNet.ConnectionStatus.ErrorConnectFailed);
                    ZNet.instance.Disconnect(peer);
                    WorldCache.DeleteCacheItem(id);
                    yield break;
                }

                Settings = loadTask.Result.Value;
                Settings.Dump();


                // We only care about server/client version match when the server sends a world that actually uses the mod
                if (Settings.EnabledForThisWorld && ServerVersion != ModInfo.Version)
                {
                    LastConnectionError = $"Better Continents: world has the mod enabled, but server {ServerVersion} and client {ModInfo.Version} versions don't match";
                    LogError(LastConnectionError);
                    m_connectionStatus.SetValue(null, ZNet.ConnectionStatus.ErrorConnectFailed);
                    ZNet.instance.Disconnect(peer);
                }
                else if (!Settings.EnabledForThisWorld)
                {
                    Log($"Server world does not have Better Continents enabled, skipping version check");
                }

                peer.m_rpc.Invoke("BetterContinentsReady", 0);
            }
Exemple #4
0
        public static MapNode GetMapNode(this Entity entity)
        {
            Location location = entity.GetComponent <Location>();

            if (location == null)
            {
                return(null);
            }

            MapCache maps = WorldCache.GetCache(entity.EntityWorld).Maps;
            Map      map  = maps[location.Map];

            return(map[location.Position]);
        }
Exemple #5
0
        private void AddNewPlayerInventory(Entity entity)
        {
            EntityWorld     gameWorld   = entity.EntityWorld;
            EntityDataCache entityDatas = WorldCache.GetCache(gameWorld).EntityDatas;

            Container inventory = new Container(10);

            entity.AddComponent(inventory);

            Entity itemStack = gameWorld.CreateEntity();

            itemStack.AddComponent(new EntityStack(3, 3));
            itemStack.AddComponent(entityDatas[EntityType.Consumable]);

            Entity itemSingle = gameWorld.CreateEntity();

            itemSingle.AddComponent(entityDatas[EntityType.Consumable]);

            Entity     bag           = gameWorld.CreateEntity();
            Container  bagContainer  = new Container(3);
            EntityData bagEntityData = new EntityData(
                Guid.NewGuid(),
                "Bag",
                "Just some bag.",
                null,
                EntityType.Container);

            entityDatas.Add(bagEntityData);
            bag.AddComponent(bagEntityData);
            bag.AddComponent(bagContainer);
            bagContainer.AddEntity(itemStack);

            Entity     backpack           = gameWorld.CreateEntity();
            Container  backpackContainer  = new Container(3);
            EntityData backpackEntityData = new EntityData(
                Guid.NewGuid(),
                "Backpack",
                "A weathered old backpack.",
                null,
                EntityType.Container);

            entityDatas.Add(backpackEntityData);
            backpack.AddComponent(backpackEntityData);
            backpack.AddComponent(backpackContainer);

            inventory.AddEntity(bag);
            inventory.AddEntity(backpack);
            inventory.AddEntity(itemSingle);
        }
Exemple #6
0
        public string DebugClearCachedWorld(int game_id)
        {
            BasicResponse response = new BasicResponse();

            if (RestUtilities.ValidateJSONRequestHasAuthenticatedSession(Session, out response.result) &&
                RestUtilities.ValidateJSONRequestSessionHasAdminOpsLevel(Session, out response.result))
            {
                WorldCache.ClearWorld(Application, game_id);
                WorldBuilderCache.ClearWorldBuilder(Application);

                response.result = SuccessMessages.GENERAL_SUCCESS;
            }

            return(JSONUtilities.SerializeJSONResponse <BasicResponse>(response));
        }
        private bool ClearPlayerFromCache(
            RequestCache requestCache,
            out string result_code)
        {
            bool success;

            if (m_character_state.game_id != -1)
            {
                World world =
                    WorldCache.GetWorld(
                        requestCache.DatabaseContext,
                        requestCache.SessionCache,
                        m_character_state.game_id);

                if (world != null)
                {
                    requestCache.RemovePlayer(
                        new RoomKey(
                            m_character_state.game_id,
                            m_character_state.room_x,
                            m_character_state.room_y,
                            m_character_state.room_z),
                        m_character_id);

                    result_code = SuccessMessages.GENERAL_SUCCESS;
                    success     = true;
                }
                else
                {
                    result_code = ErrorMessages.INVALID_WORLD;
                    success     = false;
                }
            }
            else
            {
                // Character not bound to game, thus won't be in the cache
                result_code = SuccessMessages.GENERAL_SUCCESS;
                success     = true;
            }

            return(success);
        }
Exemple #8
0
        //TODO
        private void MergeAllParentProperties(
            EntityWorld world,
            EntityData parentEntityData)
        {
            foreach (KeyValuePair <string, DynamicValue> parentProperty in parentEntityData.properties)
            {
                if (this.properties.ContainsKey(parentProperty.Key))
                {
                    continue;
                }
                this.properties.Add(parentProperty.Key, parentProperty.Value);
            }

            if (parentEntityData.parentPrototypeId != null)
            {
                parentEntityData =
                    WorldCache.GetCache(world).EntityDatas[parentEntityData.parentPrototypeId];
                MergeAllParentProperties(world, parentEntityData);
            }
        }
        protected override bool ProcessRequestInternal(
            RequestCache requestCache,
            out string result_code)
        {
            bool success = false;

            result_code = SuccessMessages.GENERAL_SUCCESS;

            if (GameQueries.VerifyAccountOwnsGame(requestCache.DatabaseContext, m_account_id, m_game_id))
            {
                GameQueries.DeleteGame(requestCache.DatabaseContext, m_game_id);
                WorldCache.ClearWorld(requestCache.SessionCache, m_game_id);
                success = true;
            }
            else
            {
                result_code = ErrorMessages.NOT_GAME_OWNER;
            }

            return(success);
        }
Exemple #10
0
        public void SetUp()
        {
            this.world  = MockWorld.Generate();
            this.entity = this.world.CreateEntity();

            this.interpreter = new Interpreter(Assembly.GetAssembly(typeof(ReverieGame)));

            Container inventory = new Container(10);

            this.entity.AddComponent(inventory);

            EntityDataCache entityDatas = WorldCache.GetCache(this.world).EntityDatas;

            Entity itemStack = this.world.CreateEntity();

            itemStack.AddComponent(new EntityStack(3, 3));
            itemStack.AddComponent(entityDatas[EntityType.Consumable]);

            Entity itemSingle = this.world.CreateEntity();

            itemSingle.AddComponent(entityDatas[EntityType.Consumable]);

            Entity     bag           = this.world.CreateEntity();
            Container  container     = new Container(3);
            EntityData bagEntityData = new EntityData(
                Guid.NewGuid(),
                "Bag",
                "Just a bag.",
                null,
                EntityType.Container);

            bag.AddComponent(bagEntityData);
            bag.AddComponent(container);
            container.AddEntity(itemStack);

            inventory.AddEntity(bag);
            inventory.AddEntity(itemSingle);
        }
Exemple #11
0
        protected override bool ProcessRequestInternal(
            RequestCache requestCache,
            out string result_code)
        {
            bool success = false;

            result_code = SuccessMessages.GENERAL_SUCCESS;

            m_new_game_id =
                GameQueries.CreateGame(
                    requestCache.DatabaseContext,
                    m_account_id,
                    m_game_name,
                    m_dungeon_size,
                    m_dungeon_difficulty,
                    m_irc_enabled,
                    m_irc_server,
                    m_irc_port,
                    m_irc_encryption_enabled);

            if (m_new_game_id >= 0)
            {
                success =
                    WorldCache.BuildWorld(
                        requestCache.DatabaseContext,
                        requestCache.SessionCache,
                        m_new_game_id,
                        out result_code);

                if (!success)
                {
                    GameQueries.DeleteGame(requestCache.DatabaseContext, m_new_game_id);
                }
            }

            return(success);
        }
Exemple #12
0
            private static IEnumerator SendSettings(ZNet instance, ZRpc rpc, ZPackage pkg)
            {
                byte[] ArraySlice(byte[] source, int offset, int length)
                {
                    var target = new byte[length];

                    Buffer.BlockCopy(source, offset, target, 0, length);
                    return(target);
                }

                var peer = instance.GetPeers().First(p => p.m_rpc == rpc);

                if (!Settings.EnabledForThisWorld)
                {
                    Log($"Skipping sending settings to {PeerName(peer)}, as Better Continents is not enabled in this world");
                }
                else
                {
                    Log($"World is using Better Continents, so client version must match server version {ModInfo.Name}");

                    if (!ClientInfo.TryGetValue(peer.m_uid, out var bcClientInfo))
                    {
                        Log($"Client info for {PeerName(peer)} not found, client has an old version of Better Continents, or none!");
                        rpc.Invoke("Error", ZNet.ConnectionStatus.ErrorConnectFailed);
                        ZNet.instance.Disconnect(peer);
                        yield break;
                    }
                    else if (bcClientInfo.version != ModInfo.Version)
                    {
                        Log($"Client {PeerName(peer)} version {bcClientInfo.version} doesn't match server version {ModInfo.Version}");
                        peer.m_rpc.Invoke("Error", 69);
                        ZNet.instance.Disconnect(peer);
                        yield break;
                    }
                    else
                    {
                        Log($"Client {PeerName(peer)} version {bcClientInfo.version} matches server version {ModInfo.Version}");
                    }

                    // This was the initial way that versioning was implemented, before the client->server way, so may
                    // as well leave it in
                    Log($"Sending server version {ModInfo.Version} to client for bi-lateral version agreement");
                    rpc.Invoke("BetterContinentsVersion", ModInfo.Version);

                    var settingsPackage = new ZPackage();
                    var cleanSettings   = Settings.Clean();
                    cleanSettings.Serialize(settingsPackage);

                    if (WorldCache.CacheItemExists(settingsPackage, bcClientInfo.worldCache))
                    {
                        // We send hash and id
                        string cacheId = WorldCache.PackageID(settingsPackage);
                        Log($"Client {PeerName(peer)} already has cached settings for world, instructing it to load those (id {cacheId})");
                        rpc.Invoke("BetterContinentsConfigLoadFromCache", cacheId);
                    }
                    else
                    {
                        Log($"Client {PeerName(peer)} doesn't have cached settings, sending them now");
                        cleanSettings.Dump();

                        var settingsData = settingsPackage.GetArray();
                        Log($"Sending settings package header for {settingsData.Length} byte stream");
                        rpc.Invoke("BetterContinentsConfigStart", settingsData.Length, GetHashCode(settingsData));

                        const int SendChunkSize = 256 * 1024;

                        for (int sentBytes = 0; sentBytes < settingsData.Length;)
                        {
                            int packetSize = Mathf.Min(settingsData.Length - sentBytes, SendChunkSize);
                            var packet     = ArraySlice(settingsData, sentBytes, packetSize);
                            rpc.Invoke("BetterContinentsConfigPacket", sentBytes, GetHashCode(packet),
                                       new ZPackage(packet));
                            // Make sure to flush or we will saturate the queue...
                            rpc.GetSocket().Flush();
                            sentBytes += packetSize;
                            Log($"Sent {sentBytes} of {settingsData.Length} bytes");
                            float timeout = Time.time + 30;
                            yield return(new WaitUntil(() => rpc.GetSocket().GetSendQueueSize() < SendChunkSize || Time.time > timeout));

                            if (Time.time > timeout)
                            {
                                Log($"Timed out sending config to client {PeerName(peer)} after 30 seconds, disconnecting them");
                                peer.m_rpc.Invoke("Error", ZNet.ConnectionStatus.ErrorConnectFailed);
                                ZNet.instance.Disconnect(peer);
                                yield break;
                            }
                        }
                    }
                    yield return(new WaitUntil(() => ClientInfo[peer.m_uid].readyForPeerInfo || !peer.m_socket.IsConnected()));
                }

                RPC_PeerInfo(instance, rpc, pkg);
            }
Exemple #13
0
            private static void OnNewConnectionPrefix(ZNet __instance, ZNetPeer peer)
            {
                Log($"Registering settings RPC");

                ServerVersion = "(old)";

                if (ZNet.instance.IsServer())
                {
                    ClientInfo.Remove(peer.m_uid);
                    peer.m_rpc.Register("BetterContinentsServerHandshake", (ZRpc rpc, string clientVersion, ZPackage worldCache) =>
                    {
                        Log($"Receiving client {PeerName(peer)} version {clientVersion}");
                        // We check this when sending settings (if we have a BC world loaded, otherwise it doesn't matter)
                        ClientInfo[peer.m_uid] = new BCClientInfo {
                            version = clientVersion, worldCache = worldCache, readyForPeerInfo = false
                        };
                    });

                    peer.m_rpc.Register("BetterContinentsReady", (ZRpc rpc, int stage) =>
                    {
                        Log($"Client is ready for PeerInfo");

                        // We wait for this flag before continuing after sending the world settings, allowing the client to behave asynchronously on its end
                        ClientInfo[peer.m_uid].readyForPeerInfo = true;
                    });
                }
                else
                {
                    peer.m_rpc.Invoke("BetterContinentsServerHandshake", ModInfo.Version, WorldCache.SerializeCacheList());

                    peer.m_rpc.Register("BetterContinentsVersion", (ZRpc rpc, string serverVersion) =>
                    {
                        ServerVersion = serverVersion;
                        Log($"Receiving server version {serverVersion}");
                    });

                    peer.m_rpc.Register("BetterContinentsConfigLoadFromCache", (ZRpc rpc, string id) =>
                    {
                        Log($"Loading server world settings from local cache, id {id}");

                        __instance.StartCoroutine(LoadFromCache(peer, id));
                    });

                    peer.m_rpc.Register("BetterContinentsConfigStart", (ZRpc rpc, int totalBytes, int hash) =>
                    {
                        SettingsReceiveBuffer = new byte[totalBytes];
                        SettingsReceiveHash   = hash;
                        SettingsReceiveBufferBytesReceived = 0;
                        Log($"Receiving settings from server ({SettingsReceiveBuffer.Length} bytes)");

                        UI.Add("ConfigDownload", () => UI.ProgressBar(SettingsReceiveBufferBytesReceived * 100 / SettingsReceiveBuffer.Length, $"Better Continents: downloading world settings from server ..."));
                    });

                    peer.m_rpc.Register("BetterContinentsConfigPacket", (ZRpc rpc, int offset, int packetHash, ZPackage packet) =>
                    {
                        var packetData = packet.GetArray();
                        int hash       = GetHashCode(packetData);
                        if (hash != packetHash)
                        {
                            LastConnectionError = $"Better Continents: settings from server were corrupted during transfer, please reconnect!";
                            LogError($"{LastConnectionError}: packet hash mismatch, got {hash}, expected {packetHash}");

                            m_connectionStatus.SetValue(null, ZNet.ConnectionStatus.ErrorConnectFailed);
                            ZNet.instance.Disconnect(peer);
                            return;
                        }

                        Buffer.BlockCopy(packetData, 0, SettingsReceiveBuffer, offset, packetData.Length);

                        SettingsReceiveBufferBytesReceived += packetData.Length;

                        Log($"Received settings packet {packetData.Length} bytes at {offset}, {SettingsReceiveBufferBytesReceived} / {SettingsReceiveBuffer.Length} received");
                        if (SettingsReceiveBufferBytesReceived == SettingsReceiveBuffer.Length)
                        {
                            UI.Remove("ConfigDownload");
                            __instance.StartCoroutine(ReceivedSettings(peer));
                        }
                    });
                }
            }
 public World GetWorld(
     int game_id)
 {
     return(WorldCache.GetWorld(m_dbContext, m_sessionCache, game_id));
 }