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); }
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); } }
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); }
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]); }
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); }
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); }
//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); }
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); }
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); }
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); }
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)); }