From 173a62928bb007e46c6b10f7dd18cd3b02817b0b Mon Sep 17 00:00:00 2001 From: Ragnok123 <=> Date: Mon, 27 Aug 2018 20:45:16 +0200 Subject: [PATCH 1/3] Scoreboards Basic scoreboards --- src/MiNET/MiNET.Client/MiNetClient.cs | 68 +- src/MiNET/MiNET.Test.Console/packages.config | 5 + src/MiNET/MiNET/Entities/Entity.cs | 11 +- src/MiNET/MiNET/LoginMessageHandler.cs | 49 +- .../MiNET/Net/MCPE Protocol Documentation.md | 8 +- src/MiNET/MiNET/Net/MCPE Protocol.cs | 155 +++-- src/MiNET/MiNET/Net/MCPE Protocol.xml | 15 +- src/MiNET/MiNET/Net/McpeAvailableCommands.cs | 18 +- src/MiNET/MiNET/Net/McpeText.cs | 4 - src/MiNET/MiNET/Net/Packet.cs | 92 ++- src/MiNET/MiNET/Player.cs | 115 +++- src/MiNET/MiNET/PlayerNetworkSession.cs | 6 +- src/MiNET/MiNET/Scoreboards/Score.cs | 47 ++ src/MiNET/MiNET/Scoreboards/Scoreboard.cs | 52 ++ .../MiNET/Scoreboards/ScoreboardCriteria.cs | 11 + .../Scoreboards/ScoreboardDisplaySlot.cs | 15 + .../MiNET/Scoreboards/ScoreboardObjective.cs | 89 +++ src/MiNET/MiNET/Utils/CryptoUtils.cs | 30 +- src/MiNET/MiNET/Utils/ScorePacketInfo.cs | 7 +- .../MiNET/Utils/ScoreboardIdentityPacket.cs | 20 + .../TestPlugin/NiceLobby/NiceLobbyPlugin.cs | 620 +++++++++--------- 21 files changed, 1060 insertions(+), 377 deletions(-) create mode 100644 src/MiNET/MiNET.Test.Console/packages.config create mode 100644 src/MiNET/MiNET/Scoreboards/Score.cs create mode 100644 src/MiNET/MiNET/Scoreboards/Scoreboard.cs create mode 100644 src/MiNET/MiNET/Scoreboards/ScoreboardCriteria.cs create mode 100644 src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs create mode 100644 src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs create mode 100644 src/MiNET/MiNET/Utils/ScoreboardIdentityPacket.cs diff --git a/src/MiNET/MiNET.Client/MiNetClient.cs b/src/MiNET/MiNET.Client/MiNetClient.cs index 834330578..d7d095d91 100644 --- a/src/MiNET/MiNET.Client/MiNetClient.cs +++ b/src/MiNET/MiNET.Client/MiNetClient.cs @@ -123,11 +123,11 @@ private static void Main(string[] args) int threads; int iothreads; ThreadPool.GetMinThreads(out threads, out iothreads); + var client = new MiNetClient(new IPEndPoint(IPAddress.Parse("10.0.0.6"), 19132), "RagnokBot", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); + //var client = new MiNetClient(new IPEndPoint(Dns.GetHostEntry("yodamine.com").AddressList[0], 19132), "TheGrey", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); + //var client = new MiNetClient(new IPEndPoint(IPAddress.Loopback, 19132), "TheGrey", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); - var client = new MiNetClient(new IPEndPoint(Dns.GetHostEntry("yodamine.com").AddressList[0], 19132), "TheGrey", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); - //var client = new MiNetClient(new IPEndPoint(IPAddress.Loopback, 19132), "TheGrey", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); - - client.StartClient(); + client.StartClient(); Log.Warn("Client listening for connecting on: " + client._clientEndpoint); Console.WriteLine("Server started."); @@ -613,19 +613,16 @@ private void HandleConnectedPacket(ConnectedPacket packet) public void AddToProcessing(Packet message) { - if (Session.CryptoContext == null || Session.CryptoContext.UseEncryption == false || message.Reliability != Reliability.ReliableOrdered) + if (message.Reliability != Reliability.ReliableOrdered) { HandlePacket(message); return; } - //Log.Error("DO NOT USE THIS"); //throw new Exception("DO NOT USE THIS"); lock (_eventSync) { - if (_lastSequenceNumber < 0) _lastSequenceNumber = 1; - if (_queue.Count == 0 && message.OrderingIndex == _lastSequenceNumber + 1) { _lastSequenceNumber = message.OrderingIndex; @@ -1123,10 +1120,27 @@ private void HandlePacket(Packet message) else if (typeof (McpeUpdateEquipment) == message.GetType()) { OnMcpeUpdateEquipment((McpeUpdateEquipment) message); - - return; + } + else if (typeof(McpeSetDisplayObjective) == message.GetType()) + { + OnMcpeSetDisplayObjective((McpeSetDisplayObjective)message); + return; + } + + else if (typeof(McpeSetScoreboardIdentity) == message.GetType()) + { + OnMcpeSetScoreboardIdentity((McpeSetScoreboardIdentity)message); + return; + } + + else if(typeof (McpeSetScore) == message.GetType()) + { + OnMcpeSetScore((McpeSetScore)message); + return; + } + else if (typeof (UnknownPacket) == message.GetType()) { @@ -1140,6 +1154,38 @@ private void HandlePacket(Packet message) } } + private void OnMcpeSetDisplayObjective(McpeSetDisplayObjective message) + { + Log.Warn($"Criterium {message.criteriaName}"); + Log.Warn($"DisplayName {message.displayName}"); + Log.Warn($"Slot {message.displaySlot}"); + Log.Warn($"Obj {message.objectiveName}"); + Log.Warn($"Sort {message.sortOrder}"); + } + + private void OnMcpeSetScoreboardIdentity(McpeSetScoreboardIdentity message) + { + Log.Warn($"Type {message.type}"); + foreach (var id in message.scoreboardIdentityPackets) + { + Log.Warn($"ScoreboardId {id.ScoreboardId}"); + Log.Warn($"EntityId {id.EntityId}"); + } + } + + private void OnMcpeSetScore(McpeSetScore message) + { + Log.Warn($"Type {message.type}"); + foreach(var scores in message.scorePacketInfos) + { + Log.Warn($"Id {scores.scoreboardId}"); + Log.Warn($"Obj {scores.objectiveName}"); + Log.Warn($"Score {scores.score}"); + Log.Warn($"IdentityType {scores.addType}"); + Log.Warn($"FakeName {scores.fakePlayer}"); + } + } + private void OnMcpeInventoryTransaction(McpeInventoryTransaction message) { } @@ -1427,7 +1473,7 @@ private void OnMcpeServerToClientHandshake(McpeServerToClientHandshake message) string x5u = headers["x5u"]; ECPublicKeyParameters remotePublicKey = (ECPublicKeyParameters) - PublicKeyFactory.CreateKey(x5u.DecodeBase64Url()); + PublicKeyFactory.CreateKey(x5u.DecodeBase64()); var signParam = new ECParameters diff --git a/src/MiNET/MiNET.Test.Console/packages.config b/src/MiNET/MiNET.Test.Console/packages.config new file mode 100644 index 000000000..eec72af58 --- /dev/null +++ b/src/MiNET/MiNET.Test.Console/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/src/MiNET/MiNET/Entities/Entity.cs b/src/MiNET/MiNET/Entities/Entity.cs index 55c8e9a22..afbbb8f4a 100644 --- a/src/MiNET/MiNET/Entities/Entity.cs +++ b/src/MiNET/MiNET/Entities/Entity.cs @@ -347,6 +347,7 @@ public enum DataFlags Charged, Tamed, + Orphaned, Leashed, Sheared, FlagAllFlying, @@ -369,7 +370,15 @@ public enum DataFlags AffectedByGravity, FireImmune, Dancing, - Enchanted + Enchanted, + + ShowTridentRope, + ContainerPrivate, + SpinAttack = 55, + Swimming = 56, + Bribed = 57, + Pregnant = 58, + LayingEgg = 59 } protected virtual BitArray GetFlags() diff --git a/src/MiNET/MiNET/LoginMessageHandler.cs b/src/MiNET/MiNET/LoginMessageHandler.cs index 323da87ac..ac8470167 100644 --- a/src/MiNET/MiNET/LoginMessageHandler.cs +++ b/src/MiNET/MiNET/LoginMessageHandler.cs @@ -173,7 +173,6 @@ public void DecodeCert(McpeLogin message) _playerInfo.PlatformChatId = payload.PlatformChatId; _playerInfo.ServerAddress = payload.ServerAddress; _playerInfo.UIProfile = payload.UIProfile; - _playerInfo.ThirdPartyName = payload.ThirdPartyName; _playerInfo.TenantId = payload.TenantId; _playerInfo.Skin = new Skin() @@ -361,9 +360,9 @@ public void DecodeCert(McpeLogin message) { X = pubAsyKey.Q.AffineXCoord.GetEncoded(), Y = pubAsyKey.Q.AffineYCoord.GetEncoded() - }, - D = privAsyKey.D.ToByteArrayUnsigned() + } }; + signParam.D = CryptoUtils.FixDSize(privAsyKey.D.ToByteArrayUnsigned(), signParam.Q.X.Length); signParam.Validate(); string signedToken = null; @@ -600,10 +599,46 @@ public void HandleMcpeLabTable(McpeLabTable messae) } - public void HandleMcpeSetLocalPlayerAsInitializedPacket(McpeSetLocalPlayerAsInitializedPacket message) - { - } - } + public void HandleMcpeSetLocalPlayerAsInitializedPacket(McpeSetLocalPlayerAsInitialized message) + { + + } + + public void HandleSetScoreboardIdentity(McpeSetScoreboardIdentity message) + { + + } + + public void HandleUpdateEnumSoft(McpeUpdateSoftEnum message) + { + + } + + public void HandleNetworkStackLatency(McpeNetworkStackLatency message) + { + + } + + public void HandleScriptCustomEvent(McpeScriptCustomEvent message) + { + + } + + public void HandleMcpeRemoveObjective(McpeRemoveObjective mesage) + { + + } + + public void HandleMcpeSetDisplayObjective(McpeSetDisplayObjective message) + { + + } + + public void HandleMcpeSetScore(McpeSetScore message) + { + + } + } public interface IServerManager { diff --git a/src/MiNET/MiNET/Net/MCPE Protocol Documentation.md b/src/MiNET/MiNET/Net/MCPE Protocol Documentation.md index 36c0edab8..d5b756eef 100644 --- a/src/MiNET/MiNET/Net/MCPE Protocol Documentation.md +++ b/src/MiNET/MiNET/Net/MCPE Protocol Documentation.md @@ -128,6 +128,7 @@ Read more about packets and this specification on the [Protocol Wiki](https://gi | Data type | |:--- | | BlockCoordinates [(wiki)](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-Type-BlockCoordinates) | +| Blockstates [(wiki)](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-Type-Blockstates) | | bool [(wiki)](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-Type-bool) | | byte [(wiki)](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-Type-byte) | | byte[] [(wiki)](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-Type-byte[]) | @@ -427,6 +428,8 @@ Wiki: [Start Game](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-StartG |Is Trial | bool | | |Current Tick | long | | |Enchantment Seed | SignedVarInt | | +|Blockstates | Blockstates | | +|Multiplayer Correlation ID | string | | ----------------------------------------------------------------------- ### Add Player (0x0c) Wiki: [Add Player](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-AddPlayer) @@ -466,6 +469,7 @@ Wiki: [Add Player](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-AddPla |Custom stored permissions | UnsignedVarInt | | |User Id | long | | |Links | Links | | +|Device ID | string | | ----------------------------------------------------------------------- ### Add Entity (0x0d) Wiki: [Add Entity](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-AddEntity) @@ -503,6 +507,7 @@ val2 float |Speed Z | float | | |Pitch | float | | |Yaw | float | | +|Head Yaw | float | | |Attributes | EntityAttributes | | |Metadata | MetadataDictionary | | |Links | Links | | @@ -577,9 +582,8 @@ Wiki: [Move Entity](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-MoveE | Name | Type | Size | |:-----|:-----|:-----| |Runtime Entity ID | UnsignedVarLong | | +|Flags | byte | | |Position | PlayerLocation | | -|On Ground | bool | | -|Teleport | bool | | ----------------------------------------------------------------------- ### Move Player (0x13) Wiki: [Move Player](https://github.com/NiclasOlofsson/MiNET/wiki//Protocol-MovePlayer) diff --git a/src/MiNET/MiNET/Net/MCPE Protocol.cs b/src/MiNET/MiNET/Net/MCPE Protocol.cs index 444edc064..a0e1cc222 100644 --- a/src/MiNET/MiNET/Net/MCPE Protocol.cs +++ b/src/MiNET/MiNET/Net/MCPE Protocol.cs @@ -31,6 +31,7 @@ using System.Net; using System.Numerics; using System.Threading; +using System.Collections.Generic; using MiNET.Utils; using MiNET.Utils.Skins; using MiNET.Items; @@ -42,8 +43,8 @@ namespace MiNET.Net { public class McpeProtocolInfo { - public const int ProtocolVersion = 281; - public const string GameVersion = "1.6.0.5"; + public const int ProtocolVersion = 290; + public const string GameVersion = "1.7.0.2"; } public interface IMcpeMessageHandler @@ -92,8 +93,15 @@ public interface IMcpeMessageHandler void HandleMcpePhotoTransfer(McpePhotoTransfer message); void HandleMcpeModalFormResponse(McpeModalFormResponse message); void HandleMcpeServerSettingsRequest(McpeServerSettingsRequest message); + void HandleMcpeRemoveObjective(McpeRemoveObjective mesage); + void HandleMcpeSetDisplayObjective(McpeSetDisplayObjective message); + void HandleMcpeSetScore(McpeSetScore message); void HandleMcpeLabTable(McpeLabTable message); - void HandleMcpeSetLocalPlayerAsInitializedPacket(McpeSetLocalPlayerAsInitializedPacket message); + void HandleMcpeSetLocalPlayerAsInitializedPacket(McpeSetLocalPlayerAsInitialized message); + void HandleSetScoreboardIdentity(McpeSetScoreboardIdentity message); + void HandleUpdateEnumSoft(McpeUpdateSoftEnum message); + void HandleNetworkStackLatency(McpeNetworkStackLatency message); + void HandleScriptCustomEvent(McpeScriptCustomEvent message); } public class PacketFactory @@ -628,21 +636,25 @@ public static Packet Create(byte messageId, byte[] buffer, string ns) packet.Decode(buffer); return packet; case 0x70: - packet = McpeSetScoreboardIdentityPacket.CreateObject(); + packet = McpeSetScoreboardIdentity.CreateObject(); packet.Decode(buffer); return packet; case 0x71: - packet = McpeSetLocalPlayerAsInitializedPacket.CreateObject(); + packet = McpeSetLocalPlayerAsInitialized.CreateObject(); packet.Decode(buffer); return packet; case 0x72: - packet = McpeUpdateSoftEnumPacket.CreateObject(); + packet = McpeUpdateSoftEnum.CreateObject(); packet.Decode(buffer); return packet; case 0x73: - packet = McpeNetworkStackLatencyPacket.CreateObject(); + packet = McpeNetworkStackLatency.CreateObject(); packet.Decode(buffer); return packet; + case 0x75: + packet = McpeScriptCustomEvent.CreateObject(); + packet.Decode(buffer); + return packet; } } @@ -2130,6 +2142,8 @@ public partial class McpeStartGame : Packet public long currentTick; // = null; public int enchantmentSeed; // = null; public Blockstates blockstates; // = null; + public string multiplayerCorrelationId; // = null; + public bool useMsaGamertagsOnly; // = null; public McpeStartGame() { @@ -2180,6 +2194,7 @@ protected override void EncodePacket() Write(hasLockedBehaviorPack); Write(hasLockedResourcePack); Write(isFromLockedWorldTemplate); + Write(useMsaGamertagsOnly); Write(levelId); Write(worldName); Write(premiumWorldTemplateId); @@ -2187,6 +2202,7 @@ protected override void EncodePacket() Write(currentTick); WriteSignedVarInt(enchantmentSeed); Write(blockstates); + Write(multiplayerCorrelationId); AfterEncode(); } @@ -2237,6 +2253,7 @@ protected override void DecodePacket() hasLockedBehaviorPack = ReadBool(); hasLockedResourcePack = ReadBool(); isFromLockedWorldTemplate = ReadBool(); + useMsaGamertagsOnly = ReadBool(); levelId = ReadString(); worldName = ReadString(); premiumWorldTemplateId = ReadString(); @@ -2244,6 +2261,7 @@ protected override void DecodePacket() currentTick = ReadLong(); enchantmentSeed = ReadSignedVarInt(); blockstates = ReadBlockstates(); + multiplayerCorrelationId = ReadString(); AfterDecode(); } @@ -2299,6 +2317,7 @@ protected override void ResetPacket() currentTick=default(long); enchantmentSeed=default(int); blockstates=default(Blockstates); + multiplayerCorrelationId=default(string); } } @@ -2331,6 +2350,7 @@ public partial class McpeAddPlayer : Packet public uint customStoredPermissions; // = null; public long userId; // = null; public Links links; // = null; + public string deviceId; // = null; public McpeAddPlayer() { @@ -2369,6 +2389,7 @@ protected override void EncodePacket() WriteUnsignedVarInt(customStoredPermissions); Write(userId); Write(links); + Write(deviceId); AfterEncode(); } @@ -2407,6 +2428,7 @@ protected override void DecodePacket() customStoredPermissions = ReadUnsignedVarInt(); userId = ReadLong(); links = ReadLinks(); + deviceId = ReadString(); AfterDecode(); } @@ -2443,6 +2465,7 @@ protected override void ResetPacket() customStoredPermissions=default(uint); userId=default(long); links=default(Links); + deviceId=default(string); } } @@ -2743,7 +2766,7 @@ public partial class McpeMoveEntity : Packet { public long runtimeEntityId; // = null; - public short flags; // = null; + public byte flags; // = null; public PlayerLocation position; // = null; public McpeMoveEntity() @@ -2775,7 +2798,7 @@ protected override void DecodePacket() BeforeDecode(); runtimeEntityId = ReadUnsignedVarLong(); - flags = ReadShort(); + flags = ReadByte(); position = ReadPlayerLocation(); AfterDecode(); @@ -2789,7 +2812,7 @@ protected override void ResetPacket() base.ResetPacket(); runtimeEntityId=default(long); - flags=default(short); + flags=default(byte); position=default(PlayerLocation); } @@ -7690,7 +7713,7 @@ protected override void EncodePacket() Write(objectiveName); Write(displayName); Write(criteriaName); - WriteVarInt(sortOrder); + WriteSignedVarInt(sortOrder); AfterEncode(); } @@ -7708,7 +7731,7 @@ protected override void DecodePacket() objectiveName = ReadString(); displayName = ReadString(); criteriaName = ReadString(); - sortOrder = ReadVarInt(); + sortOrder = ReadSignedVarInt(); AfterDecode(); } @@ -7734,7 +7757,7 @@ public partial class McpeSetScore : Packet public enum Types { ModifyScore = 0, - ResetScore = 1, + RemoveScore = 1, } public byte type; // = null; @@ -7970,11 +7993,18 @@ protected override void ResetPacket() } - public partial class McpeSetScoreboardIdentityPacket : Packet + public partial class McpeSetScoreboardIdentity : Packet { + public enum Types + { + RegisterIdentity = 0, + ClearIdentity = 1 + } + public byte type; // = null; + public ScoreboardIdentityPackets scoreboardIdentityPackets; // = null; - public McpeSetScoreboardIdentityPacket() + public McpeSetScoreboardIdentity() { Id = 0x70; IsMcpe = true; @@ -7985,8 +8015,8 @@ protected override void EncodePacket() base.EncodePacket(); BeforeEncode(); - - + Write(type); + Write(scoreboardIdentityPackets, type); AfterEncode(); } @@ -7998,8 +8028,8 @@ protected override void DecodePacket() base.DecodePacket(); BeforeDecode(); - - + type = ReadByte(); + scoreboardIdentityPackets = ReadScoreboardIdentityPackets(type); AfterDecode(); } @@ -8009,16 +8039,18 @@ protected override void DecodePacket() protected override void ResetPacket() { base.ResetPacket(); - + type = default(byte); + scoreboardIdentityPackets = default(ScoreboardIdentityPackets); } } - public partial class McpeSetLocalPlayerAsInitializedPacket : Packet + public partial class McpeSetLocalPlayerAsInitialized : Packet { + public long runtimeEntityId; // = null; - public McpeSetLocalPlayerAsInitializedPacket() + public McpeSetLocalPlayerAsInitialized() { Id = 0x71; IsMcpe = true; @@ -8029,7 +8061,7 @@ protected override void EncodePacket() base.EncodePacket(); BeforeEncode(); - + WriteUnsignedVarLong(runtimeEntityId); AfterEncode(); } @@ -8042,7 +8074,7 @@ protected override void DecodePacket() base.DecodePacket(); BeforeDecode(); - + runtimeEntityId = ReadUnsignedVarLong(); AfterDecode(); } @@ -8053,16 +8085,20 @@ protected override void DecodePacket() protected override void ResetPacket() { base.ResetPacket(); - + runtimeEntityId = default(long); } } - public partial class McpeUpdateSoftEnumPacket : Packet - { + public class EnumValues : List { } + public partial class McpeUpdateSoftEnum : Packet + { + public string enumName; // = null; + public EnumValues values; // = null; + public byte type; // = null; - public McpeUpdateSoftEnumPacket() + public McpeUpdateSoftEnum() { Id = 0x72; IsMcpe = true; @@ -8073,7 +8109,9 @@ protected override void EncodePacket() base.EncodePacket(); BeforeEncode(); - + Write(enumName); + Write(values); + Write(type); AfterEncode(); } @@ -8086,8 +8124,9 @@ protected override void DecodePacket() base.DecodePacket(); BeforeDecode(); - - + enumName = ReadString(); + values = ReadEnumValues(); + type = ReadByte(); AfterDecode(); } @@ -8097,16 +8136,19 @@ protected override void DecodePacket() protected override void ResetPacket() { base.ResetPacket(); - + enumName = default(string); + values = default(EnumValues); + type = default(byte); } } - public partial class McpeNetworkStackLatencyPacket : Packet + public partial class McpeNetworkStackLatency : Packet { + public ulong timestamp; - public McpeNetworkStackLatencyPacket() + public McpeNetworkStackLatency() { Id = 0x73; IsMcpe = true; @@ -8117,7 +8159,7 @@ protected override void EncodePacket() base.EncodePacket(); BeforeEncode(); - + Write(timestamp); AfterEncode(); } @@ -8130,7 +8172,7 @@ protected override void DecodePacket() base.DecodePacket(); BeforeDecode(); - + timestamp = ReadUlong(); AfterDecode(); } @@ -8141,11 +8183,50 @@ protected override void DecodePacket() protected override void ResetPacket() { base.ResetPacket(); - + timestamp = default(ulong); } } + public partial class McpeScriptCustomEvent : Packet + { + public McpeScriptCustomEvent() + { + Id = 0x75; + IsMcpe = true; + } + + protected override void EncodePacket() + { + base.EncodePacket(); + + BeforeEncode(); + + AfterEncode(); + } + + partial void BeforeEncode(); + partial void AfterEncode(); + + protected override void DecodePacket() + { + base.DecodePacket(); + + BeforeDecode(); + + AfterDecode(); + } + + partial void BeforeDecode(); + partial void AfterDecode(); + + protected override void ResetPacket() + { + base.ResetPacket(); + } + + } + public partial class McpeWrapper : Packet { diff --git a/src/MiNET/MiNET/Net/MCPE Protocol.xml b/src/MiNET/MiNET/Net/MCPE Protocol.xml index e44959e5b..a243ab9cd 100644 --- a/src/MiNET/MiNET/Net/MCPE Protocol.xml +++ b/src/MiNET/MiNET/Net/MCPE Protocol.xml @@ -1,6 +1,6 @@  - + @@ -241,6 +241,7 @@ + @@ -270,6 +271,7 @@ + @@ -329,7 +331,7 @@ - + @@ -1010,16 +1012,23 @@ + + + + + + - + + diff --git a/src/MiNET/MiNET/Net/McpeAvailableCommands.cs b/src/MiNET/MiNET/Net/McpeAvailableCommands.cs index 9c54123d6..7f083aa7b 100644 --- a/src/MiNET/MiNET/Net/McpeAvailableCommands.cs +++ b/src/MiNET/MiNET/Net/McpeAvailableCommands.cs @@ -53,6 +53,7 @@ partial void AfterDecode() enumValues.Add(s); } } + int enumValuesCount = enumValues.Count(); { uint count = ReadUnsignedVarInt(); @@ -92,7 +93,19 @@ partial void AfterDecode() Log.Debug($"{s}:{c}"); for (int j = 0; j < c; j++) { - int idx = ReadShort(); + int idx; + if (enumValuesCount <= byte.MaxValue) + { + idx = ReadByte(); + } + else if (enumValuesCount <= short.MaxValue) + { + idx = ReadShort(); + } + else + { + idx = ReadInt(); + } Log.Debug($"{s}:{c}:{idx}"); string enumValue = enumValues[idx]; @@ -190,6 +203,7 @@ partial void AfterEncode() WriteUnsignedVarInt(0); WriteUnsignedVarInt(0); WriteUnsignedVarInt(0); + WriteUnsignedVarInt(0); return; } @@ -403,6 +417,8 @@ partial void AfterEncode() } } } + + WriteUnsignedVarInt(0); //TODO: soft enums } catch (Exception e) { diff --git a/src/MiNET/MiNET/Net/McpeText.cs b/src/MiNET/MiNET/Net/McpeText.cs index 0c3cc10c9..6f669d620 100644 --- a/src/MiNET/MiNET/Net/McpeText.cs +++ b/src/MiNET/MiNET/Net/McpeText.cs @@ -40,8 +40,6 @@ partial void AfterEncode() case ChatTypes.Whisper: case ChatTypes.Announcement: Write(source); - Write(""); //TODO: third party name - WriteSignedVarInt(0); //TODO: platform goto case ChatTypes.Raw; case ChatTypes.Raw: case ChatTypes.Tip: @@ -80,8 +78,6 @@ partial void AfterDecode() case ChatTypes.Whisper: case ChatTypes.Announcement: source = ReadString(); - ReadString(); //TODO: third party name - ReadSignedVarInt(); //TODO: platform goto case ChatTypes.Raw; case ChatTypes.Raw: case ChatTypes.Tip: diff --git a/src/MiNET/MiNET/Net/Packet.cs b/src/MiNET/MiNET/Net/Packet.cs index e21fb44bb..b1d630c13 100644 --- a/src/MiNET/MiNET/Net/Packet.cs +++ b/src/MiNET/MiNET/Net/Packet.cs @@ -461,7 +461,7 @@ public void Write(PlayerRecords records) Write(record.ClientUuid); WriteSignedVarLong(record.EntityId); Write(record.DisplayName ?? record.Username); - Write(record.PlayerInfo.ThirdPartyName ?? record.DisplayName ?? record.Username); + Write(record.DisplayName ?? record.Username); WriteSignedVarInt(record.PlayerInfo.DeviceOS); Write(record.Skin, record?.PlayerInfo?.CertificateData?.ExtraData?.Xuid); Write(record.PlayerInfo.PlatformChatId); @@ -1762,9 +1762,20 @@ public void Write(ScorePacketInfos list) WriteUnsignedVarInt((uint) list.Count); foreach(var entry in list) { - Write(entry.uuid); + WriteVarLong(entry.scoreboardId); Write(entry.objectiveName); - Write(entry.score); + Write((uint)entry.score); + Write(entry.addType); + switch (entry.addType) + { + case 1: + case 2: + WriteVarLong(entry.entityId); + break; + case 3: + Write(entry.fakePlayer); + break; + } } } @@ -1773,18 +1784,81 @@ public ScorePacketInfos ReadScorePacketInfos() var list = new ScorePacketInfos(); var length = ReadUnsignedVarInt(); - for(var i = 0; i < length; ++i) - { - var entry = new ScorePacketInfo(); - entry.uuid = ReadUUID(); - entry.objectiveName = ReadString(); - entry.score = ReadUint(); + for (var i = 0; i < length; ++i) + { + var entry = new ScorePacketInfo(); + entry.scoreboardId = ReadVarLong(); + entry.objectiveName = ReadString(); + entry.score = (int) ReadUint(); + entry.addType = ReadByte(); + switch (entry.addType) + { + case 1: + case 2: + entry.entityId = ReadVarLong(); + break; + case 3: + entry.fakePlayer = ReadString(); + break; + } list.Add(entry); } return list; } + public void Write(ScoreboardIdentityPackets sip, byte type) + { + WriteUnsignedVarInt((uint)sip.Count); + foreach(var list in sip) + { + Write(list.ScoreboardId); + if (type == 0) + { + WriteVarLong(list.EntityId); + } + } + } + + public ScoreboardIdentityPackets ReadScoreboardIdentityPackets(byte type) + { + var list = new ScoreboardIdentityPackets(); + + var length = ReadUnsignedVarInt(); + for (var i = 0; i < length; ++i) + { + var entry = new ScoreboardIdentityPacket(); + entry.ScoreboardId = ReadVarLong(); + if(type == 0) + { + entry.EntityId = ReadVarLong(); + } + list.Add(entry); + } + + return list; + } + + public void Write(EnumValues values) + { + WriteUnsignedVarInt((uint)values.Count); + foreach(var value in values) + { + Write(value); + } + } + + public EnumValues ReadEnumValues() + { + var list = new EnumValues(); + var length = ReadUnsignedVarInt(); + for(int i = 0; i <= length; i++) + { + list.Add(ReadString()); + } + return list; + } + public bool CanRead() { return _reader.BaseStream.Position < _reader.BaseStream.Length; diff --git a/src/MiNET/MiNET/Player.cs b/src/MiNET/MiNET/Player.cs index a1151a199..6b04f61e0 100644 --- a/src/MiNET/MiNET/Player.cs +++ b/src/MiNET/MiNET/Player.cs @@ -46,6 +46,7 @@ using MiNET.Utils; using MiNET.Utils.Skins; using MiNET.Worlds; +using MiNET.Scoreboards; using Newtonsoft.Json; namespace MiNET @@ -101,6 +102,8 @@ public class Player : Entity, IMcpeMessageHandler public DamageCalculator DamageCalculator { get; set; } = new DamageCalculator(); + public Scoreboard Scoreboard; + public Player(MiNetServer server, IPEndPoint endPoint) : base(-1, null) { @@ -225,9 +228,7 @@ public virtual void HandleMcpeLabTable(McpeLabTable message) { } - public void HandleMcpeSetLocalPlayerAsInitializedPacket(McpeSetLocalPlayerAsInitializedPacket message) - { - } + private bool _serverHaveResources = false; @@ -1877,6 +1878,70 @@ public virtual void SetOpenInventory(IInventory inventory) _openInventory = inventory; } + + public void SendScoreboard() + { + if (Scoreboard != null) { + + var pk = McpeSetDisplayObjective.CreateObject(); + pk.displaySlot = Scoreboard.objective.SlotToString(); + pk.objectiveName = Scoreboard.objective.Name; + pk.displayName = Scoreboard.objective.DisplayName; + pk.criteriaName = Scoreboard.objective.CriteriaToString(); + pk.sortOrder = Scoreboard.objective.Sort; + SendPacket(pk); + foreach (var scores in Scoreboard.objective.Scores) + { + var pk2 = McpeSetScore.CreateObject(); + pk2.type = 0; + var spi = new ScorePacketInfos(); + if (scores.IsFake) + { + var info = new ScorePacketInfo() + { + scoreboardId = scores.ScoreboardId, + objectiveName = scores.Objective.Name, + score = scores.ScoreId, + fakePlayer = scores.FakePlayer, + addType = 3 + }; + spi.Add(info); + } else + { + var info = new ScorePacketInfo() + { + scoreboardId = scores.ScoreboardId, + objectiveName = scores.Objective.Name, + score = scores.ScoreId, + entityId = scores.Id, + addType = 1 + }; + spi.Add(info); + } + + + pk2.scorePacketInfos = spi; + SendPacket(pk2); + } + } else + { + Log.Error("Cannot send scoreboard while it's null"); + } + } + + public void RemoveScoreboard() + { + if(Scoreboard != null) + { + var pk = McpeRemoveObjective.CreateObject(); + pk.objectiveName = Scoreboard.objective.Name; + SendPacket(pk); + Scoreboard = null; + } + } + + + public void OpenInventory(BlockCoordinates inventoryCoord) { lock (_inventorySync) @@ -2569,7 +2634,7 @@ public void SendStartGame() startGame.isMultiplayer = true; startGame.broadcastToLan = true; startGame.broadcastToXbl = true; - startGame.enableCommands = EnableCommands; + startGame.enableCommands = EnableCommands; startGame.isTexturepacksRequired = false; startGame.gamerules = Level.GetGameRules(); startGame.bonusChest = false; @@ -3467,7 +3532,47 @@ protected virtual void OnTicked(PlayerEventArgs e) { Ticked?.Invoke(this, e); } - } + + public void HandleMcpeSetLocalPlayerAsInitializedPacket(McpeSetLocalPlayerAsInitialized message) + { + + } + + public void HandleSetScoreboardIdentity(McpeSetScoreboardIdentity message) + { + + } + + public void HandleUpdateEnumSoft(McpeUpdateSoftEnum message) + { + + } + + public void HandleNetworkStackLatency(McpeNetworkStackLatency message) + { + + } + + public void HandleScriptCustomEvent(McpeScriptCustomEvent message) + { + + } + + public void HandleMcpeRemoveObjective(McpeRemoveObjective mesage) + { + throw new NotImplementedException(); + } + + public void HandleMcpeSetDisplayObjective(McpeSetDisplayObjective message) + { + + } + + public void HandleMcpeSetScore(McpeSetScore message) + { + + } + } public class PlayerEventArgs : EventArgs { diff --git a/src/MiNET/MiNET/PlayerNetworkSession.cs b/src/MiNET/MiNET/PlayerNetworkSession.cs index c9d42768e..ef067d183 100644 --- a/src/MiNET/MiNET/PlayerNetworkSession.cs +++ b/src/MiNET/MiNET/PlayerNetworkSession.cs @@ -651,6 +651,11 @@ private void HandlePacket(IMcpeMessageHandler handler, Packet message) handler.HandleMcpeNpcRequest((McpeNpcRequest)message); } + else if (typeof(McpeSetDisplayObjective) == message.GetType()) + { + handler.HandleMcpeSetDisplayObjective((McpeSetDisplayObjective)message); + } + else { Log.Error($"Unhandled packet: {message.GetType().Name} 0x{message.Id:X2} for user: {Username}, IP {EndPoint.Address}"); @@ -1079,7 +1084,6 @@ public class PlayerInfo public int ProtocolVersion { get; set; } public string LanguageCode { get; set; } public string PlatformChatId { get; set; } - public string ThirdPartyName { get; set; } public string TenantId { get; set; } } } diff --git a/src/MiNET/MiNET/Scoreboards/Score.cs b/src/MiNET/MiNET/Scoreboards/Score.cs new file mode 100644 index 000000000..2e463ce6e --- /dev/null +++ b/src/MiNET/MiNET/Scoreboards/Score.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MiNET.Entities; +using MiNET.Net; + +namespace MiNET.Scoreboards +{ + public class Score + { + public long ScoreboardId { get; set; } + public ScoreboardObjective Objective { get; set; } + public Entity Entity { get; set; } + public string FakePlayer { get; set; } + public int ScoreId { get; set; } + public long Id { get; set; } + public bool IsFake { get; set; } + + public Score(ScoreboardObjective obj, string fakeplayer) + { + ScoreboardId = Scoreboard.RandomId(); + Objective = obj; + FakePlayer = fakeplayer; + IsFake = true; + } + + public Score(ScoreboardObjective obj, Entity entity) + { + ScoreboardId = Scoreboard.RandomId(); + Objective = obj; + Entity = entity; + Id = entity.EntityId; + IsFake = false; + } + + public void SetScore(int score) + { + ScoreId = score; + } + + public int GetScore() + { + return ScoreId; + } + + } +} diff --git a/src/MiNET/MiNET/Scoreboards/Scoreboard.cs b/src/MiNET/MiNET/Scoreboards/Scoreboard.cs new file mode 100644 index 000000000..a95e59168 --- /dev/null +++ b/src/MiNET/MiNET/Scoreboards/Scoreboard.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading; +using MiNET.Net; + +namespace MiNET.Scoreboards +{ + public class Scoreboard + { + + public ScoreboardObjective objective { get; set; } + public long id { get; set; } + public bool AlreadyCreated = false; + + public Scoreboard() + { + id = -RandomId(); + } + + public ScoreboardObjective registerObjective(string name, ScoreboardCriteria criteria) + { + var obj = new ScoreboardObjective() + { + Name = name, + Criteria = criteria + }; + objective = obj; + return objective; + } + + public static long RandomId() + { + Random rnd = new Random(); + + byte[] buf = new byte[8]; + rnd.NextBytes(buf); + long intRand = BitConverter.ToInt64(buf, 0); + + long result = (Math.Abs(intRand % (20000000000 - 10000000000)) + 10000000000); + + long random_seed = (long)rnd.Next(1000, 5000); + random_seed = random_seed * result + rnd.Next(1000, 5000); + long randomlong = ((long)(random_seed / 655) % 10000000001); + return randomlong; + } + + + } + +} diff --git a/src/MiNET/MiNET/Scoreboards/ScoreboardCriteria.cs b/src/MiNET/MiNET/Scoreboards/ScoreboardCriteria.cs new file mode 100644 index 000000000..4818dc35f --- /dev/null +++ b/src/MiNET/MiNET/Scoreboards/ScoreboardCriteria.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MiNET.Scoreboards +{ + public enum ScoreboardCriteria + { + Dummy + } +} diff --git a/src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs b/src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs new file mode 100644 index 000000000..802461862 --- /dev/null +++ b/src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace MiNET.Scoreboards +{ + + public enum ScoreboardDisplaySlot + { + List, + Sidebar, + BellowName + + } +} diff --git a/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs b/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs new file mode 100644 index 000000000..93bff1708 --- /dev/null +++ b/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs @@ -0,0 +1,89 @@ +using System; +using System.Collections.Generic; +using System.Text; +using MiNET.Entities; + +namespace MiNET.Scoreboards +{ + public enum ScoreboardSort + { + Ascending = 0, + Descending = 1 + } + + public class ScoreboardObjective + { + + public String Name { get; set; } + public ScoreboardDisplaySlot DisplaySlot { get; set; } + public ScoreboardCriteria Criteria { get; set; } + public String DisplayName { get; set; } + public List Scores = new List(); + + public byte Sort = (int)ScoreboardSort.Descending; + + public Score GetScore(String fakeplayer) + { + Score score = null; + foreach(var scores in Scores) + { + if (scores.FakePlayer.Equals(fakeplayer)) + { + score = scores; + } + } + return score; + } + + public void AddScore(Entity entity, int value) + { + var score = new Score(this, entity); + score.SetScore(value); + if (!Scores.Contains(score)) + { + Scores.Add(score); + } + } + + public void AddScore(string entry, int value) + { + var score = new Score(this, entry); + score.SetScore(value); + if (!Scores.Contains(score)) + { + Scores.Add(score); + } + } + + public string CriteriaToString() + { + string s = ""; + switch (Criteria) + { + case ScoreboardCriteria.Dummy: + s = "dummy"; + break; + } + return s; + } + + public string SlotToString() + { + string slot = ""; + switch (DisplaySlot) + { + case ScoreboardDisplaySlot.Sidebar: + slot = "sidebar"; + break; + case ScoreboardDisplaySlot.List: + slot = "list"; + break; + case ScoreboardDisplaySlot.BellowName: + slot = "bellowname"; + break; + } + return slot; + } + + } +} diff --git a/src/MiNET/MiNET/Utils/CryptoUtils.cs b/src/MiNET/MiNET/Utils/CryptoUtils.cs index 4c1ec2e69..fad7d8414 100644 --- a/src/MiNET/MiNET/Utils/CryptoUtils.cs +++ b/src/MiNET/MiNET/Utils/CryptoUtils.cs @@ -280,14 +280,40 @@ private static ECDsa ConvertToSingKeyFormat(AsymmetricCipherKeyPair key) { X = pubAsyKey.Q.AffineXCoord.GetEncoded(), Y = pubAsyKey.Q.AffineYCoord.GetEncoded() - }, - D = privAsyKey.D.ToByteArrayUnsigned() + } }; + signParam.D = FixDSize(privAsyKey.D.ToByteArrayUnsigned(), signParam.Q.X.Length); signParam.Validate(); return ECDsa.Create(signParam); } + public static byte[] FixDSize(byte[] input, int expectedSize) + { + if (input.Length == expectedSize) + { + return input; + } + + byte[] tmp; + + if (input.Length < expectedSize) + { + tmp = new byte[expectedSize]; + Buffer.BlockCopy(input, 0, tmp, expectedSize - input.Length, input.Length); + return tmp; + } + + if (input.Length > expectedSize + 1 || input[0] != 0) + { + throw new InvalidOperationException(); + } + + tmp = new byte[expectedSize]; + Buffer.BlockCopy(input, 1, tmp, 0, expectedSize); + return tmp; + } + public static byte[] CompressJwtBytes(byte[] certChain, byte[] skinData, CompressionLevel compressionLevel) { using (MemoryStream stream = MiNetServer.MemoryStreamManager.GetStream()) diff --git a/src/MiNET/MiNET/Utils/ScorePacketInfo.cs b/src/MiNET/MiNET/Utils/ScorePacketInfo.cs index d622cb8f6..06543d9cf 100644 --- a/src/MiNET/MiNET/Utils/ScorePacketInfo.cs +++ b/src/MiNET/MiNET/Utils/ScorePacketInfo.cs @@ -7,8 +7,11 @@ public class ScorePacketInfos : List { } public class ScorePacketInfo { - public UUID uuid { get; set; } + public long scoreboardId { get; set; } public string objectiveName { get; set; } - public uint score { get; set; } + public int score { get; set; } + public long entityId { get; set; } + public string fakePlayer { get; set; } + public byte addType; } } diff --git a/src/MiNET/MiNET/Utils/ScoreboardIdentityPacket.cs b/src/MiNET/MiNET/Utils/ScoreboardIdentityPacket.cs new file mode 100644 index 000000000..74b7c10b1 --- /dev/null +++ b/src/MiNET/MiNET/Utils/ScoreboardIdentityPacket.cs @@ -0,0 +1,20 @@ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using MiNET.Net; +namespace MiNET.Utils +{ + + public class ScoreboardIdentityPackets : List { } + + public class ScoreboardIdentityPacket + { + public long ScoreboardId { get; set; } + public long EntityId { get; set; } + + + } +} \ No newline at end of file diff --git a/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs b/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs index a3ee49f0b..1d46e1b85 100644 --- a/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs +++ b/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs @@ -50,300 +50,330 @@ using MiNET.Utils; using MiNET.Utils.Skins; using MiNET.Worlds; +using MiNET.Scoreboards; namespace TestPlugin.NiceLobby { - [Plugin(PluginName = "NiceLobby", Description = "", PluginVersion = "1.0", Author = "MiNET Team")] - public class NiceLobbyPlugin : Plugin - { - private static readonly ILog Log = LogManager.GetLogger(typeof (NiceLobbyPlugin)); - - private Timer _popupTimer; - private Timer _tickTimer; - - private long _tick = 0; - - protected override void OnEnable() - { - var server = Context.Server; - - server.LevelManager.LevelCreated += (sender, args) => - { - Level level = args.Level; - - //BossBar bossBar = new BossBar(level) - //{ - // Animate = false, - // MaxProgress = 10, - // Progress = 10, - // NameTag = $"{ChatColors.Gold}You are playing on a {ChatColors.Gold}MiNET{ChatColors.Gold} server" - //}; - //bossBar.SpawnEntity(); - - //level.AllowBuild = false; - //level.AllowBreak = false; - - //level.BlockBreak += LevelOnBlockBreak; - //level.BlockPlace += LevelOnBlockPlace; - }; - - server.PlayerFactory.PlayerCreated += (sender, args) => - { - Player player = args.Player; - player.PlayerJoin += OnPlayerJoin; - player.PlayerLeave += OnPlayerLeave; - player.Ticking += OnTicking; - }; - - //_popupTimer = new Timer(DoDevelopmentPopups, null, 10000, 20000); - //_tickTimer = new Timer(LevelTick, null, 0, 50); - //_tickTimer = new Timer(SkinTick, null, 0, 50); - } - - private void OnTicking(object sender, PlayerEventArgs e) - { - var player = e.Player; - var level = player.Level; - - //if (e.Level.TickTime % 2 == 0) - //{ - // BlockCoordinates pos = (BlockCoordinates)player.KnownPosition; - // player.AddPopup(new Popup() - // { - // Id = 11, - // MessageType = MessageType.Popup, - // Message = $"SkyLight Subtracted={level.SkylightSubtracted}, Under={level.GetSkyLight(pos + BlockCoordinates.Down)}, Foot={level.GetSkyLight(pos)}, Head={level.GetSkyLight(pos + BlockCoordinates.Up)}, Height={level.GetHeight(pos)}", - // Duration = 20 * 5, - // }); - //} - - - // Compass - //if (e.Level.TickTime % 2 == 0) - //{ - // player.AddPopup(new Popup() - // { - // Id = 10, - // MessageType = MessageType.Tip, - // Message = GetCompass(player.KnownPosition.HeadYaw), - // Duration = 20 * 5, - // }); - //} - - - // Glide extension - //if (player.IsGliding) - //{ - // if (player.CurrentSpeed > 30) - // { - // var particle = new CriticalParticle(level); - // particle.Position = player.KnownPosition.ToVector3(); - // particle.Spawn(); - // } - - // if (level.TickTime%10 == 0) - // { - // player.AddPopup(new Popup() - // { - // Id = 10, - // MessageType = MessageType.Tip, - // Message = $"Speed: {player.CurrentSpeed:F2}m/s", - // Duration = 20*5, - // }); - // } - //} - } - - public static float Wrap(float angle) - { - return (float) (angle + Math.Ceiling(-angle/360)*360); - } - - public static string GetCompass(float direction) - { - direction = Wrap(direction); - direction = direction*2/10; - - direction += 72; - - int width = 25; - - var compass = new string('|', 72).ToCharArray(); - compass[0] = 'S'; - - compass[9] = 'S'; - compass[9 + 1] = 'W'; - - compass[(18)] = 'W'; - - compass[(18 + 9)] = 'N'; - compass[(18 + 9 + 1)] = 'W'; - - compass[36] = 'N'; - - compass[36 + 9] = 'N'; - compass[36 + 9 + 1] = 'E'; - - compass[54] = 'E'; - - compass[54 + 9] = 'S'; - compass[54 + 9 + 1] = 'E'; - - compass = compass.Concat(compass).Concat(compass).ToArray(); - - return new String(compass.Skip((int) (direction - Math.Floor((double) width/2))).Take(width).ToArray()) - .Replace("|", "| ") - .Replace("| N|", $"| {ChatFormatting.Bold}{ChatColors.Red}N{ChatFormatting.Reset} |") - .Replace("| NE|", $"| {ChatFormatting.Bold}{ChatColors.Yellow}NE{ChatFormatting.Reset} |").Trim('N', 'W', 'S', 'E').Trim('N', 'W', 'S', 'E') - .Replace("| E|", $"| {ChatFormatting.Bold}{ChatColors.Green}E{ChatFormatting.Reset} |") - .Replace("| SE|", $"| {ChatFormatting.Bold}{ChatColors.Green}SE{ChatFormatting.Reset} |") - .Replace("| S|", $"| {ChatFormatting.Bold}{ChatColors.Aqua}S{ChatFormatting.Reset} |") - .Replace("| SW|", $"| {ChatFormatting.Bold}{ChatColors.Blue}SW{ChatFormatting.Reset} |") - .Replace("| W|", $"| {ChatFormatting.Bold}{ChatColors.DarkPurple}W{ChatFormatting.Reset} |") - .Replace("| NW|", $"| {ChatFormatting.Bold}{ChatColors.LightPurple}NW{ChatFormatting.Reset} |") - ; - } - - - private object _skinSynk = new object(); - - private int _image = 0; - private int _imageCape = 0; - - private void SkinTick(object state) - { - if (!Monitor.TryEnter(_skinSynk)) return; - - try - { - foreach (var player in _players.Values) - { - { - if (!player.Username.Equals("gurunx")) continue; - - if (_image >= 9) _image = 0; - - _image++; - _imageCape++; - - Skin skin = player.Skin; - - - //skin.SkinGeometryName = ""; - //skin.SkinGeometry = Encoding.UTF8.GetBytes(File.ReadAllText(@"D:\Temp\humanoid.json")); - - { - string file = Path.Combine(@"D:\Development\Other\Smash Heroes 3x6 (128)\Smash Heroes 3x6 (128)", $"Smash Heroes Trailer{_imageCape:D4}.bmp"); - //string file = @"D:\Temp\Smiley\big_smile0" + _image + ".png"; - if (!File.Exists(file)) - { - _imageCape = 0; - continue; - } - - //Bitmap bitmap = new Bitmap((Bitmap)Image.FromFile(file), 12, 18); - Bitmap bitmap = new Bitmap((Bitmap) Image.FromFile(file), 64, 64); - int offsetx = 16, offsety = 16; - bitmap = CropImage(bitmap, new Rectangle(offsetx, offsety, 12, 18)); - byte[] bytes = new byte[32*64*4]; - - int i = 0; - for (int y = 0; y < 32; y++) - { - for (int x = 0; x < 64; x++) - { - if (y >= bitmap.Height || x >= bitmap.Width) - { - Color color = Color.Yellow; - bytes[i++] = color.R; - bytes[i++] = color.G; - bytes[i++] = color.B; - bytes[i++] = color.A; - continue; - } - else - { - Color color = bitmap.GetPixel(x, y); - bytes[i++] = color.R; - bytes[i++] = color.G; - bytes[i++] = color.B; - bytes[i++] = color.A; - } - } - } - skin.CapeData = bytes; - } - - - Level level = player.Level; - //if (level.TickTime%3 != 0) return; - //player.SetNameTag(player.Username + " " + level.TickTime + " testing"); - //player.SetDisplayName(player.Username + " " + level.TickTime + " testing"); - - var texture = skin.SkinData; - byte[] smiley = GetTextureFromFile(@"D:\Temp\Smiley\big_smile0" + _image + ".png"); - if (smiley.Length != 8*8*4) return; - int s = 0; - int br = 8; - int bc = 8; - for (int r = 0; r < 8; r++) - { - for (int c = 0; c < 8; c++) - { - int i = ((c + bc)*4) + ((r + br)*64*4); - int j = ((c)*4) + ((r)*8*4); - - texture[(i) + 0] = smiley[j + 0]; - texture[(i) + 1] = smiley[j + 1]; - texture[(i) + 2] = smiley[j + 2]; - texture[(i) + 3] = smiley[j + 3]; - } - } - - { - McpePlayerSkin updateSkin = McpePlayerSkin.CreateObject(); - updateSkin.uuid = player.ClientUuid; - updateSkin.skinId = skin.SkinId; - updateSkin.skinData = skin.SkinData; - updateSkin.capeData = skin.CapeData; - updateSkin.geometryModel = skin.SkinGeometryName; - updateSkin.geometryData = skin.SkinGeometry; - level.RelayBroadcast(updateSkin); - } - - { - //player.SpawnPosition = player.KnownPosition; - - //level.DespawnFromAll(player); - //level.SpawnToAll(player); - - //var players = level.GetSpawnedPlayers(); - - //McpePlayerList playerList = McpePlayerList.CreateObject(); - //playerList.records = new PlayerAddRecords {player}; - //level.RelayBroadcast(player, players, CreateMcpeBatch(playerList.Encode())); - //playerList.records = null; - //playerList.PutPool(); - - //player.IsInvisible = true; - //player.HideNameTag = true; - //player.BroadcastSetEntityData(); - - //player.SpawnToPlayers(players); - - //Thread.Sleep(100); - //player.HideNameTag = false; - //player.IsInvisible = false; - //player.BroadcastSetEntityData(); - } - } - } - } - finally - { - Monitor.Exit(_skinSynk); - } - } + [Plugin(PluginName = "NiceLobby", Description = "", PluginVersion = "1.0", Author = "MiNET Team")] + public class NiceLobbyPlugin : Plugin + { + private static readonly ILog Log = LogManager.GetLogger(typeof(NiceLobbyPlugin)); + + private Timer _popupTimer; + private Timer _tickTimer; + + private long _tick = 0; + + protected override void OnEnable() + { + var server = Context.Server; + + server.LevelManager.LevelCreated += (sender, args) => + { + Level level = args.Level; + + //BossBar bossBar = new BossBar(level) + //{ + // Animate = false, + // MaxProgress = 10, + // Progress = 10, + // NameTag = $"{ChatColors.Gold}You are playing on a {ChatColors.Gold}MiNET{ChatColors.Gold} server" + //}; + //bossBar.SpawnEntity(); + + //level.AllowBuild = false; + //level.AllowBreak = false; + + //level.BlockBreak += LevelOnBlockBreak; + //level.BlockPlace += LevelOnBlockPlace; + }; + + server.PlayerFactory.PlayerCreated += (sender, args) => + { + Player player = args.Player; + player.PlayerJoin += OnPlayerJoin; + player.PlayerLeave += OnPlayerLeave; + player.Ticking += OnTicking; + }; + + //_popupTimer = new Timer(DoDevelopmentPopups, null, 10000, 20000); + //_tickTimer = new Timer(LevelTick, null, 0, 50); + //_tickTimer = new Timer(SkinTick, null, 0, 50); + } + + private void OnTicking(object sender, PlayerEventArgs e) + { + var player = e.Player; + var level = player.Level; + + //if (e.Level.TickTime % 2 == 0) + //{ + // BlockCoordinates pos = (BlockCoordinates)player.KnownPosition; + // player.AddPopup(new Popup() + // { + // Id = 11, + // MessageType = MessageType.Popup, + // Message = $"SkyLight Subtracted={level.SkylightSubtracted}, Under={level.GetSkyLight(pos + BlockCoordinates.Down)}, Foot={level.GetSkyLight(pos)}, Head={level.GetSkyLight(pos + BlockCoordinates.Up)}, Height={level.GetHeight(pos)}", + // Duration = 20 * 5, + // }); + //} + + + // Compass + //if (e.Level.TickTime % 2 == 0) + //{ + // player.AddPopup(new Popup() + // { + // Id = 10, + // MessageType = MessageType.Tip, + // Message = GetCompass(player.KnownPosition.HeadYaw), + // Duration = 20 * 5, + // }); + //} + + + // Glide extension + //if (player.IsGliding) + //{ + // if (player.CurrentSpeed > 30) + // { + // var particle = new CriticalParticle(level); + // particle.Position = player.KnownPosition.ToVector3(); + // particle.Spawn(); + // } + + // if (level.TickTime%10 == 0) + // { + // player.AddPopup(new Popup() + // { + // Id = 10, + // MessageType = MessageType.Tip, + // Message = $"Speed: {player.CurrentSpeed:F2}m/s", + // Duration = 20*5, + // }); + // } + //} + } + + public static float Wrap(float angle) + { + return (float)(angle + Math.Ceiling(-angle / 360) * 360); + } + + public static string GetCompass(float direction) + { + direction = Wrap(direction); + direction = direction * 2 / 10; + + direction += 72; + + int width = 25; + + var compass = new string('|', 72).ToCharArray(); + compass[0] = 'S'; + + compass[9] = 'S'; + compass[9 + 1] = 'W'; + + compass[(18)] = 'W'; + + compass[(18 + 9)] = 'N'; + compass[(18 + 9 + 1)] = 'W'; + + compass[36] = 'N'; + + compass[36 + 9] = 'N'; + compass[36 + 9 + 1] = 'E'; + + compass[54] = 'E'; + + compass[54 + 9] = 'S'; + compass[54 + 9 + 1] = 'E'; + + compass = compass.Concat(compass).Concat(compass).ToArray(); + + return new String(compass.Skip((int)(direction - Math.Floor((double)width / 2))).Take(width).ToArray()) + .Replace("|", "| ") + .Replace("| N|", $"| {ChatFormatting.Bold}{ChatColors.Red}N{ChatFormatting.Reset} |") + .Replace("| NE|", $"| {ChatFormatting.Bold}{ChatColors.Yellow}NE{ChatFormatting.Reset} |").Trim('N', 'W', 'S', 'E').Trim('N', 'W', 'S', 'E') + .Replace("| E|", $"| {ChatFormatting.Bold}{ChatColors.Green}E{ChatFormatting.Reset} |") + .Replace("| SE|", $"| {ChatFormatting.Bold}{ChatColors.Green}SE{ChatFormatting.Reset} |") + .Replace("| S|", $"| {ChatFormatting.Bold}{ChatColors.Aqua}S{ChatFormatting.Reset} |") + .Replace("| SW|", $"| {ChatFormatting.Bold}{ChatColors.Blue}SW{ChatFormatting.Reset} |") + .Replace("| W|", $"| {ChatFormatting.Bold}{ChatColors.DarkPurple}W{ChatFormatting.Reset} |") + .Replace("| NW|", $"| {ChatFormatting.Bold}{ChatColors.LightPurple}NW{ChatFormatting.Reset} |") + ; + } + + + private object _skinSynk = new object(); + + private int _image = 0; + private int _imageCape = 0; + + private void SkinTick(object state) + { + if (!Monitor.TryEnter(_skinSynk)) return; + + try + { + foreach (var player in _players.Values) + { + { + if (!player.Username.Equals("gurunx")) continue; + + if (_image >= 9) _image = 0; + + _image++; + _imageCape++; + + Skin skin = player.Skin; + + + //skin.SkinGeometryName = ""; + //skin.SkinGeometry = Encoding.UTF8.GetBytes(File.ReadAllText(@"D:\Temp\humanoid.json")); + + { + string file = Path.Combine(@"D:\Development\Other\Smash Heroes 3x6 (128)\Smash Heroes 3x6 (128)", $"Smash Heroes Trailer{_imageCape:D4}.bmp"); + //string file = @"D:\Temp\Smiley\big_smile0" + _image + ".png"; + if (!File.Exists(file)) + { + _imageCape = 0; + continue; + } + + //Bitmap bitmap = new Bitmap((Bitmap)Image.FromFile(file), 12, 18); + Bitmap bitmap = new Bitmap((Bitmap)Image.FromFile(file), 64, 64); + int offsetx = 16, offsety = 16; + bitmap = CropImage(bitmap, new Rectangle(offsetx, offsety, 12, 18)); + byte[] bytes = new byte[32 * 64 * 4]; + + int i = 0; + for (int y = 0; y < 32; y++) + { + for (int x = 0; x < 64; x++) + { + if (y >= bitmap.Height || x >= bitmap.Width) + { + Color color = Color.Yellow; + bytes[i++] = color.R; + bytes[i++] = color.G; + bytes[i++] = color.B; + bytes[i++] = color.A; + continue; + } + else + { + Color color = bitmap.GetPixel(x, y); + bytes[i++] = color.R; + bytes[i++] = color.G; + bytes[i++] = color.B; + bytes[i++] = color.A; + } + } + } + skin.CapeData = bytes; + } + + + Level level = player.Level; + //if (level.TickTime%3 != 0) return; + //player.SetNameTag(player.Username + " " + level.TickTime + " testing"); + //player.SetDisplayName(player.Username + " " + level.TickTime + " testing"); + + var texture = skin.SkinData; + byte[] smiley = GetTextureFromFile(@"D:\Temp\Smiley\big_smile0" + _image + ".png"); + if (smiley.Length != 8 * 8 * 4) return; + int s = 0; + int br = 8; + int bc = 8; + for (int r = 0; r < 8; r++) + { + for (int c = 0; c < 8; c++) + { + int i = ((c + bc) * 4) + ((r + br) * 64 * 4); + int j = ((c) * 4) + ((r) * 8 * 4); + + texture[(i) + 0] = smiley[j + 0]; + texture[(i) + 1] = smiley[j + 1]; + texture[(i) + 2] = smiley[j + 2]; + texture[(i) + 3] = smiley[j + 3]; + } + } + + { + McpePlayerSkin updateSkin = McpePlayerSkin.CreateObject(); + updateSkin.uuid = player.ClientUuid; + updateSkin.skinId = skin.SkinId; + updateSkin.skinData = skin.SkinData; + updateSkin.capeData = skin.CapeData; + updateSkin.geometryModel = skin.SkinGeometryName; + updateSkin.geometryData = skin.SkinGeometry; + level.RelayBroadcast(updateSkin); + } + + { + //player.SpawnPosition = player.KnownPosition; + + //level.DespawnFromAll(player); + //level.SpawnToAll(player); + + //var players = level.GetSpawnedPlayers(); + + //McpePlayerList playerList = McpePlayerList.CreateObject(); + //playerList.records = new PlayerAddRecords {player}; + //level.RelayBroadcast(player, players, CreateMcpeBatch(playerList.Encode())); + //playerList.records = null; + //playerList.PutPool(); + + //player.IsInvisible = true; + //player.HideNameTag = true; + //player.BroadcastSetEntityData(); + + //player.SpawnToPlayers(players); + + //Thread.Sleep(100); + //player.HideNameTag = false; + //player.IsInvisible = false; + //player.BroadcastSetEntityData(); + } + } + } + } + finally + { + Monitor.Exit(_skinSynk); + } + } + + public void SendScoreboard(Player player) + { + var board = new Scoreboard(); + var objective = board.registerObjective("minet", ScoreboardCriteria.Dummy); + objective.DisplayName = "§l§6MiNET dev server"; + objective.DisplaySlot = ScoreboardDisplaySlot.Sidebar; + objective.AddScore("Scores", 3); + objective.AddScore("Work's", 2); + objective.AddScore($"{player.Username}", 1); + player.Scoreboard = board; + player.SendScoreboard(); + + } + + public void ResendScoreboard(Player player) + { + player.RemoveScoreboard(); + var board = new Scoreboard(); + var objective = board.registerObjective("minet", ScoreboardCriteria.Dummy); + objective.DisplayName = "§l§eMiNET dev server"; + objective.DisplaySlot = ScoreboardDisplaySlot.Sidebar; + objective.AddScore("This", 3); + objective.AddScore("Work's", 2); + objective.AddScore("Too", 1); + player.Scoreboard = board; + player.SendScoreboard(); + } + public static byte[] GetTextureFromFile(string filename) { @@ -484,6 +514,7 @@ private void OnPlayerJoin(object o, PlayerEventArgs eventArgs) player.SendTitle(null, TitleType.AnimationTimes, 6, 6, 20*10); player.SendTitle($"{ChatColors.White}This is gurun's MiNET\n.NET core test server", TitleType.SubTitle); player.SendTitle($"{ChatColors.Gold}Welcome {player.Username}!", TitleType.Title); + SendScoreboard(player); }); } @@ -788,8 +819,13 @@ public void Reset(Player player) } } + [Command(Name ="board")] + public void Board(Player player) + { + ResendScoreboard(player); + } - [Command] + [Command] public void Awk(Player player) { string awk = "[" + ChatColors.DarkRed + "AWK" + ChatFormatting.Reset + "]"; From debef9b70308f7a9315c0b79990e0833b4607ea8 Mon Sep 17 00:00:00 2001 From: Ragnok123 <=> Date: Mon, 27 Aug 2018 21:16:57 +0200 Subject: [PATCH 2/3] Fix below name --- src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs | 2 +- src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs b/src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs index 802461862..de9639bc3 100644 --- a/src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs +++ b/src/MiNET/MiNET/Scoreboards/ScoreboardDisplaySlot.cs @@ -9,7 +9,7 @@ public enum ScoreboardDisplaySlot { List, Sidebar, - BellowName + BelowName } } diff --git a/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs b/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs index 93bff1708..1db6ba9b0 100644 --- a/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs +++ b/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs @@ -78,8 +78,8 @@ public string SlotToString() case ScoreboardDisplaySlot.List: slot = "list"; break; - case ScoreboardDisplaySlot.BellowName: - slot = "bellowname"; + case ScoreboardDisplaySlot.BelowName: + slot = "belowname"; break; } return slot; From a20777d25f1a248cb2bd8ed692e9908fb1d9bc3f Mon Sep 17 00:00:00 2001 From: Ragnok123 <=> Date: Sun, 2 Sep 2018 21:30:48 +0200 Subject: [PATCH 3/3] Started working on scores system --- src/MiNET/MiNET.Client/MiNetClient.cs | 4 +- src/MiNET/MiNET/Player.cs | 1 - .../MiNET/Scoreboards/ScoreboardObjective.cs | 37 ++++++++++++++++++- .../TestPlugin/NiceLobby/NiceLobbyPlugin.cs | 12 +++--- 4 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/MiNET/MiNET.Client/MiNetClient.cs b/src/MiNET/MiNET.Client/MiNetClient.cs index d7d095d91..cff447d96 100644 --- a/src/MiNET/MiNET.Client/MiNetClient.cs +++ b/src/MiNET/MiNET.Client/MiNetClient.cs @@ -123,8 +123,8 @@ private static void Main(string[] args) int threads; int iothreads; ThreadPool.GetMinThreads(out threads, out iothreads); - var client = new MiNetClient(new IPEndPoint(IPAddress.Parse("10.0.0.6"), 19132), "RagnokBot", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); - //var client = new MiNetClient(new IPEndPoint(Dns.GetHostEntry("yodamine.com").AddressList[0], 19132), "TheGrey", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); + //var client = new MiNetClient(new IPEndPoint(IPAddress.Parse("10.0.0.6"), 19132), "RagnokBot", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); + var client = new MiNetClient(new IPEndPoint(Dns.GetHostEntry("yodamine.com").AddressList[0], 19132), "TheGrey", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); //var client = new MiNetClient(new IPEndPoint(IPAddress.Loopback, 19132), "TheGrey", new DedicatedThreadPool(new DedicatedThreadPoolSettings(Environment.ProcessorCount))); client.StartClient(); diff --git a/src/MiNET/MiNET/Player.cs b/src/MiNET/MiNET/Player.cs index 6b04f61e0..7452936b7 100644 --- a/src/MiNET/MiNET/Player.cs +++ b/src/MiNET/MiNET/Player.cs @@ -1882,7 +1882,6 @@ public virtual void SetOpenInventory(IInventory inventory) public void SendScoreboard() { if (Scoreboard != null) { - var pk = McpeSetDisplayObjective.CreateObject(); pk.displaySlot = Scoreboard.objective.SlotToString(); pk.objectiveName = Scoreboard.objective.Name; diff --git a/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs b/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs index 1db6ba9b0..ee55f7b11 100644 --- a/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs +++ b/src/MiNET/MiNET/Scoreboards/ScoreboardObjective.cs @@ -35,23 +35,56 @@ public Score GetScore(String fakeplayer) return score; } - public void AddScore(Entity entity, int value) + public Score GetScore(Entity fakeplayer) + { + Score score = null; + foreach (var scores in Scores) + { + if (scores.Entity.Equals(fakeplayer)) + { + score = scores; + } + } + return score; + } + + public void SetScore(Entity entity, int value) { var score = new Score(this, entity); score.SetScore(value); if (!Scores.Contains(score)) { Scores.Add(score); + } else + { + foreach (var scores in Scores) + { + if(scores.Entity.Equals(entity)) + { + Scores.Remove(scores); + Scores.Add(score); + } + } } } - public void AddScore(string entry, int value) + public void SetScore(string entry, int value) { var score = new Score(this, entry); score.SetScore(value); if (!Scores.Contains(score)) { Scores.Add(score); + } else + { + foreach(var scores in Scores) + { + if (scores.FakePlayer.Equals(entry)) + { + Scores.Remove(scores); + Scores.Add(score); + } + } } } diff --git a/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs b/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs index 1d46e1b85..4eda99948 100644 --- a/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs +++ b/src/MiNET/TestPlugin/NiceLobby/NiceLobbyPlugin.cs @@ -352,9 +352,9 @@ public void SendScoreboard(Player player) var objective = board.registerObjective("minet", ScoreboardCriteria.Dummy); objective.DisplayName = "§l§6MiNET dev server"; objective.DisplaySlot = ScoreboardDisplaySlot.Sidebar; - objective.AddScore("Scores", 3); - objective.AddScore("Work's", 2); - objective.AddScore($"{player.Username}", 1); + objective.SetScore("Scores", 3); + objective.SetScore("Work's", 2); + objective.SetScore($"{player.Username}", 1); player.Scoreboard = board; player.SendScoreboard(); @@ -367,9 +367,9 @@ public void ResendScoreboard(Player player) var objective = board.registerObjective("minet", ScoreboardCriteria.Dummy); objective.DisplayName = "§l§eMiNET dev server"; objective.DisplaySlot = ScoreboardDisplaySlot.Sidebar; - objective.AddScore("This", 3); - objective.AddScore("Work's", 2); - objective.AddScore("Too", 1); + objective.SetScore("This", 3); + objective.SetScore("Work's", 2); + objective.SetScore("Too", 1); player.Scoreboard = board; player.SendScoreboard(); }