void OnServerCharacterDelete(NetworkMessage netMsg) { print("OnServerCharacterDelete " + netMsg.conn); var msg = netMsg.ReadMessage <CharacterDeleteMsg>(); // can only delete while in lobby (aka after handshake and not ingame) if (lobby.ContainsKey(netMsg.conn)) { var account = lobby[netMsg.conn]; var chars = Database.CharactersForAccount(account); // validate index if (0 <= msg.index && msg.index < chars.Count) { // delete the character print("delete character: " + msg.index); Database.CharacterDelete(account, chars[msg.index]); // send the new character list to client var msgchars = new CharactersAvailableMsg(); msgchars.characters = Database.CharactersForAccount(account).ToArray(); netMsg.conn.Send(CharactersAvailableMsg.MsgId, msgchars); } else { print("invalid character index: " + account + " " + msg.index); ClientSendPopup(netMsg.conn, "invalid character index", false); } } else { print("CharacterDelete: not in lobby: " + netMsg.conn); ClientSendPopup(netMsg.conn, "CharacterDelete: not in lobby", true); } }
void OnServerLogin(NetworkMessage netMsg) { print("OnServerLogin " + netMsg.conn); var msg = netMsg.ReadMessage <LoginMsg>(); // not too long? if (msg.id.Length <= accountMaxLength) { // only contains letters, number and underscore and not empty (+)? // (important for database safety etc.) if (Regex.IsMatch(msg.id, @"^[a-zA-Z0-9_]+$")) { // validate account info if (Database.IsValidAccount(msg.id, msg.pw)) { // not in lobby and not in world yet? if (!AccountLoggedIn(msg.id)) { print("login successful: " + msg.id); // add to logged in accounts lobby[netMsg.conn] = msg.id; // send available characters to client var chars = Database.CharactersForAccount(msg.id); var msgchars = new CharactersAvailableMsg { characterNames = chars.Keys.ToArray(), characterClasses = chars.Values.ToArray() }; netMsg.conn.Send(CharactersAvailableMsg.MsgId, msgchars); } else { print("account already logged in: " + msg.id); ClientSendPopup(netMsg.conn, "already logged in", true); // note: we should disconnect the client here, but we can't as // long as unity has no "SendAllAndThenDisconnect" function, // because then the error message would never be sent. //netMsg.conn.Disconnect(); } } else { print("invalid account or password for: " + msg.id); ClientSendPopup(netMsg.conn, "invalid account", true); } } else { print("account invalid: " + msg.id); ClientSendPopup(netMsg.conn, "forbidden account name", true); } } else { print("account too long: " + msg.id); ClientSendPopup(netMsg.conn, "account too long", true); } }
void OnClientCharactersAvailable(NetworkMessage netMsg) { charactersAvailableMsg = netMsg.ReadMessage <CharactersAvailableMsg>(); print("characters available:" + charactersAvailableMsg.characters.Length); // set state state = NetworkState.Lobby; // clear previous previews in any case ClearPreviews(); // load previews for 3D character selection for (int i = 0; i < charactersAvailableMsg.characters.Length; ++i) { CharactersAvailableMsg.CharacterPreview character = charactersAvailableMsg.characters[i]; // find the prefab for that class Player prefab = GetPlayerClasses().Find(p => p.name == character.className); if (prefab != null) { LoadPreview(prefab.gameObject, selectionLocations[i], i, character); } else { Debug.LogWarning("Character Selection: no prefab found for class " + character.className); } } // setup camera Camera.main.transform.position = selectionCameraLocation.position; Camera.main.transform.rotation = selectionCameraLocation.rotation; // addon system hooks Utils.InvokeMany(typeof(NetworkManagerMMO), this, "OnClientCharactersAvailable_", charactersAvailableMsg); }
void OnClientCharactersAvailable(NetworkConnection conn, CharactersAvailableMsg message) { charactersAvailableMsg = message; print("存档中可用角色:" + charactersAvailableMsg.characters.Length); // set state state = NetworkState.Lobby; // clear previous previews in any case ClearPreviews(); // load previews for 3D character selection for (int i = 0; i < charactersAvailableMsg.characters.Length; ++i) { CharactersAvailableMsg.CharacterPreview character = charactersAvailableMsg.characters[i]; // find the prefab for that class Player prefab = GetPlayerClasses().Find(p => p.name == character.className); if (prefab != null) { LoadPreview(prefab.gameObject, selectionLocations[i], i, character); } else { Debug.LogWarning("没有找到对应类名的预制体 " + character.className); } } // setup camera Camera.main.transform.position = selectionCameraLocation.position; Camera.main.transform.rotation = selectionCameraLocation.rotation; }
// handshake: character selection ////////////////////////////////////////// void OnClientCharactersAvailable(NetworkMessage netMsg) { charactersAvailableMsg = netMsg.ReadMessage<CharactersAvailableMsg>(); print("characters available:" + charactersAvailableMsg.characters.Length); // addon system hooks Utils.InvokeMany(typeof(NetworkManagerMMO), this, "OnClientCharactersAvailable_", charactersAvailableMsg); }
void OnServerLogin(NetworkMessage netMsg) { print("OnServerLogin " + netMsg.conn); LoginMsg message = netMsg.ReadMessage <LoginMsg>(); // correct version? if (message.version == Application.version) { // allowed account name? if (IsAllowedAccountName(message.account)) { // validate account info if (Database.IsValidAccount(message.account, message.password)) { // not in lobby and not in world yet? if (!AccountLoggedIn(message.account)) { print("login successful: " + message.account); // add to logged in accounts lobby[netMsg.conn] = message.account; // send necessary data to client CharactersAvailableMsg reply = MakeCharactersAvailableMessage(message.account); netMsg.conn.Send(CharactersAvailableMsg.MsgId, reply); // addon system hooks Utils.InvokeMany(typeof(NetworkManagerMMO), this, "OnServerLogin_", message); } else { print("account already logged in: " + message.account); ClientSendPopup(netMsg.conn, "already logged in", true); // note: we should disconnect the client here, but we can't as // long as unity has no "SendAllAndThenDisconnect" function, // because then the error message would never be sent. //netMsg.conn.Disconnect(); } } else { print("invalid account or password for: " + message.account); ClientSendPopup(netMsg.conn, "invalid account", true); } } else { print("account name not allowed: " + message.account); ClientSendPopup(netMsg.conn, "account name not allowed", true); } } else { print("version mismatch: " + message.account + " expected:" + Application.version + " received: " + message.version); ClientSendPopup(netMsg.conn, "outdated version", true); } }
CharactersAvailableMsg MakeCharactersAvailableMessage(string account) { List <string> names = Database.singleton.CharactersForAccount(account); List <Player> characters = new List <Player>(); foreach (string character in names) { GameObject player = Database.singleton.CharacterLoad(character, playerClasses, true); characters.Add(player.GetComponent <Player>()); } CharactersAvailableMsg message = new CharactersAvailableMsg(); message.Load(characters); characters.ForEach(player => Destroy(player.gameObject)); return(message); }
private void OnClientCharactersAvailable_UCE_NetworkZones(CharactersAvailableMsg message) { int index = message.characters.ToList().FindIndex(c => c.name == UCE_NetworkZone.autoSelectCharacter); if (index != -1) { // send character select message print("[Zones]: autoselect " + UCE_NetworkZone.autoSelectCharacter + "(" + index + ")"); byte[] extra = BitConverter.GetBytes(index); ClientScene.AddPlayer(NetworkClient.connection, extra); // clear auto select UCE_NetworkZone.autoSelectCharacter = ""; } }
// helper function to make a CharactersAvailableMsg from all characters in // an account CharactersAvailableMsg MakeCharactersAvailableMessage(string account) { // load from database List<Player> characters = Database.CharactersForAccount(account) .Select(character => Database.CharacterLoad(character, GetPlayerClasses())) .Select(go => go.GetComponent<Player>()) .ToList(); // construct the message CharactersAvailableMsg message = new CharactersAvailableMsg(); message.Load(characters); // destroy the temporary players again and return the result characters.ForEach(player => Destroy(player.gameObject)); return message; }
void OnServerCharacterDelete(NetworkMessage netMsg) { print("OnServerCharacterDelete " + netMsg.conn); var message = netMsg.ReadMessage <CharacterDeleteMsg>(); // can only delete while in lobby (aka after handshake and not ingame) if (lobby.ContainsKey(netMsg.conn)) { string account = lobby[netMsg.conn]; var characters = Database.CharactersForAccount(account); // validate index if (0 <= message.index && message.index < characters.Count) { // delete the character print("delete character: " + characters.Keys.ElementAt(message.index)); Database.CharacterDelete(characters.Keys.ElementAt(message.index)); // addon system hooks Utils.InvokeMany(typeof(NetworkManagerMMO), this, "OnServerCharacterDelete_", message); // send the new character list to client characters = Database.CharactersForAccount(account); var msgchars = new CharactersAvailableMsg { characterNames = characters.Keys.ToArray(), characterClasses = characters.Values.ToArray() }; netMsg.conn.Send(CharactersAvailableMsg.MsgId, msgchars); } else { print("invalid character index: " + account + " " + message.index); ClientSendPopup(netMsg.conn, "invalid character index", false); } } else { print("CharacterDelete: not in lobby: " + netMsg.conn); ClientSendPopup(netMsg.conn, "CharacterDelete: not in lobby", true); } }
// helper function to make a CharactersAvailableMsg from all characters in // an account CharactersAvailableMsg MakeCharactersAvailableMessage(string account) { // load from database // (avoid Linq for performance/gc. characters are loaded frequently!) List <Player> characters = new List <Player>(); foreach (string characterName in Database.singleton.CharactersForAccount(account)) { GameObject player = Database.singleton.CharacterLoad(characterName, playerClasses, true); characters.Add(player.GetComponent <Player>()); } // construct the message CharactersAvailableMsg message = new CharactersAvailableMsg(); message.Load(characters); // destroy the temporary players again and return the result characters.ForEach(player => Destroy(player.gameObject)); return(message); }
void OnServerCharacterDelete(NetworkMessage netMsg) { print("OnServerCharacterDelete " + netMsg.conn); CharacterDeleteMsg message = netMsg.ReadMessage <CharacterDeleteMsg>(); // only while in lobby (aka after handshake and not ingame) if (lobby.ContainsKey(netMsg.conn)) { string account = lobby[netMsg.conn]; List <string> characters = Database.CharactersForAccount(account); // validate index if (0 <= message.index && message.index < characters.Count) { // delete the character print("delete character: " + characters[message.index]); Database.CharacterDelete(characters[message.index]); // addon system hooks Utils.InvokeMany(typeof(NetworkManagerMMO), this, "OnServerCharacterDelete_", message); // send the new character list to client characters = Database.CharactersForAccount(account); CharactersAvailableMsg reply = MakeCharactersAvailableMessage(account); netMsg.conn.Send(CharactersAvailableMsg.MsgId, reply); } else { print("invalid character index: " + account + " " + message.index); ClientSendPopup(netMsg.conn, "invalid character index", false); } } else { print("CharacterDelete: not in lobby: " + netMsg.conn); ClientSendPopup(netMsg.conn, "CharacterDelete: not in lobby", true); } }
void OnServerCharacterCreate(NetworkMessage netMsg) { print("OnServerCharacterCreate " + netMsg.conn); CharacterCreateMsg message = netMsg.ReadMessage <CharacterCreateMsg>(); // only while in lobby (aka after handshake and not ingame) if (lobby.ContainsKey(netMsg.conn)) { // allowed character name? if (IsAllowedCharacterName(message.name)) { // not existant yet? string account = lobby[netMsg.conn]; if (!Database.CharacterExists(message.name)) { // not too may characters created yet? if (Database.CharactersForAccount(account).Count < characterLimit) { // valid class index? List <Player> classes = GetPlayerClasses(); if (0 <= message.classIndex && message.classIndex < classes.Count) { // create new character based on the prefab. // -> we also assign default items and equipment for new characters // -> skills are handled in Database.CharacterLoad every time. if we // add new ones to a prefab, all existing players should get them // (instantiate temporary player) print("creating character: " + message.name + " " + message.classIndex); Player prefab = GameObject.Instantiate(classes[message.classIndex]).GetComponent <Player>(); prefab.name = message.name; prefab.account = account; prefab.className = classes[message.classIndex].name; prefab.transform.position = GetStartPositionFor(prefab.className).position; for (int i = 0; i < prefab.inventorySize; ++i) { // add empty slot or default item if any prefab.inventory.Add(i < prefab.defaultItems.Length ? new ItemSlot(new Item(prefab.defaultItems[i])) : new ItemSlot()); } for (int i = 0; i < prefab.equipmentInfo.Length; ++i) { // add empty slot or default item if any EquipmentInfo info = prefab.equipmentInfo[i]; prefab.equipment.Add(info.defaultItem != null ? new ItemSlot(new Item(info.defaultItem)) : new ItemSlot()); } prefab.health = prefab.healthMax; // after equipment in case of boni prefab.mana = prefab.manaMax; // after equipment in case of boni // addon system hooks Utils.InvokeMany(typeof(NetworkManagerMMO), this, "OnServerCharacterCreate_", message, prefab); // save the player Database.CharacterSave(prefab, false); GameObject.Destroy(prefab.gameObject); // send available characters list again, causing // the client to switch to the character // selection scene again CharactersAvailableMsg reply = MakeCharactersAvailableMessage(account); netMsg.conn.Send(CharactersAvailableMsg.MsgId, reply); } else { print("character invalid class: " + message.classIndex); ClientSendPopup(netMsg.conn, "character invalid class", false); } } else { print("character limit reached: " + message.name); ClientSendPopup(netMsg.conn, "character limit reached", false); } } else { print("character name already exists: " + message.name); ClientSendPopup(netMsg.conn, "name already exists", false); } } else { print("character name not allowed: " + message.name); ClientSendPopup(netMsg.conn, "character name not allowed", false); } } else { print("CharacterCreate: not in lobby"); ClientSendPopup(netMsg.conn, "CharacterCreate: not in lobby", true); } }
void OnServerCharacterCreate(NetworkMessage netMsg) { print("OnServerCharacterCreate " + netMsg.conn); var msg = netMsg.ReadMessage <CharacterCreateMsg>(); // can only delete while in lobby (aka after handshake and not ingame) if (lobby.ContainsKey(netMsg.conn)) { // not too long? if (msg.name.Length <= charNameMaxLength) { // only contains letters, number and underscore and not empty (+)? // (important for database safety etc.) if (Regex.IsMatch(msg.name, @"^[a-zA-Z0-9_]+$")) { // not existant yet? var account = lobby[netMsg.conn]; if (!Database.CharacterExists(msg.name)) { // not too may characters created yet? if (Database.CharactersForAccount(account).Count < charLimit) { // valid class index? var classes = GetPlayerClasses(); if (0 <= msg.classIndex && msg.classIndex < classes.Count) { // create new character based on the class // prefab's defaults print("creating character: " + msg.name + " " + msg.classIndex); var player = classes[msg.classIndex].GetComponent <Player>(); CreateCharacter(account, msg.name, player); // send available characters list again, causing // the client to switch to the character // selection scene again var msgchars = new CharactersAvailableMsg(); msgchars.characters = Database.CharactersForAccount(account).ToArray(); netMsg.conn.Send(CharactersAvailableMsg.MsgId, msgchars); } else { print("character invalid class: " + msg.classIndex); ClientSendPopup(netMsg.conn, "character invalid class", false); } } else { print("character limit reached: " + msg.name); ClientSendPopup(netMsg.conn, "character limit reached", false); } } else { print("character name already exists: " + msg.name); ClientSendPopup(netMsg.conn, "name already exists", false); } } else { print("character name invalid: " + msg.name); ClientSendPopup(netMsg.conn, "invalid name", false); } } else { print("character name too long: " + msg.name); ClientSendPopup(netMsg.conn, "name too long", false); } } else { print("CharacterCreate: not in lobby"); ClientSendPopup(netMsg.conn, "CharacterCreate: not in lobby", true); } }
void OnServerLogin(NetworkMessage netMsg) { print("OnServerLogin " + netMsg.conn); var message = netMsg.ReadMessage <LoginMsg>(); // correct version? if (message.version == Application.version) { // not too long? if (message.account.Length <= accountMaxLength) { // only contains letters, number and underscore and not empty (+)? // (important for database safety etc.) if (Regex.IsMatch(message.account, @"^[a-zA-Z0-9_]+$")) { // validate account info if (Database.IsValidAccount(message.account, message.password)) { // not in lobby and not in world yet? if (!AccountLoggedIn(message.account)) { print("login successful: " + message.account); // add to logged in accounts lobby[netMsg.conn] = message.account; // send available characters to client var characters = Database.CharactersForAccount(message.account); var reply = new CharactersAvailableMsg { characterNames = characters.Keys.ToArray(), characterClasses = characters.Values.ToArray() }; netMsg.conn.Send(CharactersAvailableMsg.MsgId, reply); // addon system hooks Utils.InvokeMany(typeof(NetworkManagerMMO), this, "OnServerLogin_", message); } else { print("account already logged in: " + message.account); ClientSendPopup(netMsg.conn, "already logged in", true); // note: we should disconnect the client here, but we can't as // long as unity has no "SendAllAndThenDisconnect" function, // because then the error message would never be sent. //netMsg.conn.Disconnect(); } } else { print("invalid account or password for: " + message.account); ClientSendPopup(netMsg.conn, "invalid account", true); } } else { print("account invalid: " + message.account); ClientSendPopup(netMsg.conn, "forbidden account name", true); } } else { print("account too long: " + message.account); ClientSendPopup(netMsg.conn, "account too long", true); } } else { print("version mismatch: " + message.account + " expected:" + Application.version + " received: " + message.version); ClientSendPopup(netMsg.conn, "outdated version", true); } }
void OnServerCharacterCreate(NetworkMessage netMsg) { print("OnServerCharacterCreate " + netMsg.conn); var message = netMsg.ReadMessage <CharacterCreateMsg>(); // can only delete while in lobby (aka after handshake and not ingame) if (lobby.ContainsKey(netMsg.conn)) { // not too long? if (message.name.Length <= characterNameMaxLength) { // only contains letters, number and underscore and not empty (+)? // (important for database safety etc.) if (Regex.IsMatch(message.name, @"^[a-zA-Z0-9_]+$")) { // not existant yet? string account = lobby[netMsg.conn]; if (!Database.CharacterExists(message.name)) { // not too may characters created yet? if (Database.CharactersForAccount(account).Count < characterLimit) { // valid class index? var classes = GetPlayerClasses(); if (0 <= message.classIndex && message.classIndex < classes.Count) { // create new character based on the prefab // (instantiate temporary player) print("creating character: " + message.name + " " + message.classIndex); var prefab = GameObject.Instantiate(classes[message.classIndex]).GetComponent <Player>(); prefab.name = message.name; prefab.account = account; prefab.className = classes[message.classIndex].name; prefab.transform.position = GetStartPosition().position; prefab.health = prefab.healthMax; prefab.mana = prefab.manaMax; Database.CharacterSave(prefab); GameObject.Destroy(prefab.gameObject); // send available characters list again, causing // the client to switch to the character // selection scene again var chars = Database.CharactersForAccount(account); var reply = new CharactersAvailableMsg { characterNames = chars.Keys.ToArray(), characterClasses = chars.Values.ToArray() }; netMsg.conn.Send(CharactersAvailableMsg.MsgId, reply); } else { print("character invalid class: " + message.classIndex); ClientSendPopup(netMsg.conn, "character invalid class", false); } } else { print("character limit reached: " + message.name); ClientSendPopup(netMsg.conn, "character limit reached", false); } } else { print("character name already exists: " + message.name); ClientSendPopup(netMsg.conn, "name already exists", false); } } else { print("character name invalid: " + message.name); ClientSendPopup(netMsg.conn, "invalid name", false); } } else { print("character name too long: " + message.name); ClientSendPopup(netMsg.conn, "name too long", false); } } else { print("CharacterCreate: not in lobby"); ClientSendPopup(netMsg.conn, "CharacterCreate: not in lobby", true); } }
void OnClientCharactersAvailable(NetworkConnection conn, CharactersAvailableMsg message) { charactersAvailableMsg = message; print("characters available:" + charactersAvailableMsg.characters.Length); state = NetworkState.Lobby; }
void OnServerCharacterCreate(NetworkMessage netMsg) { print("OnServerCharacterCreate " + netMsg.conn); var msg = netMsg.ReadMessage <CharacterCreateMsg>(); // can only delete while in lobby (aka after handshake and not ingame) if (lobby.ContainsKey(netMsg.conn)) { // not too long? if (msg.name.Length <= charNameMaxLength) { // only contains letters, number and underscore and not empty (+)? // (important for database safety etc.) if (Regex.IsMatch(msg.name, @"^[a-zA-Z0-9_]+$")) { // not existant yet? string account = lobby[netMsg.conn]; if (!Database.CharacterExists(msg.name)) { // not too may characters created yet? if (Database.CharactersForAccount(account).Count < charLimit) { // valid class index? var classes = GetPlayerClasses(); if (0 <= msg.classIndex && msg.classIndex < classes.Count) { // create new character based on the prefab print("creating character: " + msg.name + " " + msg.classIndex); var prefab = classes[msg.classIndex].GetComponent <Player>(); Database.CharacterSave( msg.name, account, prefab.name, GetStartPosition().position, prefab.level, prefab.hpMax, prefab.mpMax, prefab.strength, prefab.intelligence, prefab.exp, prefab.skillExp, prefab.gold, prefab.inventory.ToList(), prefab.equipment.ToList(), prefab.skills.ToList(), prefab.quests.ToList() ); // send available characters list again, causing // the client to switch to the character // selection scene again var chars = Database.CharactersForAccount(account); var msgchars = new CharactersAvailableMsg { characterNames = chars.Keys.ToArray(), characterClasses = chars.Values.ToArray() }; netMsg.conn.Send(CharactersAvailableMsg.MsgId, msgchars); } else { print("character invalid class: " + msg.classIndex); ClientSendPopup(netMsg.conn, "character invalid class", false); } } else { print("character limit reached: " + msg.name); ClientSendPopup(netMsg.conn, "character limit reached", false); } } else { print("character name already exists: " + msg.name); ClientSendPopup(netMsg.conn, "name already exists", false); } } else { print("character name invalid: " + msg.name); ClientSendPopup(netMsg.conn, "invalid name", false); } } else { print("character name too long: " + msg.name); ClientSendPopup(netMsg.conn, "name too long", false); } } else { print("CharacterCreate: not in lobby"); ClientSendPopup(netMsg.conn, "CharacterCreate: not in lobby", true); } }
void OnClientCharactersAvailable_Example(CharactersAvailableMsg message) { }