/// <summary> /// Reads a number of bits from the buffer and inserts them to a new NetBuffer instance /// </summary> public static NetBuffer ExtractBits(this NetBuffer originalBuffer, int numberOfBits) { var buffer = new NetBuffer(); byte[] data = new byte[(int)Math.Ceiling(numberOfBits / (double)8)]; originalBuffer.ReadBits(data, 0, numberOfBits); buffer.Write(data); return(buffer); }
public void ServerWrite(NetBuffer msg, Client c, object[] extraData = null) { string errorMsg = ""; if (extraData == null || extraData.Length == 0 || !(extraData[0] is NetEntityEvent.Type)) { if (extraData == null) { errorMsg = "Failed to write a network event for the item \"" + Name + "\" - event data was null."; } else if (extraData.Length == 0) { errorMsg = "Failed to write a network event for the item \"" + Name + "\" - event data was empty."; } else { errorMsg = "Failed to write a network event for the item \"" + Name + "\" - event type not set."; } msg.WriteRangedInteger(0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1, (int)NetEntityEvent.Type.Invalid); DebugConsole.Log(errorMsg); GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:InvalidData" + Name, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); return; } int initialWritePos = msg.LengthBits; NetEntityEvent.Type eventType = (NetEntityEvent.Type)extraData[0]; msg.WriteRangedInteger(0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1, (int)eventType); switch (eventType) { case NetEntityEvent.Type.ComponentState: if (extraData.Length < 2 || !(extraData[1] is int)) { errorMsg = "Failed to write a component state event for the item \"" + Name + "\" - component index not given."; break; } int componentIndex = (int)extraData[1]; if (componentIndex < 0 || componentIndex >= components.Count) { errorMsg = "Failed to write a component state event for the item \"" + Name + "\" - component index out of range (" + componentIndex + ")."; break; } else if (!(components[componentIndex] is IServerSerializable)) { errorMsg = "Failed to write a component state event for the item \"" + Name + "\" - component \"" + components[componentIndex] + "\" is not server serializable."; break; } msg.WriteRangedInteger(0, components.Count - 1, componentIndex); (components[componentIndex] as IServerSerializable).ServerWrite(msg, c, extraData); break; case NetEntityEvent.Type.InventoryState: if (extraData.Length < 2 || !(extraData[1] is int)) { errorMsg = "Failed to write an inventory state event for the item \"" + Name + "\" - component index not given."; break; } int containerIndex = (int)extraData[1]; if (containerIndex < 0 || containerIndex >= components.Count) { errorMsg = "Failed to write an inventory state event for the item \"" + Name + "\" - container index out of range (" + containerIndex + ")."; break; } else if (!(components[containerIndex] is ItemContainer)) { errorMsg = "Failed to write an inventory state event for the item \"" + Name + "\" - component \"" + components[containerIndex] + "\" is not server serializable."; break; } msg.WriteRangedInteger(0, components.Count - 1, containerIndex); (components[containerIndex] as ItemContainer).Inventory.ServerWrite(msg, c); break; case NetEntityEvent.Type.Status: msg.Write(condition); break; case NetEntityEvent.Type.Treatment: { ItemComponent targetComponent = (ItemComponent)extraData[1]; ActionType actionType = (ActionType)extraData[2]; ushort targetID = (ushort)extraData[3]; Limb targetLimb = (Limb)extraData[4]; Character targetCharacter = FindEntityByID(targetID) as Character; byte targetLimbIndex = targetLimb != null && targetCharacter != null ? (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb) : (byte)255; msg.Write((byte)components.IndexOf(targetComponent)); msg.WriteRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1, (int)actionType); msg.Write(targetID); msg.Write(targetLimbIndex); } break; case NetEntityEvent.Type.ApplyStatusEffect: { ActionType actionType = (ActionType)extraData[1]; ItemComponent targetComponent = extraData.Length > 2 ? (ItemComponent)extraData[2] : null; ushort targetID = extraData.Length > 3 ? (ushort)extraData[3] : (ushort)0; Limb targetLimb = extraData.Length > 4 ? (Limb)extraData[4] : null; Character targetCharacter = FindEntityByID(targetID) as Character; byte targetLimbIndex = targetLimb != null && targetCharacter != null ? (byte)Array.IndexOf(targetCharacter.AnimController.Limbs, targetLimb) : (byte)255; msg.WriteRangedInteger(0, Enum.GetValues(typeof(ActionType)).Length - 1, (int)actionType); msg.Write((byte)(targetComponent == null ? 255 : components.IndexOf(targetComponent))); msg.Write(targetID); msg.Write(targetLimbIndex); } break; case NetEntityEvent.Type.ChangeProperty: try { WritePropertyChange(msg, extraData, false); } catch (Exception e) { errorMsg = "Failed to write a ChangeProperty network event for the item \"" + Name + "\" (" + e.Message + ")"; } break; default: errorMsg = "Failed to write a network event for the item \"" + Name + "\" - \"" + eventType + "\" is not a valid entity event type for items."; break; } if (!string.IsNullOrEmpty(errorMsg)) { //something went wrong - rewind the write position and write invalid event type to prevent creating an unreadable event msg.ReadBits(msg.Data, 0, initialWritePos); msg.LengthBits = initialWritePos; msg.WriteRangedInteger(0, Enum.GetValues(typeof(NetEntityEvent.Type)).Length - 1, (int)NetEntityEvent.Type.Invalid); DebugConsole.Log(errorMsg); GameAnalyticsManager.AddErrorEventOnce("Item.ServerWrite:" + errorMsg, GameAnalyticsSDK.Net.EGAErrorSeverity.Error, errorMsg); } }