示例#1
0
		/// <summary>
		/// <para>ID 0x0436</para>
		/// <para>Length 19</para>
		/// <para>First packet after selecting a character</para>
		/// </summary>
		public static void WantToConnect(NetState state, PacketReader reader) {
			int accountID = reader.ReadInt32();
			int charID = reader.ReadInt32();
			int loginID1 = reader.ReadInt32();
			int clientTick = reader.ReadInt32();
			byte iSex = reader.ReadByte();
			EAccountSex sex = (EAccountSex)iSex;

			state.Account = World.GetAccount(accountID);
			if (state.Account == null || state.Account.AccountState != EAccountState.Char) {
				state.Disconnect();
				return;
			}
			if (state.Account.LoginID1 != loginID1 || state.Account.Sex != sex) {
				state.Disconnect();
				return;
			}
			if (state.Account.ActiveChar == null || state.Account.ActiveChar.ID != charID) {
				state.Disconnect();
				return;
			}

			// Mark as authed
			state.Account.AccountState = EAccountState.World;
			state.Send(new Response.WorldAuthOK(state.Account));
		}
示例#2
0
		public static void AccountAuth(NetState state, PacketReader reader) {
			int accountID = reader.ReadInt32();
			int loginID1 = reader.ReadInt32();
			int loginID2 = reader.ReadInt32();
			int unknown = reader.ReadInt16(); // offset 14 - 16
			int iSex = reader.ReadByte();
			EAccountSex sex = (EAccountSex)iSex;

			state.Account = (Account)World.Objects[EDatabaseType.Account, accountID];
			state.Account.Netstate = state;
			if (
				state.Account == null ||
				state.Account.AccountState != EAccountState.Login ||
				state.Account.LoginID1 != loginID1 ||
				state.Account.LoginID2 != loginID2 ||
				state.Account.Sex != sex
			) {
				// Wrong data - hack attempt?
				state.Account = null;
				state.Send(new CharacterResponseError((byte)0));
				return;
			}

			// Mark as authed in character server
			state.Account.AccountState = EAccountState.Char;
			state.Account.LoadChars();

			// Auth successfull, send a special packet containing the AccountID
			state.Send(new CharacterResponseSuccess(state.Account));
			// Send character list
			state.Send(new CharacterResponseList(state.Account));
		}
示例#3
0
		/// <summary>
		/// <para>ID 0x007D</para>
		/// <para>Length 0</para>
		/// <para>Notification that the client ressource loading has completed</para>
		/// <para>
		/// No data given, but its the right place to load and send 
		/// everything else.
		/// </para>
		/// </summary>
		public static void LoadEndAck(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			// TODO:
			//		- check if variable loading and every other hist has been finished
			//		- check for rewarp (find out)
			//		- changelook calls
			//		- send inventory list
			//		- check items
			//		- if cart on, send cart-info and check items
			//		- send weights
			//		- if guild, send short guild info
			//		- check for invicible timer
			//		- clif_spawn() (.. what? Oo)
			//		- if party, send infos
			//		- check for pvp, gvg, duel, ...
			//		- getareacharinfo for nearby objects
			//		- pet, homunculus, mercanery
			//		- if first connection, send complete status
			//		- send friendlist info (friend logged in)
			//		- login npc events
			//		- if not first connect, refresh some infos
			//		- many many more..

		}
示例#4
0
		public static void CharacterCreation(NetState state, PacketReader reader) {
			if (state.Account == null || state.Account.AccountState != EAccountState.Char) {
				state.Disconnect();
				return;
			}

			string name = reader.ReadString(24);
			byte attrStr = reader.ReadByte();
			byte attrAgi = reader.ReadByte();
			byte attrVit = reader.ReadByte();
			byte attrInt = reader.ReadByte();
			byte attrDex = reader.ReadByte();
			byte attrLuk = reader.ReadByte();
			byte slot = reader.ReadByte();
			short hairColor = reader.ReadInt16();
			short hairStyle = reader.ReadInt16();

			Character newChar = null;
			ECharacterCreationResult result = Character.Create(state.Account, name, slot, attrStr, attrAgi, attrVit, attrInt, attrDex, attrLuk, hairColor, hairStyle, out newChar);
			if (result != ECharacterCreationResult.Success) {
				state.Send(new CharacterResponseCreation(result));
				return;
			}

			// Creation was successfull, send new characterlist
			state.Send(new CharacterResponseNewData(newChar));
		}
示例#5
0
		public static void KeepAlive(NetState state, PacketReader reader) {
			uint accountID = reader.ReadUInt32();
			if (state.Account == null || state.Account.AccountState != EAccountState.Char || accountID != state.Account.WorldID.ID) {
				state.Disconnect();
				return;
			}

			//state.UpdateAcitivty();
		}
示例#6
0
		/// Notification of the state of client command /effect (CZ_LESSEFFECT)
		/// 021D 6: <state>.L
		public static void LessEffect(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			// 0 = Full effects
			// 1 = Reduced effects
			int lessEffect = reader.ReadInt32();
		}
示例#7
0
		public static bool ValidateMessage(NetState state, string text, out string username, out string message) {
			// Delimiter for <username> and <message>
			// and yep, this means, the client sends us "Username : message" as one string
			// so we have to parse it..
			string delim = " : ";

			username = "";
			message = "";

			// TODO: i saw a topic in eA source request about fakename talking
			//		 he wanted to display the fakename in the chat
			//		 if implementing such a mod, we should check here for the fakename too!
			if (text.StartsWith(state.ActiveChar.Status.Name + delim) == false) {
				// This is just to check for a hacked packet
				// The message always has to start with <username><delimiter>, so its incorrect either @ this point
				if (text.StartsWith(state.ActiveChar.Status.Name) == false) {
					ServerConsole.DebugLine("Chatting.ValidateMessage: Player '{0}' sent a message using an incorrect name! Forcing a relog...", state.ActiveChar.Status.Name);
					state.Dispose();
				}
				return false;
			}

			// Split by delimiter
			string[] messageParts = text.Split(new string[] { delim }, StringSplitOptions.None);
			// Just in case..
			if (messageParts.Length != 2) {
				return false;
			}

			// TODO: couldnt trim here to not modify the message, but i should.. maybe.. or not? o.o
			username = messageParts[0];
			message = messageParts[1];

			// Remove |00
			if (message.StartsWith("|00") == true) {
				message = message.Substring(3);
			}

			// TODO: We didnt have max size for message as eAthena
			//		 but the client has (max display size is 254 + 1)
			//		 so.. ? o.o
			if (message.Length >= Global.CHAT_SIZE_MAX) {
				ServerConsole.WarningLine("Chatting.ValidateMessage: Message is to long! Max {0} length, msg has {1}: {2}", Global.CHAT_SIZE_MAX, message.Length, message);
				message = message.Substring(0, Global.CHAT_SIZE_MAX - 1);
			}

			return true;
		}
示例#8
0
		public static void CharacterSelect(NetState state, PacketReader reader) {
			short slot = reader.ReadByte();

			if (state.Account == null || state.Account.AccountState != EAccountState.Char) {
				state.Send(new CharacterResponseError((byte)0));
				state.Disconnect();
				return;
			}
			if (state.Account.HasSlot(slot) == false) {
				state.Send(new CharacterResponseError((byte)0));
				state.Disconnect();
				return;
			}

			Character selectedChar = state.Account.SetActiveChar(slot);
			state.Send(new CharacterResponseWorldLogin(selectedChar));
		}
示例#9
0
		public static void AccountLogin(NetState state, PacketReader reader) {
			int clientVersion = reader.ReadInt32();
			string loginName = reader.ReadString(24);
			string loginPassword = reader.ReadString(24);
			byte clientType = reader.ReadByte();

			Account acc;
			EAccountLoadResult result = Account.Load(state, loginName, loginPassword, out acc, false);
			if (result != EAccountLoadResult.Success) {
				state.Send(new Response.LoginResponseAccountError((byte)result));
				state.Disconnect();
				return;
			}

			acc.AccountState = EAccountState.Login;
			acc.UpdateLastLogin(state.Address.ToString());

			state.Send(new Response.LoginResponseServerList(acc));
		}
示例#10
0
		public virtual bool OnBeforeSend(NetState state) {
			// @TODO: delegates & events!
			// Return true to send
			return true;
		}
示例#11
0
		public static void SpawnOnce(NetState state, Location loc, string name, int mobID, int amount) {
			// TODO: calllback/event
			Character character = (state != null && state.Account != null && state.Account.ActiveChar != null ? state.Account.ActiveChar : null);
			int lv = (int)(character != null ? character.Status.LevelBase : 255);
			mobID = (mobID >= 0 ? mobID : GetRandomMobID(state.Account.ActiveChar, -mobID - 1, 3, lv));

			amount = Math.Min(amount, 1000);
			for (int i = 0; i < amount; i++) {
				Monster mob = SpawnOnceSub(character, loc, name, mobID);
				if (mob == null) {
					continue;
				}

				// TODO: check for emperium, add guardian & castle data
				mob.Spawn();

				// TODO: check for negative mobID (Dead branch) and mode changes
			}
		}
示例#12
0
		public static void WalkToXY(SerialObject obj, NetState state) {

			Timer.DelayCall(TimeSpan.FromMilliseconds(120), new TimerStateCallback<SerialObject>(WalkToXY_Tick), obj);

		}
示例#13
0
		public virtual void OnSend(NetState state, bool wasSend) {
			// Update internal state
			if ((mState & (EPacketState.Acquired | EPacketState.Static)) == 0) {
				Free();
			}
		}
示例#14
0
		/// 014f 6: <state>.L
		public static void GuildRequestInfo(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			Character c = state.Account.ActiveChar;
			// Nothing to send?
			if (!(c.GuildID is Serial)) {
				// TODO: or battleground ID
				return;
			}

			int requestType = reader.ReadInt32();
			switch (requestType) {
				case 0:
					//clif_guild_basicinfo(sd);
					//clif_guild_allianceinfo(sd);
					break;
				case 1:
					//clif_guild_positionnamelist(sd);
					//clif_guild_memberlist(sd);
					break;
				case 2:
					//clif_guild_positionnamelist(sd);
					//clif_guild_positioninfolist(sd);
					break;
				case 3:
					//clif_guild_skillinfo(sd);
					break;
				case 4:
					//clif_guild_expulsionlist(sd);
					break;
				default:
					ServerConsole.ErrorLine("GuildRequestInfo: Unknown request type {0}", requestType);
					break;
			}
		}
示例#15
0
		/// <summary>
		/// Try to load a specific account from the database
		/// </summary>
		/// <param name="state"></param>
		/// <param name="Name"></param>
		/// <param name="Password"></param>
		/// <param name="Acc"></param>
		/// <returns>EAccountLoadResult</returns>
		public static EAccountLoadResult Load(NetState state, string Name, string Password, out Account Acc, bool loadChars) {
			// Lookup on object manager
			if ((Acc = World.Objects.SearchAccount(Name)) != null) {
				if (loadChars == true) {
					Acc.LoadChars();
				}
				Acc.Netstate = state;
				return EAccountLoadResult.Success;
			}

			// Not found, load from Database
			Acc = new Account(true); // auto-push to world
			Acc.Netstate = state;
			DataTable table = Core.Database.Query("SELECT a.*, COUNT(*) AS charCount FROM account AS a LEFT JOIN `char` AS c ON c.accountID = a.accountID WHERE a.username = '******' LIMIT 0,1", Name.MysqlEscape());
			table.TableName = "Account Table";
			if (table.Rows.Count == 0) {
				return EAccountLoadResult.UnregisteredID;
			}

			DataRow accRow = table.Rows[0];

			// Password check
			if (accRow.Field<string>("password") != Password) {
				Acc = null;
				return EAccountLoadResult.IncorrectPassword;
			}
			Rovolution.Server.Database.RovolutionDatabase.PrintTableTypes(accRow.Table);
			// Enfore a serial value equal to the account ID
			// Assumes our Account creation script wont take a same ID twice
			Acc.WorldID = new WorldID(accRow.Field<uint>("accountID"), EDatabaseType.Account);
			Acc.Name = accRow.Field<string>("username");
			Acc.Password = accRow.Field<string>("password");
			Acc.Sex = (accRow.Field<string>("sex").ToLower() == "m" ? EAccountSex.Male : EAccountSex.Female);
			Acc.Email = accRow.Field<string>("email");
			Acc.GMLevel = accRow.FieldNull<sbyte>("gmLevel");
			Acc.LastIP = accRow.Field<string>("lastIP");
			Acc.LastLogin = accRow.FieldDateTime("lastLogin");
			Acc.LoginID1 = mLoginRandomizer.Next() + 1;
			Acc.LoginID2 = mLoginRandomizer.Next() + 1;
			// `accountState`, `unbanTime`, `expirationTime`, `loginCount`, `birthDate`
			if (loadChars == true) {
				Acc.LoadChars();
			}

			return EAccountLoadResult.Success;
		}
示例#16
0
		public static void Execute(NetState state, string name) {
		}
示例#17
0
		public bool HandleReceive(NetState ns) {
			if (ns == null || ns.Running == false) {
				return false;
			}
			ByteQueue buffer = ns.Buffer;

			if (buffer == null || buffer.Length <= 0)
				return true;

			ServerConsole.DebugLine("{0}: Incoming data, {1} bytes", ns, buffer.Length);

			/*
			 * Packet Analyse/verify && Parsing
			 */

			lock (buffer) {
				int turns = 0;
				int length = buffer.Length;
				while (length > 0 && ns != null && ns.Running) {
					short packetID = buffer.GetPacketID();

#if DEBUG_PACKETS
					// debug log
					using (TextWriter writer = File.CreateText(AppDomain.CurrentDomain.BaseDirectory + @"\packet_" + DateTime.Now.UnixTimestamp() + ".log")) {
						using (MemoryStream ms = new MemoryStream(buffer.ByteBuffer))
							Tools.FormatBuffer(writer, ms, (int)ms.Length);
					}
#endif

					PacketHandler handler = PacketHandlers.GetHandler(packetID);
					if (handler == null) {
						byte[] data = new byte[length];
						length = buffer.Dequeue(data, 0, length);

						// Log unknown packets
						string unknownPacketPath = AppDomain.CurrentDomain.BaseDirectory + @"\packet_" + packetID.ToString("X4") + ".log";
						if (File.Exists(unknownPacketPath) == false) {
							using (TextWriter writer = File.CreateText(unknownPacketPath)) {
								writer.WriteLine("Unknown packet 0x" + packetID.ToString("X4") + ", length " + length);
								using (MemoryStream ms = new MemoryStream(data)) {
									Tools.FormatBuffer(writer, ms, (int)ms.Length);
								}
							}
						}

						ServerConsole.WarningLine("{0}: P {1:X4}, {2} bytes, no Handler found!", ns, packetID, length);
						break;
					}

					ServerConsole.StatusLine("{0}: [{1}] P {2:X4}, {3} bytes, handled {4}", ns, handler.Name, packetID, length, handler.Length);

					byte[] packetBuffer;
					// If we set the length to -1 (dynamic packet length), read the full buffer
					int bufferLength = (handler.Length > 0 ? handler.Length : length);
					if (bufferLength < mBufferSize)
						packetBuffer = mBuffers.AcquireBuffer();
					else
						packetBuffer = new byte[bufferLength];

					buffer.Dequeue(packetBuffer, 0, bufferLength);

					PacketReader r = new PacketReader(packetBuffer, bufferLength, 0, true);
					handler.OnReceive(ns, r);
					length -= bufferLength;

					if (bufferLength < mBufferSize) {
						mBuffers.ReleaseBuffer(packetBuffer);
					} else {
						packetBuffer = null;
					}

					turns++;
				} // end while()*/

			} // end Lock()

			// Clear internal byte buffer for receive data
			if (ns != null && ns.Buffer != null) {
				ns.Buffer.Clear();
			}

			return true;
		}
示例#18
0
		public virtual void OnSend(NetState state) {
			// Assume data was send
			OnSend(state, true);
		}
示例#19
0
		/// <summary>
		/// an Empty/Unused/not yet available Packet Handler
		/// </summary>
		/// <param name="state"></param>
		/// <param name="reader"></param>
		public static void EmptyHandler(NetState state, PacketReader reader) {
		}
示例#20
0
		/// Request servert ticks
		/// 0089 11: <clientTicks>.L
		public static void TickSend(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			// TODO: has a length of 11..
			// state.Account.ClientTick = reader.ReadInt32();
			// TODO: send server ticks
		}
示例#21
0
		/// Validates and processes global messages
		/// 008C/00F3 -1: <packet len>.W <text>.?B (<name> : <message>) 00
		public static void GlobalMessage(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			short textLen = (short)(reader.ReadInt16() - 4);
			string text = reader.ReadString(textLen);

			// TODO:
			//		- check name/message
			//		- check atcommand
			//		- process message to all in range (9 cells)
			//		- trigger listening npc's
			//		- log chat
		}
示例#22
0
		/// Requesting unit's name
		/// 0094 6: <object id>.L
		public static void CharNameRequest(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			int id = reader.ReadInt32();
			// Disguises using -ID..
			if (id < 0 && -id == state.Account.ID) {
				id = (int)state.Account.ID;
			}

			SerialObject obj = World.GetObject(id);
			if (obj == null) {
				// Lagged clients could request names of already gone mobs/players..
				// so no disconnect on invalid requests..
				//state.Disconnect();
				return;
			}

			if (obj.Location.Map != state.Account.ActiveChar.Location.Map) {
				// || !check_distance_bl(&sd->bl, bl, AREA_SIZE)
				return; // Block namerequests past view range
			}

			// 'see people in GM hide' cheat detection
			/* disabled due to false positives (network lag + request name of char that's about to hide = race condition)
			sc = status_get_sc(bl);
			if (sc && sc->option&OPTION_INVISIBLE && !disguised(bl) &&
				bl->type != BL_NPC && //Skip hidden NPCs which can be seen using Maya Purple
				pc_isGM(sd) < battle_config.hack_info_GM_level
			) {
				char gm_msg[256];
				sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requested the name of an invisible target (id: %d).\n", sd->status.name, sd->status.account_id, id);
				ShowWarning(gm_msg);
				// information is sent to all online GMs
				intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, gm_msg);
				return;
			}
			*/

			// TODO: implement me :o
			//clif_charnameack(fd, bl);
		}
示例#23
0
		/// Request for game exiting
		/// 018A 4: <dont_know>.W
		public static void QuitGame(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			// TODO: logout check
			state.Send(new Response.WorldConfirmGameExit(true));
		}
示例#24
0
		public void OnReceive(NetState ns) {
			lock (this)
				mQueue.Enqueue(ns);

			Core.Set();
		}
示例#25
0
		/// Request to walk
		/// 0x00A7 9: 
		public static void WalkToXY(NetState state, PacketReader reader) {
			if (state.IsValid(EAccountState.World) == false) {
				state.Disconnect();
				return;
			}

			Character c = state.Account.ActiveChar;

			int unkInt = reader.ReadInt32();
			// Since 2008-08-27aRagexeRE, X/Y starts at pos 6
			byte b1 = reader.ReadByte();
			byte b2 = reader.ReadByte();
			byte b3 = reader.ReadByte();
			int x = b1 * 4 + (b2 >> 6);
			int y = ((b2 & 0x3f) << 4) + (b3 >> 4);
			Point2D targetLoc = new Point2D(x, y);
			c.TargetLocation = c.Location.Point + (c.Location.Point - targetLoc);
		}
示例#26
0
		/// <summary>
		/// Checks for new connections
		/// </summary>
		private void CheckListener() {
			Socket[] accepted = mListener.Slice();

			for (int i = 0; i < accepted.Length; ++i) {
				NetState ns = new NetState(accepted[i], this);
				ns.Start();

				if (ns.Running) {
					ServerConsole.StatusLine("{0}: Connected. [{1} Online]", ns, NetState.Instances.Count);
				}
			}
		}
示例#27
0
		/// <summary>
		/// Try to load a specific account from the database, including all characters
		/// </summary>
		/// <param name="State"></param>
		/// <param name="Name"></param>
		/// <param name="Password"></param>
		/// <param name="Acc"></param>
		/// <returns>EAccountLoadResult</returns>
		public static EAccountLoadResult Load(NetState State, string Name, string Password, out Account Acc) {
			return Load(State, Name, Password, out Acc, true);
		}