From a3593b81de93acebf027497d10cd4ee7fcfbbac4 Mon Sep 17 00:00:00 2001 From: Mitchell Kutchuk Date: Sun, 21 Jun 2015 08:35:17 -0700 Subject: [PATCH 01/15] Cleanup QueryProtocol - Dispose of streams - Use ConcurrentDictionary --- TrueCraft/QueryProtocol.cs | 200 ++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 83 deletions(-) diff --git a/TrueCraft/QueryProtocol.cs b/TrueCraft/QueryProtocol.cs index 47490ef..f913799 100644 --- a/TrueCraft/QueryProtocol.cs +++ b/TrueCraft/QueryProtocol.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; @@ -19,12 +20,11 @@ namespace TrueCraft private IMultiplayerServer Server; private CancellationTokenSource CToken; - private readonly byte[] ProtocolVersion = new byte[] { 0xFE, 0xFD }; + private readonly byte[] ProtocolVersion = { 0xFE, 0xFD }; private readonly byte Type_Handshake = 0x09; private readonly byte Type_Stat = 0x00; - private Dictionary UserList; - private object UserLock = new object(); + private ConcurrentDictionary UserList; public QueryProtocol(IMultiplayerServer server) { @@ -35,6 +35,7 @@ namespace TrueCraft { Port = Program.ServerConfiguration.QueryPort; Udp = new UdpClient(Port); + UserList = new ConcurrentDictionary(); Timer = new Timer(ResetUserList, null, 0, 30000); CToken = new CancellationTokenSource(); Udp.BeginReceive(HandleReceive, null); @@ -72,80 +73,114 @@ namespace TrueCraft private void HandleHandshake(byte[] buffer, IPEndPoint clientEP) { - var stream = GetStream(buffer); - int sessionId = GetSessionId(stream); - - var user = new QueryUser { SessionId = sessionId, ChallengeToken = Rnd.Next() }; - lock (UserLock) + using (var ms = new MemoryStream(buffer)) { - if (UserList.ContainsKey(clientEP)) - UserList.Remove(clientEP); - UserList.Add(clientEP, user); + using (var stream = new BinaryReader(ms)) + { + int sessionId = GetSessionId(stream); + + var user = new QueryUser { SessionId = sessionId, ChallengeToken = Rnd.Next() }; + + if (UserList.ContainsKey(clientEP)) + { + QueryUser u; + while (!UserList.TryRemove(clientEP, out u)) + Thread.Sleep(1); + } + + UserList[clientEP] = user; + + using (var response = new MemoryStream()) + { + using (var writer = new BinaryWriter(response)) + { + WriteHead(Type_Handshake, user, writer); + WriteStringToStream(user.ChallengeToken.ToString(), ms); + + SendResponse(response.ToArray(), clientEP); + } + } + } + } - - var response = GetStream(); - WriteHead(Type_Handshake, user, response); - WriteStringToStream(user.ChallengeToken.ToString(), response.BaseStream); - - SendResponse(response, clientEP); } private void HandleBasicStat(byte[] buffer, IPEndPoint clientEP) { - var stream = GetStream(buffer); - int sessionId = GetSessionId(stream); - int token = GetToken(stream); + using (var ms = new MemoryStream(buffer)) + { + using (var stream = new BinaryReader(ms)) + { + int sessionId = GetSessionId(stream); + int token = GetToken(stream); - var user = GetUser(clientEP); - if (user.ChallengeToken != token || user.SessionId != sessionId) throw new Exception("Invalid credentials"); + var user = GetUser(clientEP); + if (user.ChallengeToken != token || user.SessionId != sessionId) throw new Exception("Invalid credentials"); - var stats = GetStats(); - var response = GetStream(); - WriteHead(Type_Stat, user, response); - WriteStringToStream(stats["hostname"], response.BaseStream); - WriteStringToStream(stats["gametype"], response.BaseStream); - WriteStringToStream(stats["numplayers"], response.BaseStream); - WriteStringToStream(stats["maxplayers"], response.BaseStream); - byte[] hostport = BitConverter.GetBytes(UInt16.Parse(stats["hostport"])); - Array.Reverse(hostport);//The specification needs little endian short - response.Write(hostport); - WriteStringToStream(stats["hostip"], response.BaseStream); + var stats = GetStats(); + using (var response = new MemoryStream()) + { + using (var writer = new BinaryWriter(response)) + { + WriteHead(Type_Stat, user, writer); + WriteStringToStream(stats["hostname"], response); + WriteStringToStream(stats["gametype"], response); + WriteStringToStream(stats["numplayers"], response); + WriteStringToStream(stats["maxplayers"], response); + byte[] hostport = BitConverter.GetBytes(ushort.Parse(stats["hostport"])); + Array.Reverse(hostport);//The specification needs little endian short + writer.Write(hostport); + WriteStringToStream(stats["hostip"], response); - SendResponse(response, clientEP); + SendResponse(response.ToArray(), clientEP); + } + } + } + } } private void HandleFullStat(byte[] buffer, IPEndPoint clientEP) { - var stream = GetStream(buffer); - int sessionId = GetSessionId(stream); - int token = GetToken(stream); - - var user = GetUser(clientEP); - if (user.ChallengeToken != token || user.SessionId != sessionId) throw new Exception("Invalid credentials"); - - var stats = GetStats(); - var response = GetStream(); - WriteHead(Type_Stat, user, response); - WriteStringToStream("SPLITNUM\0\0", response.BaseStream); - foreach (var pair in stats) + using (var stream = new MemoryStream(buffer)) { - WriteStringToStream(pair.Key, response.BaseStream); - WriteStringToStream(pair.Value, response.BaseStream); - } - response.Write((byte)0x00); - response.Write((byte)0x01); - WriteStringToStream("player_\0", response.BaseStream); - var players = GetPlayers(); - foreach (string player in players) - WriteStringToStream(player, response.BaseStream); - response.Write((byte)0x00); + using (var reader = new BinaryReader(stream)) + { + int sessionId = GetSessionId(reader); + int token = GetToken(reader); - SendResponse(response, clientEP); + var user = GetUser(clientEP); + if (user.ChallengeToken != token || user.SessionId != sessionId) throw new Exception("Invalid credentials"); + + var stats = GetStats(); + using (var response = new MemoryStream()) + { + using (var writer = new BinaryWriter(response)) + { + WriteHead(Type_Stat, user, writer); + WriteStringToStream("SPLITNUM\0\0", response); + foreach (var pair in stats) + { + WriteStringToStream(pair.Key, response); + WriteStringToStream(pair.Value, response); + } + writer.Write((byte)0x00); + writer.Write((byte)0x01); + WriteStringToStream("player_\0", response); + var players = GetPlayers(); + foreach (string player in players) + WriteStringToStream(player, response); + writer.Write((byte)0x00); + + SendResponse(response.ToArray(), clientEP); + } + } + } + } } private bool CheckVersion(byte[] ver) { - return ver[0] == ProtocolVersion[0] && ver[1] == ProtocolVersion[1]; + return ver.SequenceEqual(ProtocolVersion); } private int GetSessionId(BinaryReader stream) { @@ -157,40 +192,39 @@ namespace TrueCraft stream.BaseStream.Position = 7; return stream.ReadInt32(); } - private BinaryReader GetStream(byte[] buffer) - { return new BinaryReader(new MemoryStream(buffer)); } - private BinaryWriter GetStream() - { return new BinaryWriter(new MemoryStream()); } + private void WriteHead(byte type, QueryUser user, BinaryWriter stream) { stream.Write(type); stream.Write(user.SessionId); } - private void SendResponse(BinaryWriter res, IPEndPoint destination) + + private void SendResponse(byte[] res, IPEndPoint destination) { - byte[] data = ((MemoryStream)res.BaseStream).ToArray(); - Udp.Send(data, data.Length, destination); + Udp.Send(res, res.Length, destination); } - private QueryUser GetUser(IPEndPoint ep) + private QueryUser GetUser(IPEndPoint ipe) { - QueryUser user; - lock (UserLock) - if (!UserList.TryGetValue(ep, out user)) throw new Exception("Undefined user"); - return user; + if (!UserList.ContainsKey(ipe)) + throw new Exception("Undefined user"); + + return UserList[ipe]; } private Dictionary GetStats() { - var stats = new Dictionary(); - stats.Add("hostname", Program.ServerConfiguration.MOTD); - stats.Add("gametype", "SMP"); - stats.Add("game_id", "TRUECRAFT"); - stats.Add("version", "1.0"); - stats.Add("plugins", "TrueCraft"); - stats.Add("map", Server.Worlds.First().Name); - stats.Add("numplayers", Server.Clients.Count.ToString()); - stats.Add("maxplayers", "64"); - stats.Add("hostport", Program.ServerConfiguration.ServerPort.ToString()); - stats.Add("hostip", Program.ServerConfiguration.ServerAddress); + var stats = new Dictionary + { + {"hostname", Program.ServerConfiguration.MOTD}, + {"gametype", "SMP"}, + {"game_id", "TRUECRAFT"}, + {"version", "1.0"}, + {"plugins", "TrueCraft"}, + {"map", Server.Worlds.First().Name}, + {"numplayers", Server.Clients.Count.ToString()}, + {"maxplayers", "64"}, + {"hostport", Program.ServerConfiguration.ServerPort.ToString()}, + {"hostip", Program.ServerConfiguration.ServerAddress} + }; return stats; } private List GetPlayers() @@ -223,14 +257,14 @@ namespace TrueCraft public void Stop() { + Timer.Dispose(); CToken.Cancel(); Udp.Close(); } private void ResetUserList(object state) { - lock (UserLock) - UserList = new Dictionary(); + UserList.Clear(); } struct QueryUser From e3a022e3ba88e5284621134549396459dc2af2ba Mon Sep 17 00:00:00 2001 From: Mitchell Kutchuk Date: Sun, 21 Jun 2015 09:09:23 -0700 Subject: [PATCH 02/15] Fix QueryProtocol --- TrueCraft/QueryProtocol.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/TrueCraft/QueryProtocol.cs b/TrueCraft/QueryProtocol.cs index f913799..5fdf9c3 100644 --- a/TrueCraft/QueryProtocol.cs +++ b/TrueCraft/QueryProtocol.cs @@ -44,7 +44,7 @@ namespace TrueCraft private void HandleReceive(IAsyncResult ar) { if (CToken.IsCancellationRequested) return; - + try { var clientEP = new IPEndPoint(IPAddress.Any, Port); @@ -95,8 +95,7 @@ namespace TrueCraft using (var writer = new BinaryWriter(response)) { WriteHead(Type_Handshake, user, writer); - WriteStringToStream(user.ChallengeToken.ToString(), ms); - + WriteStringToStream(user.ChallengeToken.ToString(), response); SendResponse(response.ToArray(), clientEP); } } @@ -180,7 +179,7 @@ namespace TrueCraft private bool CheckVersion(byte[] ver) { - return ver.SequenceEqual(ProtocolVersion); + return ver[0] == ProtocolVersion[0] && ver[1] == ProtocolVersion[1]; } private int GetSessionId(BinaryReader stream) { From 655a0d71e8e0c52825c67089d1889b5657f7761a Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 16:26:09 -0400 Subject: [PATCH 03/15] Fixed issue where the client continued to reset the mouse position after losing focus --- TrueCraft.Client/TrueCraftGame.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TrueCraft.Client/TrueCraftGame.cs b/TrueCraft.Client/TrueCraftGame.cs index 8935bd6..d0be9ad 100644 --- a/TrueCraft.Client/TrueCraftGame.cs +++ b/TrueCraft.Client/TrueCraftGame.cs @@ -246,7 +246,7 @@ namespace TrueCraft.Client private void OnMouseComponentMove(object sender, MouseMoveEventArgs e) { - if (MouseCaptured) + if (MouseCaptured && IsActive) { var centerX = GraphicsDevice.Viewport.Width / 2; var centerY = GraphicsDevice.Viewport.Height / 2; From 9f7b923fbf95d8267d6e27aa280b8ec6977eef1e Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 16:30:40 -0400 Subject: [PATCH 04/15] Fixed build failure (on Windows?) due to unimplemented virtual property --- TrueCraft.Client/Rendering/FlatQuadRenderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TrueCraft.Client/Rendering/FlatQuadRenderer.cs b/TrueCraft.Client/Rendering/FlatQuadRenderer.cs index 1fffa19..66d4a36 100644 --- a/TrueCraft.Client/Rendering/FlatQuadRenderer.cs +++ b/TrueCraft.Client/Rendering/FlatQuadRenderer.cs @@ -7,7 +7,7 @@ namespace TrueCraft.Client.Rendering { public abstract class FlatQuadRenderer : BlockRenderer { - protected virtual Vector2 TextureMap { get; } + protected virtual Vector2 TextureMap { get { return Vector2.Zero; } } protected Vector2[] Texture; protected FlatQuadRenderer() From 13baea71918ee7c209c450156317e36d6c65fdfe Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 21 Jun 2015 17:36:42 -0400 Subject: [PATCH 05/15] Partially implement chests --- TrueCraft.API/TrueCraft.API.csproj | 7 +- TrueCraft.API/Windows/IWindow.cs | 1 + TrueCraft.API/packages.config | 4 + TrueCraft.Core/Logic/BlockProvider.cs | 2 +- TrueCraft.Core/Logic/Blocks/ChestBlock.cs | 97 ++++++++++++++ TrueCraft.Core/Logic/Blocks/WallSignBlock.cs | 19 +++ TrueCraft.Core/TrueCraft.Core.csproj | 1 + TrueCraft.Core/Windows/ChestWindow.cs | 126 +++++++++++++++++++ TrueCraft.Core/Windows/Window.cs | 4 +- TrueCraft/RemoteClient.cs | 2 +- TrueCraft/TrueCraft.csproj | 6 +- TrueCraft/packages.config | 2 +- 12 files changed, 263 insertions(+), 8 deletions(-) create mode 100644 TrueCraft.API/packages.config create mode 100644 TrueCraft.Core/Windows/ChestWindow.cs diff --git a/TrueCraft.API/TrueCraft.API.csproj b/TrueCraft.API/TrueCraft.API.csproj index 4000c40..52f909a 100644 --- a/TrueCraft.API/TrueCraft.API.csproj +++ b/TrueCraft.API/TrueCraft.API.csproj @@ -31,7 +31,7 @@ - ..\packages\YamlDotNet.3.5.1\lib\net35\YamlDotNet.dll + ..\packages\YamlDotNet.3.6.0\lib\net35\YamlDotNet.dll @@ -113,4 +113,7 @@ fNbt - \ No newline at end of file + + + + diff --git a/TrueCraft.API/Windows/IWindow.cs b/TrueCraft.API/Windows/IWindow.cs index 97ad635..b96c188 100644 --- a/TrueCraft.API/Windows/IWindow.cs +++ b/TrueCraft.API/Windows/IWindow.cs @@ -11,6 +11,7 @@ namespace TrueCraft.API.Windows string Name { get; } sbyte Type { get; } int Length { get; } + int MinecraftWasWrittenByFuckingIdiotsLength { get; } ItemStack this[int index] { get; set; } bool Empty { get; } diff --git a/TrueCraft.API/packages.config b/TrueCraft.API/packages.config new file mode 100644 index 0000000..c965a8b --- /dev/null +++ b/TrueCraft.API/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/TrueCraft.Core/Logic/BlockProvider.cs b/TrueCraft.Core/Logic/BlockProvider.cs index a01ba02..bfeefbe 100644 --- a/TrueCraft.Core/Logic/BlockProvider.cs +++ b/TrueCraft.Core/Logic/BlockProvider.cs @@ -99,7 +99,7 @@ namespace TrueCraft.Core.Logic coordinates += MathHelper.BlockFaceToCoordinates(face); var old = world.GetBlockData(coordinates); byte[] overwritable = - { + { AirBlock.BlockID, WaterBlock.BlockID, StationaryWaterBlock.BlockID, diff --git a/TrueCraft.Core/Logic/Blocks/ChestBlock.cs b/TrueCraft.Core/Logic/Blocks/ChestBlock.cs index 80a955a..022211c 100644 --- a/TrueCraft.Core/Logic/Blocks/ChestBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/ChestBlock.cs @@ -2,6 +2,10 @@ using System; using TrueCraft.API; using TrueCraft.Core.Logic.Items; using TrueCraft.API.Logic; +using TrueCraft.API.World; +using TrueCraft.API.Networking; +using fNbt; +using TrueCraft.Core.Windows; namespace TrueCraft.Core.Logic.Blocks { @@ -60,5 +64,98 @@ namespace TrueCraft.Core.Logic.Blocks { get { return false; } } + + private static readonly Coordinates3D[] AdjacentBlocks = + { + Coordinates3D.North, + Coordinates3D.South, + Coordinates3D.West, + Coordinates3D.East + }; + + public override void ItemUsedOnBlock(Coordinates3D coordinates, ItemStack item, BlockFace face, IWorld world, IRemoteClient user) + { + int adjacent = 0; + var coords = coordinates + MathHelper.BlockFaceToCoordinates(face); + Coordinates3D _ = Coordinates3D.Down; + // Check for adjacent chests. We can only allow one adjacent check block. + for (int i = 0; i < AdjacentBlocks.Length; i++) + { + if (world.GetBlockID(coords + AdjacentBlocks[i]) == ChestBlock.BlockID) + { + _ = coords + AdjacentBlocks[i]; + adjacent++; + } + } + if (adjacent <= 1) + { + if (_ != Coordinates3D.Down) + { + // Confirm that adjacent chest is not a double chest + for (int i = 0; i < AdjacentBlocks.Length; i++) + { + if (world.GetBlockID(_ + AdjacentBlocks[i]) == ChestBlock.BlockID) + adjacent++; + } + } + if (adjacent <= 1) + base.ItemUsedOnBlock(coordinates, item, face, world, user); + } + } + + public override void BlockPlaced(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + world.SetMetadata(descriptor.Coordinates, (byte)MathHelper.DirectionByRotationFlat(user.Entity.Yaw, true)); + } + + public override bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + bool unobstructed = true, isDouble = false; + Coordinates3D other = Coordinates3D.Down; + for (int i = 0; i < AdjacentBlocks.Length; i++) + { + if (world.GetBlockID(descriptor.Coordinates + AdjacentBlocks[i]) == ChestBlock.BlockID) + { + isDouble = true; + other = descriptor.Coordinates + AdjacentBlocks[i]; + var _ = world.BlockRepository.GetBlockProvider(world.GetBlockID( + descriptor.Coordinates + AdjacentBlocks[i] + Coordinates3D.Up)); + if (_.Opaque) + unobstructed = false; + } + } + if (world.BlockRepository.GetBlockProvider(world.GetBlockID(descriptor.Coordinates + Coordinates3D.Up)).Opaque) + unobstructed = false; + if (!unobstructed) + return false; + var entity = world.GetTileEntity(descriptor.Coordinates); + var window = new ChestWindow((InventoryWindow)user.Inventory, isDouble); + if (entity != null) + { + foreach (NbtCompound item in (NbtList)entity["Items"]) + { + var stack = ItemStack.FromNbt(item); + window.ChestInventory[stack.Index] = stack; + } + } + if (isDouble) + { + entity = world.GetTileEntity(other); + if (entity != null) + { + foreach (NbtCompound item in (NbtList)entity["Items"]) + { + var stack = ItemStack.FromNbt(item); + window.ChestInventory[stack.Index] = stack; + } + } + } + user.OpenWindow(window); + window.WindowChange += (sender, e) => + { + // TODO: Update tile entity + }; // TODO: Memory leak here + return false; + } } } \ No newline at end of file diff --git a/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs b/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs index d28ec0d..bffa96b 100644 --- a/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs @@ -4,6 +4,8 @@ using TrueCraft.API; using TrueCraft.API.World; using TrueCraft.API.Networking; using TrueCraft.Core.Logic.Items; +using TrueCraft.Core.Networking.Packets; +using fNbt; namespace TrueCraft.Core.Logic.Blocks { @@ -37,5 +39,22 @@ namespace TrueCraft.Core.Logic.Blocks { return new[] { new ItemStack(SignItem.ItemID) }; } + + public override void TileEntityLoadedForClient(BlockDescriptor descriptor, IWorld world, NbtCompound entity, IRemoteClient client) + { + client.QueuePacket(new UpdateSignPacket + { + X = descriptor.Coordinates.X, + Y = (short)descriptor.Coordinates.Y, + Z = descriptor.Coordinates.Z, + Text = new[] + { + entity["Text1"].StringValue, + entity["Text2"].StringValue, + entity["Text3"].StringValue, + entity["Text4"].StringValue + } + }); + } } } \ No newline at end of file diff --git a/TrueCraft.Core/TrueCraft.Core.csproj b/TrueCraft.Core/TrueCraft.Core.csproj index d43f54c..22f6ffd 100644 --- a/TrueCraft.Core/TrueCraft.Core.csproj +++ b/TrueCraft.Core/TrueCraft.Core.csproj @@ -318,6 +318,7 @@ + diff --git a/TrueCraft.Core/Windows/ChestWindow.cs b/TrueCraft.Core/Windows/ChestWindow.cs new file mode 100644 index 0000000..173d806 --- /dev/null +++ b/TrueCraft.Core/Windows/ChestWindow.cs @@ -0,0 +1,126 @@ +using System; +using TrueCraft.API.Windows; +using TrueCraft.Core.Windows; +using TrueCraft.API; + +namespace TrueCraft.Core.Windows +{ + public class ChestWindow : Window + { + public ChestWindow(InventoryWindow inventory, bool doubleChest = false) + { + DoubleChest = doubleChest; + if (doubleChest) + { + WindowAreas = new[] + { + new WindowArea(ChestIndex, 54, 9, 3), // Chest + new WindowArea(DoubleMainIndex, 27, 9, 3), // Main inventory + new WindowArea(DoubleHotbarIndex, 9, 9, 1) // Hotbar + }; + } + else + { + WindowAreas = new[] + { + new WindowArea(ChestIndex, 27, 9, 3), // Chest + new WindowArea(MainIndex, 27, 9, 3), // Main inventory + new WindowArea(HotbarIndex, 9, 9, 1) // Hotbar + }; + } + inventory.MainInventory.CopyTo(MainInventory); + inventory.Hotbar.CopyTo(Hotbar); + Copying = false; + inventory.WindowChange += (sender, e) => + { + if (Copying) return; + if ((e.SlotIndex >= InventoryWindow.MainIndex && e.SlotIndex < InventoryWindow.MainIndex + inventory.MainInventory.Length) + || (e.SlotIndex >= InventoryWindow.HotbarIndex && e.SlotIndex < InventoryWindow.HotbarIndex + inventory.Hotbar.Length)) + { + inventory.MainInventory.CopyTo(MainInventory); + inventory.Hotbar.CopyTo(Hotbar); + } + }; + foreach (var area in WindowAreas) + area.WindowChange += (s, e) => OnWindowChange(new WindowChangeEventArgs( + (s as WindowArea).StartIndex + e.SlotIndex, e.Value)); + } + + public const int ChestIndex = 0; + public const int MainIndex = 27; + public const int HotbarIndex = 54; + public const int DoubleMainIndex = 54; + public const int DoubleHotbarIndex = 81; + + public bool DoubleChest { get; set; } + public override IWindowArea[] WindowAreas { get; protected set; } + private bool Copying { get; set; } + + public override string Name + { + get + { + if (DoubleChest) + return "Large Chest"; + return "Chest"; + } + } + + public override sbyte Type + { + get + { + return 0; + } + } + + public IWindowArea ChestInventory + { + get + { + return WindowAreas[0]; + } + } + + public IWindowArea MainInventory + { + get + { + return WindowAreas[1]; + } + } + + public IWindowArea Hotbar + { + get + { + return WindowAreas[2]; + } + } + + public override int MinecraftWasWrittenByFuckingIdiotsLength + { + get + { + return ChestInventory.Length; + } + } + + public override void CopyToInventory(IWindow inventoryWindow) + { + var window = (InventoryWindow)inventoryWindow; + Copying = true; + MainInventory.CopyTo(window.MainInventory); + Hotbar.CopyTo(window.Hotbar); + Copying = false; + } + + protected override IWindowArea GetLinkedArea(int index, ItemStack slot) + { + if (index == 0) + return Hotbar; + else + return ChestInventory; + } + } +} \ No newline at end of file diff --git a/TrueCraft.Core/Windows/Window.cs b/TrueCraft.Core/Windows/Window.cs index ea54bd7..d56a3b0 100644 --- a/TrueCraft.Core/Windows/Window.cs +++ b/TrueCraft.Core/Windows/Window.cs @@ -70,7 +70,7 @@ namespace TrueCraft.Core.Windows throw new IndexOutOfRangeException(); } - public int Length + public virtual int Length { get { @@ -78,6 +78,8 @@ namespace TrueCraft.Core.Windows } } + public virtual int MinecraftWasWrittenByFuckingIdiotsLength { get { return Length; } } + public bool Empty { get diff --git a/TrueCraft/RemoteClient.cs b/TrueCraft/RemoteClient.cs index 227655c..ece4749 100644 --- a/TrueCraft/RemoteClient.cs +++ b/TrueCraft/RemoteClient.cs @@ -175,7 +175,7 @@ namespace TrueCraft CurrentWindow = window; window.ID = NextWindowID++; if (NextWindowID < 0) NextWindowID = 1; - QueuePacket(new OpenWindowPacket(window.ID, window.Type, window.Name, (sbyte)window.Length)); + QueuePacket(new OpenWindowPacket(window.ID, window.Type, window.Name, (sbyte)window.MinecraftWasWrittenByFuckingIdiotsLength)); QueuePacket(new WindowItemsPacket(window.ID, window.GetSlots())); } diff --git a/TrueCraft/TrueCraft.csproj b/TrueCraft/TrueCraft.csproj index ad320bb..affb812 100644 --- a/TrueCraft/TrueCraft.csproj +++ b/TrueCraft/TrueCraft.csproj @@ -14,6 +14,8 @@ false bin\Debug 4 + true + false false @@ -25,8 +27,8 @@ ..\lib\Ionic.Zip.Reduced.dll - - ..\packages\YamlDotNet.3.5.1\lib\net35\YamlDotNet.dll + + ..\packages\YamlDotNet.3.6.0\lib\net35\YamlDotNet.dll diff --git a/TrueCraft/packages.config b/TrueCraft/packages.config index 49d63fd..c965a8b 100644 --- a/TrueCraft/packages.config +++ b/TrueCraft/packages.config @@ -1,4 +1,4 @@  - + \ No newline at end of file From ef0a24bce2eb1544132b0c7ced30dd0977bef163 Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 18:27:09 -0400 Subject: [PATCH 06/15] Added cobweb renderer --- .../Rendering/Blocks/CobwebRenderer.cs | 40 +++++++++++++++++++ TrueCraft.Client/TrueCraft.Client.csproj | 3 +- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs diff --git a/TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs b/TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs new file mode 100644 index 0000000..da1a62a --- /dev/null +++ b/TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs @@ -0,0 +1,40 @@ +using System; +using TrueCraft.Core.Logic.Blocks; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using TrueCraft.API.Logic; + +namespace TrueCraft.Client.Rendering.Blocks +{ + public class CobwebRenderer : FlatQuadRenderer + { + static CobwebRenderer() + { + BlockRenderer.RegisterRenderer(CobwebBlock.BlockID, new CobwebRenderer()); + } + + protected Vector2 CobwebTextureMap { get { return new Vector2(11, 0); } } + protected Vector2[] CobwebTexture; + + public CobwebRenderer() + { + CobwebTexture = new[] + { + CobwebTextureMap + Vector2.UnitX + Vector2.UnitY, + CobwebTextureMap + Vector2.UnitY, + CobwebTextureMap, + CobwebTextureMap + Vector2.UnitX, + }; + for (int i = 0; i < Texture.Length; i++) + { + CobwebTexture[i] *= new Vector2(16f / 256f); + } + } + + public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset, + Tuple textureMap, int indiciesOffset, out int[] indicies) + { + return RenderQuads(descriptor, offset, CobwebTexture, indiciesOffset, out indicies, Color.White); + } + } +} diff --git a/TrueCraft.Client/TrueCraft.Client.csproj b/TrueCraft.Client/TrueCraft.Client.csproj index 6c8e685..acf12a3 100644 --- a/TrueCraft.Client/TrueCraft.Client.csproj +++ b/TrueCraft.Client/TrueCraft.Client.csproj @@ -67,6 +67,7 @@ + @@ -178,4 +179,4 @@ PreserveNewest - + \ No newline at end of file From 88ed21639e98b063d9ef8df53dec385c15cb20e8 Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 18:36:02 -0400 Subject: [PATCH 07/15] Simplified cobweb renderer --- .../Rendering/Blocks/CobwebRenderer.cs | 24 +------------------ 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs b/TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs index da1a62a..5f70848 100644 --- a/TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs +++ b/TrueCraft.Client/Rendering/Blocks/CobwebRenderer.cs @@ -13,28 +13,6 @@ namespace TrueCraft.Client.Rendering.Blocks BlockRenderer.RegisterRenderer(CobwebBlock.BlockID, new CobwebRenderer()); } - protected Vector2 CobwebTextureMap { get { return new Vector2(11, 0); } } - protected Vector2[] CobwebTexture; - - public CobwebRenderer() - { - CobwebTexture = new[] - { - CobwebTextureMap + Vector2.UnitX + Vector2.UnitY, - CobwebTextureMap + Vector2.UnitY, - CobwebTextureMap, - CobwebTextureMap + Vector2.UnitX, - }; - for (int i = 0; i < Texture.Length; i++) - { - CobwebTexture[i] *= new Vector2(16f / 256f); - } - } - - public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset, - Tuple textureMap, int indiciesOffset, out int[] indicies) - { - return RenderQuads(descriptor, offset, CobwebTexture, indiciesOffset, out indicies, Color.White); - } + protected override Vector2 TextureMap { get { return new Vector2(11, 0); } } } } From 1c340d25f7f9eebecb669d6664abbe9703df4140 Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 19:26:58 -0400 Subject: [PATCH 08/15] Added slab renderer --- .../Rendering/Blocks/SlabRenderer.cs | 175 ++++++++++++++++++ TrueCraft.Client/TrueCraft.Client.csproj | 1 + 2 files changed, 176 insertions(+) create mode 100644 TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs diff --git a/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs new file mode 100644 index 0000000..2205521 --- /dev/null +++ b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs @@ -0,0 +1,175 @@ +using System; +using TrueCraft.Core.Logic.Blocks; +using Microsoft.Xna.Framework; +using Microsoft.Xna.Framework.Graphics; +using TrueCraft.API.Logic; + +namespace TrueCraft.Client.Rendering.Blocks +{ + public class SlabRenderer : BlockRenderer + { + static SlabRenderer() + { + BlockRenderer.RegisterRenderer(StoneSlabBlock.BlockID, new SlabRenderer()); + BlockRenderer.RegisterRenderer(DoubleStoneSlabBlock.BlockID, new SlabRenderer()); + } + + public enum SlabType : byte + { + Stone = 0, + Sandstone = 1, + Wood =2, + Cobblestone = 3 + } + + protected virtual Vector2 GetSideTexture(SlabType type) + { + switch (type) + { + case SlabType.Stone: + return new Vector2(5, 0); + + case SlabType.Sandstone: + return new Vector2(0, 12); + + case SlabType.Wood: + return new Vector2(4, 0); + + case SlabType.Cobblestone: + return new Vector2(1, 0); + + default: + return Vector2.Zero; + } + } + + protected virtual Vector2 GetTopTexture(SlabType type) + { + switch (type) + { + case SlabType.Stone: + return new Vector2(6, 0); + + case SlabType.Sandstone: + return new Vector2(0, 13); + + case SlabType.Wood: + return new Vector2(4, 0); + + case SlabType.Cobblestone: + return new Vector2(1, 0); + + default: + return Vector2.Zero; + } + } + + protected virtual Vector2 GetBottomTexture(SlabType type) + { + switch (type) + { + case SlabType.Stone: + return new Vector2(6, 0); + + case SlabType.Sandstone: + return new Vector2(0, 14); + + case SlabType.Wood: + return new Vector2(4, 0); + + case SlabType.Cobblestone: + return new Vector2(1, 0); + + default: + return Vector2.Zero; + } + } + + protected virtual Vector2[] GetTextureMap(SlabType type, bool isDouble) + { + var sideTexture = GetSideTexture(type); + var topTexture = GetTopTexture(type); + var bottomTexture = GetBottomTexture(type); + + var result = new Vector2[] + { + // Positive Z + sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture, + sideTexture + Vector2.UnitX, + // Negative Z + sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture, + sideTexture + Vector2.UnitX, + // Positive X + sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture, + sideTexture + Vector2.UnitX, + // Negative X + sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), + sideTexture, + sideTexture + Vector2.UnitX, + // Positive Y + topTexture + Vector2.UnitX + Vector2.UnitY, + topTexture + Vector2.UnitY, + topTexture, + topTexture + Vector2.UnitX, + // Negative Y + bottomTexture + Vector2.UnitX + Vector2.UnitY, + bottomTexture + Vector2.UnitY, + bottomTexture, + bottomTexture + Vector2.UnitX + }; + + for (int i = 0; i < result.Length; i++) + result[i] *= new Vector2(16f / 256f); + + return result; + } + + public static int Value = 0; + + public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset, Tuple textureMap, int indiciesOffset, out int[] indicies) + { + if (descriptor.ID == StoneSlabBlock.BlockID) + return RenderSlab(descriptor, offset, textureMap, indiciesOffset, out indicies); + else + return RenderDoubleSlab(descriptor, offset, textureMap, indiciesOffset, out indicies); + } + + protected virtual VertexPositionNormalColorTexture[] RenderSlab(BlockDescriptor descriptor, Vector3 offset, Tuple textureMap, int indiciesOffset, out int[] indicies) + { + var result = CreateUniformCube(offset, GetTextureMap((SlabType)descriptor.Metadata, false), indiciesOffset, out indicies, Color.White); + for (int i = 0; i < 6; i++) + { + var face = (CubeFace)i; + switch(face) + { + case CubeFace.PositiveZ: + case CubeFace.NegativeZ: + case CubeFace.PositiveX: + case CubeFace.NegativeX: + for (int j = 2; j < 4; j++) + result[(i * 4) + j].Position.Y -= 0.5f; + break; + + case CubeFace.PositiveY: + for (int j = 0; j < 4; j++) + result[(i * 4) + j].Position.Y -= 0.5f; + break; + } + } + + return result; + } + + protected virtual VertexPositionNormalColorTexture[] RenderDoubleSlab(BlockDescriptor descriptor, Vector3 offset, Tuple textureMap, int indiciesOffset, out int[] indicies) + { + return CreateUniformCube(offset, GetTextureMap((SlabType)descriptor.Metadata, true), indiciesOffset, out indicies, Color.White); + } + } +} diff --git a/TrueCraft.Client/TrueCraft.Client.csproj b/TrueCraft.Client/TrueCraft.Client.csproj index acf12a3..6cafb2f 100644 --- a/TrueCraft.Client/TrueCraft.Client.csproj +++ b/TrueCraft.Client/TrueCraft.Client.csproj @@ -68,6 +68,7 @@ + From 9e61bb9a981120e67dee504be6b0837f03634d87 Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 19:52:47 -0400 Subject: [PATCH 09/15] Renamed StoneSlabBlock to SlabBlock --- .../Logic/Blocks/{StoneSlabBlock.cs => SlabBlock.cs} | 6 +++--- TrueCraft.Core/TrueCraft.Core.csproj | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) rename TrueCraft.Core/Logic/Blocks/{StoneSlabBlock.cs => SlabBlock.cs} (96%) diff --git a/TrueCraft.Core/Logic/Blocks/StoneSlabBlock.cs b/TrueCraft.Core/Logic/Blocks/SlabBlock.cs similarity index 96% rename from TrueCraft.Core/Logic/Blocks/StoneSlabBlock.cs rename to TrueCraft.Core/Logic/Blocks/SlabBlock.cs index ea6c36a..5d75725 100644 --- a/TrueCraft.Core/Logic/Blocks/StoneSlabBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/SlabBlock.cs @@ -4,7 +4,7 @@ using TrueCraft.API; namespace TrueCraft.Core.Logic.Blocks { - public class StoneSlabBlock : BlockProvider + public class SlabBlock : BlockProvider { public enum SlabMaterial { @@ -120,9 +120,9 @@ namespace TrueCraft.Core.Logic.Blocks } } - public class DoubleStoneSlabBlock : BlockProvider + public class DoubleSlabBlock : SlabBlock { - public static readonly byte BlockID = 0x2B; + public static readonly new byte BlockID = 0x2B; public override byte ID { get { return 0x2B; } } diff --git a/TrueCraft.Core/TrueCraft.Core.csproj b/TrueCraft.Core/TrueCraft.Core.csproj index d43f54c..bdcbda5 100644 --- a/TrueCraft.Core/TrueCraft.Core.csproj +++ b/TrueCraft.Core/TrueCraft.Core.csproj @@ -298,7 +298,7 @@ - + From f60f65458e2fe6fc3e6a6fb00b5d4fc99850c1d8 Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 19:53:04 -0400 Subject: [PATCH 10/15] Implemented static texture maps --- .../Rendering/Blocks/SlabRenderer.cs | 294 +++++++++++------- 1 file changed, 177 insertions(+), 117 deletions(-) diff --git a/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs index 2205521..93ab160 100644 --- a/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs +++ b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs @@ -8,134 +8,189 @@ namespace TrueCraft.Client.Rendering.Blocks { public class SlabRenderer : BlockRenderer { + private static Vector2 StoneTopTexture = new Vector2(6, 0); + private static Vector2 StoneSideTexture = new Vector2(5, 0); + private static Vector2 StoneBottomTexture = new Vector2(6, 0); + private static Vector2 SandstoneTopTexture = new Vector2(0, 13); + private static Vector2 SandstoneSideTexture = new Vector2(0, 12); + private static Vector2 SandstoneBottomTexture = new Vector2(0, 14); + private static Vector2 WoodTopTexture = new Vector2(4, 0); + private static Vector2 WoodSideTexture = new Vector2(4, 0); + private static Vector2 WoodBottomTexture = new Vector2(4, 0); + private static Vector2 CobbleTopTexture = new Vector2(1, 0); + private static Vector2 CobbleSideTexture = new Vector2(1, 0); + private static Vector2 CobbleBottomTexture = new Vector2(1, 0); + + private static Vector2[] StoneTextureMap = + { + // Positive Z + StoneSideTexture + Vector2.UnitX + Vector2.UnitY, + StoneSideTexture + Vector2.UnitY, + StoneSideTexture, + StoneSideTexture + Vector2.UnitX, + // Negative Z + StoneSideTexture + Vector2.UnitX + Vector2.UnitY, + StoneSideTexture + Vector2.UnitY, + StoneSideTexture, + StoneSideTexture + Vector2.UnitX, + // Positive X + StoneSideTexture + Vector2.UnitX + Vector2.UnitY, + StoneSideTexture + Vector2.UnitY, + StoneSideTexture, + StoneSideTexture + Vector2.UnitX, + // Negative X + StoneSideTexture + Vector2.UnitX + Vector2.UnitY, + StoneSideTexture + Vector2.UnitY, + StoneSideTexture, + StoneSideTexture + Vector2.UnitX, + // Negative Y + StoneTopTexture + Vector2.UnitX + Vector2.UnitY, + StoneTopTexture + Vector2.UnitY, + StoneTopTexture, + StoneTopTexture + Vector2.UnitX, + // Negative Y + StoneBottomTexture + Vector2.UnitX + Vector2.UnitY, + StoneBottomTexture + Vector2.UnitY, + StoneBottomTexture, + StoneBottomTexture + Vector2.UnitX, + }; + + private static Vector2[] SandstoneTextureMap = + { + // Positive Z + SandstoneSideTexture + Vector2.UnitX + Vector2.UnitY, + SandstoneSideTexture + Vector2.UnitY, + SandstoneSideTexture, + SandstoneSideTexture + Vector2.UnitX, + // Negative Z + SandstoneSideTexture + Vector2.UnitX + Vector2.UnitY, + SandstoneSideTexture + Vector2.UnitY, + SandstoneSideTexture, + SandstoneSideTexture + Vector2.UnitX, + // Positive X + SandstoneSideTexture + Vector2.UnitX + Vector2.UnitY, + SandstoneSideTexture + Vector2.UnitY, + SandstoneSideTexture, + SandstoneSideTexture + Vector2.UnitX, + // Negative X + SandstoneSideTexture + Vector2.UnitX + Vector2.UnitY, + SandstoneSideTexture + Vector2.UnitY, + SandstoneSideTexture, + SandstoneSideTexture + Vector2.UnitX, + // Negative Y + SandstoneTopTexture + Vector2.UnitX + Vector2.UnitY, + SandstoneTopTexture + Vector2.UnitY, + SandstoneTopTexture, + SandstoneTopTexture + Vector2.UnitX, + // Negative Y + SandstoneBottomTexture + Vector2.UnitX + Vector2.UnitY, + SandstoneBottomTexture + Vector2.UnitY, + SandstoneBottomTexture, + SandstoneBottomTexture + Vector2.UnitX, + }; + + private static Vector2[] WoodTextureMap = + { + // Positive Z + WoodSideTexture + Vector2.UnitX + Vector2.UnitY, + WoodSideTexture + Vector2.UnitY, + WoodSideTexture, + WoodSideTexture + Vector2.UnitX, + // Negative Z + WoodSideTexture + Vector2.UnitX + Vector2.UnitY, + WoodSideTexture + Vector2.UnitY, + WoodSideTexture, + WoodSideTexture + Vector2.UnitX, + // Positive X + WoodSideTexture + Vector2.UnitX + Vector2.UnitY, + WoodSideTexture + Vector2.UnitY, + WoodSideTexture, + WoodSideTexture + Vector2.UnitX, + // Negative X + WoodSideTexture + Vector2.UnitX + Vector2.UnitY, + WoodSideTexture + Vector2.UnitY, + WoodSideTexture, + WoodSideTexture + Vector2.UnitX, + // Negative Y + WoodTopTexture + Vector2.UnitX + Vector2.UnitY, + WoodTopTexture + Vector2.UnitY, + WoodTopTexture, + WoodTopTexture + Vector2.UnitX, + // Negative Y + WoodBottomTexture + Vector2.UnitX + Vector2.UnitY, + WoodBottomTexture + Vector2.UnitY, + WoodBottomTexture, + WoodBottomTexture + Vector2.UnitX, + }; + + private static Vector2[] CobbleTextureMap = + { + // Positive Z + CobbleSideTexture + Vector2.UnitX + Vector2.UnitY, + CobbleSideTexture + Vector2.UnitY, + CobbleSideTexture, + CobbleSideTexture + Vector2.UnitX, + // Negative Z + CobbleSideTexture + Vector2.UnitX + Vector2.UnitY, + CobbleSideTexture + Vector2.UnitY, + CobbleSideTexture, + CobbleSideTexture + Vector2.UnitX, + // Positive X + CobbleSideTexture + Vector2.UnitX + Vector2.UnitY, + CobbleSideTexture + Vector2.UnitY, + CobbleSideTexture, + CobbleSideTexture + Vector2.UnitX, + // Negative X + CobbleSideTexture + Vector2.UnitX + Vector2.UnitY, + CobbleSideTexture + Vector2.UnitY, + CobbleSideTexture, + CobbleSideTexture + Vector2.UnitX, + // Negative Y + CobbleTopTexture + Vector2.UnitX + Vector2.UnitY, + CobbleTopTexture + Vector2.UnitY, + CobbleTopTexture, + CobbleTopTexture + Vector2.UnitX, + // Negative Y + CobbleBottomTexture + Vector2.UnitX + Vector2.UnitY, + CobbleBottomTexture + Vector2.UnitY, + CobbleBottomTexture, + CobbleBottomTexture + Vector2.UnitX, + }; + static SlabRenderer() { - BlockRenderer.RegisterRenderer(StoneSlabBlock.BlockID, new SlabRenderer()); - BlockRenderer.RegisterRenderer(DoubleStoneSlabBlock.BlockID, new SlabRenderer()); - } + BlockRenderer.RegisterRenderer(SlabBlock.BlockID, new SlabRenderer()); + BlockRenderer.RegisterRenderer(DoubleSlabBlock.BlockID, new SlabRenderer()); - public enum SlabType : byte - { - Stone = 0, - Sandstone = 1, - Wood =2, - Cobblestone = 3 - } - - protected virtual Vector2 GetSideTexture(SlabType type) - { - switch (type) + for (int i = 0; i < StoneTextureMap.Length; i++) { - case SlabType.Stone: - return new Vector2(5, 0); - - case SlabType.Sandstone: - return new Vector2(0, 12); - - case SlabType.Wood: - return new Vector2(4, 0); - - case SlabType.Cobblestone: - return new Vector2(1, 0); - - default: - return Vector2.Zero; + StoneTextureMap[i] *= new Vector2(16f / 256f); + SandstoneTextureMap[i] *= new Vector2(16f / 256f); + WoodTextureMap[i] *= new Vector2(16f / 256f); + CobbleTextureMap[i] *= new Vector2(16f / 256f); } } - protected virtual Vector2 GetTopTexture(SlabType type) + protected virtual Vector2[] GetTextureMap(SlabBlock.SlabMaterial material) { - switch (type) + switch (material) { - case SlabType.Stone: - return new Vector2(6, 0); - - case SlabType.Sandstone: - return new Vector2(0, 13); - - case SlabType.Wood: - return new Vector2(4, 0); - - case SlabType.Cobblestone: - return new Vector2(1, 0); - + case SlabBlock.SlabMaterial.Stone: + return StoneTextureMap; + case SlabBlock.SlabMaterial.Standstone: + return SandstoneTextureMap; + case SlabBlock.SlabMaterial.Wooden: + return WoodTextureMap; + case SlabBlock.SlabMaterial.Cobblestone: + return CobbleTextureMap; default: - return Vector2.Zero; + return null; } } - protected virtual Vector2 GetBottomTexture(SlabType type) - { - switch (type) - { - case SlabType.Stone: - return new Vector2(6, 0); - - case SlabType.Sandstone: - return new Vector2(0, 14); - - case SlabType.Wood: - return new Vector2(4, 0); - - case SlabType.Cobblestone: - return new Vector2(1, 0); - - default: - return Vector2.Zero; - } - } - - protected virtual Vector2[] GetTextureMap(SlabType type, bool isDouble) - { - var sideTexture = GetSideTexture(type); - var topTexture = GetTopTexture(type); - var bottomTexture = GetBottomTexture(type); - - var result = new Vector2[] - { - // Positive Z - sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture, - sideTexture + Vector2.UnitX, - // Negative Z - sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture, - sideTexture + Vector2.UnitX, - // Positive X - sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture, - sideTexture + Vector2.UnitX, - // Negative X - sideTexture + Vector2.UnitX + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture + ((isDouble) ? Vector2.UnitY : Vector2.UnitY / 2), - sideTexture, - sideTexture + Vector2.UnitX, - // Positive Y - topTexture + Vector2.UnitX + Vector2.UnitY, - topTexture + Vector2.UnitY, - topTexture, - topTexture + Vector2.UnitX, - // Negative Y - bottomTexture + Vector2.UnitX + Vector2.UnitY, - bottomTexture + Vector2.UnitY, - bottomTexture, - bottomTexture + Vector2.UnitX - }; - - for (int i = 0; i < result.Length; i++) - result[i] *= new Vector2(16f / 256f); - - return result; - } - - public static int Value = 0; - public override VertexPositionNormalColorTexture[] Render(BlockDescriptor descriptor, Vector3 offset, Tuple textureMap, int indiciesOffset, out int[] indicies) { - if (descriptor.ID == StoneSlabBlock.BlockID) + if (descriptor.ID == SlabBlock.BlockID) return RenderSlab(descriptor, offset, textureMap, indiciesOffset, out indicies); else return RenderDoubleSlab(descriptor, offset, textureMap, indiciesOffset, out indicies); @@ -143,7 +198,7 @@ namespace TrueCraft.Client.Rendering.Blocks protected virtual VertexPositionNormalColorTexture[] RenderSlab(BlockDescriptor descriptor, Vector3 offset, Tuple textureMap, int indiciesOffset, out int[] indicies) { - var result = CreateUniformCube(offset, GetTextureMap((SlabType)descriptor.Metadata, false), indiciesOffset, out indicies, Color.White); + var result = CreateUniformCube(offset, GetTextureMap((SlabBlock.SlabMaterial)descriptor.Metadata), indiciesOffset, out indicies, Color.White); for (int i = 0; i < 6; i++) { var face = (CubeFace)i; @@ -153,8 +208,13 @@ namespace TrueCraft.Client.Rendering.Blocks case CubeFace.NegativeZ: case CubeFace.PositiveX: case CubeFace.NegativeX: - for (int j = 2; j < 4; j++) - result[(i * 4) + j].Position.Y -= 0.5f; + for (int j = 0; j < 2; j++) + result[(i * 4) + j].Texture.Y -= (1f / 32f); + for (int k = 2; k < 4; k++) + { + result[(i * 4) + k].Position.Y -= 0.5f; + // result[(i * 4) + k].Texture.Y -= (1f / 16f); + } break; case CubeFace.PositiveY: @@ -169,7 +229,7 @@ namespace TrueCraft.Client.Rendering.Blocks protected virtual VertexPositionNormalColorTexture[] RenderDoubleSlab(BlockDescriptor descriptor, Vector3 offset, Tuple textureMap, int indiciesOffset, out int[] indicies) { - return CreateUniformCube(offset, GetTextureMap((SlabType)descriptor.Metadata, true), indiciesOffset, out indicies, Color.White); + return CreateUniformCube(offset, GetTextureMap((SlabBlock.SlabMaterial)descriptor.Metadata), indiciesOffset, out indicies, Color.White); } } } From 1633d214c1f92bb4d56cdc1641e8e8c19b55c324 Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 19:57:12 -0400 Subject: [PATCH 11/15] Don't crash when block values are invalid --- TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs index 93ab160..06fc728 100644 --- a/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs +++ b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs @@ -184,7 +184,7 @@ namespace TrueCraft.Client.Rendering.Blocks case SlabBlock.SlabMaterial.Cobblestone: return CobbleTextureMap; default: - return null; + return StoneTextureMap; } } From ef69c85038e5b1368792a292696eada22c2c5a7e Mon Sep 17 00:00:00 2001 From: William Moorehouse Date: Sun, 21 Jun 2015 20:02:10 -0400 Subject: [PATCH 12/15] Fixed cobble and stone textures being mixed up --- TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs index 06fc728..f163000 100644 --- a/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs +++ b/TrueCraft.Client/Rendering/Blocks/SlabRenderer.cs @@ -17,9 +17,9 @@ namespace TrueCraft.Client.Rendering.Blocks private static Vector2 WoodTopTexture = new Vector2(4, 0); private static Vector2 WoodSideTexture = new Vector2(4, 0); private static Vector2 WoodBottomTexture = new Vector2(4, 0); - private static Vector2 CobbleTopTexture = new Vector2(1, 0); - private static Vector2 CobbleSideTexture = new Vector2(1, 0); - private static Vector2 CobbleBottomTexture = new Vector2(1, 0); + private static Vector2 CobbleTopTexture = new Vector2(0, 1); + private static Vector2 CobbleSideTexture = new Vector2(0, 1); + private static Vector2 CobbleBottomTexture = new Vector2(0, 1); private static Vector2[] StoneTextureMap = { From 1bd30910660b365af8df9997f0d8d6d67f2c2dad Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 21 Jun 2015 21:55:41 -0400 Subject: [PATCH 13/15] Refactor chest code, implement storage persistence --- TrueCraft.Core/Logic/Blocks/ChestBlock.cs | 101 ++++++++++++++++------ TrueCraft.Core/Windows/ChestWindow.cs | 1 + TrueCraft.Core/World/Chunk.cs | 2 - 3 files changed, 75 insertions(+), 29 deletions(-) diff --git a/TrueCraft.Core/Logic/Blocks/ChestBlock.cs b/TrueCraft.Core/Logic/Blocks/ChestBlock.cs index 022211c..7aabd61 100644 --- a/TrueCraft.Core/Logic/Blocks/ChestBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/ChestBlock.cs @@ -110,51 +110,98 @@ namespace TrueCraft.Core.Logic.Blocks public override bool BlockRightClicked(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) { - bool unobstructed = true, isDouble = false; - Coordinates3D other = Coordinates3D.Down; + var adjacent = -Coordinates3D.One; // -1, no adjacent chest + var self = descriptor.Coordinates; for (int i = 0; i < AdjacentBlocks.Length; i++) { - if (world.GetBlockID(descriptor.Coordinates + AdjacentBlocks[i]) == ChestBlock.BlockID) + var test = self + AdjacentBlocks[i]; + if (world.GetBlockID(test) == ChestBlock.BlockID) { - isDouble = true; - other = descriptor.Coordinates + AdjacentBlocks[i]; - var _ = world.BlockRepository.GetBlockProvider(world.GetBlockID( - descriptor.Coordinates + AdjacentBlocks[i] + Coordinates3D.Up)); - if (_.Opaque) - unobstructed = false; + adjacent = test; + var up = world.BlockRepository.GetBlockProvider(world.GetBlockID(test + Coordinates3D.Up)); + if (up.Opaque) + return false; // Obstructed + break; } } - if (world.BlockRepository.GetBlockProvider(world.GetBlockID(descriptor.Coordinates + Coordinates3D.Up)).Opaque) - unobstructed = false; - if (!unobstructed) - return false; - var entity = world.GetTileEntity(descriptor.Coordinates); - var window = new ChestWindow((InventoryWindow)user.Inventory, isDouble); + var upSelf = world.BlockRepository.GetBlockProvider(world.GetBlockID(self + Coordinates3D.Up)); + if (upSelf.Opaque) + return false; // Obstructed + + if (adjacent != -Coordinates3D.One) + { + // Ensure that chests are always opened in the same arrangement + if (adjacent.X < self.X || + adjacent.Z < self.Z) + { + var _ = adjacent; + adjacent = self; + self = _; // Swap + } + } + + var window = new ChestWindow((InventoryWindow)user.Inventory, adjacent != -Coordinates3D.One); + // Add items + var entity = world.GetTileEntity(self); if (entity != null) { - foreach (NbtCompound item in (NbtList)entity["Items"]) + foreach (var item in (NbtList)entity["Items"]) { - var stack = ItemStack.FromNbt(item); - window.ChestInventory[stack.Index] = stack; + var slot = ItemStack.FromNbt((NbtCompound)item); + window.ChestInventory[slot.Index] = slot; } } - if (isDouble) + // Add adjacent items + if (adjacent != -Coordinates3D.One) { - entity = world.GetTileEntity(other); + entity = world.GetTileEntity(adjacent); if (entity != null) { - foreach (NbtCompound item in (NbtList)entity["Items"]) + foreach (var item in (NbtList)entity["Items"]) { - var stack = ItemStack.FromNbt(item); - window.ChestInventory[stack.Index] = stack; + var slot = ItemStack.FromNbt((NbtCompound)item); + window.ChestInventory[slot.Index + ChestWindow.DoubleChestSecondaryIndex] = slot; } } } - user.OpenWindow(window); window.WindowChange += (sender, e) => - { - // TODO: Update tile entity - }; // TODO: Memory leak here + { + var entitySelf = new NbtList("Items", NbtTagType.Compound); + var entityAdjacent = new NbtList("Items", NbtTagType.Compound); + for (int i = 0; i < window.ChestInventory.Items.Length; i++) + { + var item = window.ChestInventory.Items[i]; + if (!item.Empty) + { + if (i < ChestWindow.DoubleChestSecondaryIndex) + { + item.Index = i; + entitySelf.Add(item.ToNbt()); + } + else + { + item.Index = i - ChestWindow.DoubleChestSecondaryIndex; + entityAdjacent.Add(item.ToNbt()); + } + } + } + var newEntity = world.GetTileEntity(self); + if (newEntity == null) + newEntity = new NbtCompound(new[] { entitySelf }); + else + newEntity["Items"] = entitySelf; + world.SetTileEntity(self, newEntity); + if (adjacent != -Coordinates3D.One) + { + newEntity = world.GetTileEntity(adjacent); + if (newEntity == null) + newEntity = new NbtCompound(new[] { entityAdjacent }); + else + newEntity["Items"] = entityAdjacent; + world.SetTileEntity(adjacent, newEntity); + } + }; // TODO: Memory leak here, make windows implement IDisposable + user.OpenWindow(window); return false; } } diff --git a/TrueCraft.Core/Windows/ChestWindow.cs b/TrueCraft.Core/Windows/ChestWindow.cs index 173d806..5419d01 100644 --- a/TrueCraft.Core/Windows/ChestWindow.cs +++ b/TrueCraft.Core/Windows/ChestWindow.cs @@ -47,6 +47,7 @@ namespace TrueCraft.Core.Windows } public const int ChestIndex = 0; + public const int DoubleChestSecondaryIndex = 27; public const int MainIndex = 27; public const int HotbarIndex = 54; public const int DoubleMainIndex = 54; diff --git a/TrueCraft.Core/World/Chunk.cs b/TrueCraft.Core/World/Chunk.cs index 9e1539d..4217ea2 100644 --- a/TrueCraft.Core/World/Chunk.cs +++ b/TrueCraft.Core/World/Chunk.cs @@ -12,8 +12,6 @@ namespace TrueCraft.Core.World { public const int Width = 16, Height = 128, Depth = 16; - private static readonly NbtSerializer Serializer = new NbtSerializer(typeof(Chunk)); - [NbtIgnore] public DateTime LastAccessed { get; set; } [NbtIgnore] From 7673bbaf468b668262a4a6706231fbd2da6da735 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 22 Jun 2015 10:38:12 -0400 Subject: [PATCH 14/15] Make chests drop inventory when mined This also fixes a bug where a chest, when removed and replaced, would have the same inventory. Also adds validation on update sign packets to make sure it is indeed a sign they are updating. --- TrueCraft.Core/Logic/Blocks/ChestBlock.cs | 19 +++++++++++++ .../Logic/Blocks/UprightSignBlock.cs | 6 ++++ TrueCraft.Core/Logic/Blocks/WallSignBlock.cs | 28 +++++++++++-------- TrueCraft.Core/World/Chunk.cs | 5 +++- TrueCraft/Handlers/InteractionHandlers.cs | 21 +++++++++----- 5 files changed, 60 insertions(+), 19 deletions(-) diff --git a/TrueCraft.Core/Logic/Blocks/ChestBlock.cs b/TrueCraft.Core/Logic/Blocks/ChestBlock.cs index 7aabd61..17fa7fb 100644 --- a/TrueCraft.Core/Logic/Blocks/ChestBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/ChestBlock.cs @@ -6,6 +6,8 @@ using TrueCraft.API.World; using TrueCraft.API.Networking; using fNbt; using TrueCraft.Core.Windows; +using System.Collections.Generic; +using TrueCraft.Core.Entities; namespace TrueCraft.Core.Logic.Blocks { @@ -204,5 +206,22 @@ namespace TrueCraft.Core.Logic.Blocks user.OpenWindow(window); return false; } + + public override void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + var self = descriptor.Coordinates; + var entity = world.GetTileEntity(self); + var manager = user.Server.GetEntityManagerForWorld(world); + if (entity != null) + { + foreach (var item in (NbtList)entity["Items"]) + { + var slot = ItemStack.FromNbt((NbtCompound)item); + manager.SpawnEntity(new ItemEntity(descriptor.Coordinates + new Vector3(0.5), slot)); + } + } + world.SetTileEntity(self, null); + base.BlockMined(descriptor, face, world, user); + } } } \ No newline at end of file diff --git a/TrueCraft.Core/Logic/Blocks/UprightSignBlock.cs b/TrueCraft.Core/Logic/Blocks/UprightSignBlock.cs index 23b29f2..84ee780 100644 --- a/TrueCraft.Core/Logic/Blocks/UprightSignBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/UprightSignBlock.cs @@ -44,6 +44,12 @@ namespace TrueCraft.Core.Logic.Blocks return new[] { new ItemStack(SignItem.ItemID) }; } + public override void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + world.SetTileEntity(descriptor.Coordinates, null); + base.BlockMined(descriptor, face, world, user); + } + public override void TileEntityLoadedForClient(BlockDescriptor descriptor, IWorld world, NbtCompound entity, IRemoteClient client) { client.QueuePacket(new UpdateSignPacket diff --git a/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs b/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs index bffa96b..be084fd 100644 --- a/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs +++ b/TrueCraft.Core/Logic/Blocks/WallSignBlock.cs @@ -40,21 +40,27 @@ namespace TrueCraft.Core.Logic.Blocks return new[] { new ItemStack(SignItem.ItemID) }; } + public override void BlockMined(BlockDescriptor descriptor, BlockFace face, IWorld world, IRemoteClient user) + { + world.SetTileEntity(descriptor.Coordinates, null); + base.BlockMined(descriptor, face, world, user); + } + public override void TileEntityLoadedForClient(BlockDescriptor descriptor, IWorld world, NbtCompound entity, IRemoteClient client) { client.QueuePacket(new UpdateSignPacket + { + X = descriptor.Coordinates.X, + Y = (short)descriptor.Coordinates.Y, + Z = descriptor.Coordinates.Z, + Text = new[] { - X = descriptor.Coordinates.X, - Y = (short)descriptor.Coordinates.Y, - Z = descriptor.Coordinates.Z, - Text = new[] - { - entity["Text1"].StringValue, - entity["Text2"].StringValue, - entity["Text3"].StringValue, - entity["Text4"].StringValue - } - }); + entity["Text1"].StringValue, + entity["Text2"].StringValue, + entity["Text3"].StringValue, + entity["Text4"].StringValue + } + }); } } } \ No newline at end of file diff --git a/TrueCraft.Core/World/Chunk.cs b/TrueCraft.Core/World/Chunk.cs index 4217ea2..745b2f1 100644 --- a/TrueCraft.Core/World/Chunk.cs +++ b/TrueCraft.Core/World/Chunk.cs @@ -177,7 +177,10 @@ namespace TrueCraft.Core.World /// public void SetTileEntity(Coordinates3D coordinates, NbtCompound value) { - TileEntities[coordinates] = value; + if (value == null && TileEntities.ContainsKey(coordinates)) + TileEntities.Remove(coordinates); + else + TileEntities[coordinates] = value; IsModified = true; } diff --git a/TrueCraft/Handlers/InteractionHandlers.cs b/TrueCraft/Handlers/InteractionHandlers.cs index c3c7db2..4fa58ac 100644 --- a/TrueCraft/Handlers/InteractionHandlers.cs +++ b/TrueCraft/Handlers/InteractionHandlers.cs @@ -9,6 +9,8 @@ using TrueCraft.Core.Windows; using TrueCraft.API.Logic; using TrueCraft.Core.Entities; using fNbt; +using TrueCraft.Core.Logic.Blocks; +using System.Linq; namespace TrueCraft.Handlers { @@ -286,14 +288,19 @@ namespace TrueCraft.Handlers var coords = new Coordinates3D(packet.X, packet.Y, packet.Z); if (client.Entity.Position.DistanceTo(coords) < 10) // TODO: Reach { - client.World.SetTileEntity(coords, new NbtCompound(new[] + var block = client.World.GetBlockID(coords); + if (block == UprightSignBlock.BlockID || block == WallSignBlock.BlockID) { - new NbtString("Text1", packet.Text[0]), - new NbtString("Text2", packet.Text[1]), - new NbtString("Text3", packet.Text[2]), - new NbtString("Text4", packet.Text[3]), - })); - client.QueuePacket(packet); + client.World.SetTileEntity(coords, new NbtCompound(new[] + { + new NbtString("Text1", packet.Text[0]), + new NbtString("Text2", packet.Text[1]), + new NbtString("Text3", packet.Text[2]), + new NbtString("Text4", packet.Text[3]), + })); + // TODO: Some utility methods for things like "clients with given chunk loaded" + server.Clients.Where(c => ((RemoteClient)c).LoggedIn && c.World == _client.World).ToList().ForEach(c => c.QueuePacket(packet)); + } } } } From 74ebc61d2c7b5d41d42cc217fc5317acd6991b7e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 22 Jun 2015 10:52:40 -0400 Subject: [PATCH 15/15] Generate empty chunks in client --- TrueCraft.Client/MultiplayerClient.cs | 1 + TrueCraft.Core/TerrainGen/EmptyGenerator.cs | 27 +++++++++++++++++++++ TrueCraft.Core/TrueCraft.Core.csproj | 1 + 3 files changed, 29 insertions(+) create mode 100644 TrueCraft.Core/TerrainGen/EmptyGenerator.cs diff --git a/TrueCraft.Client/MultiplayerClient.cs b/TrueCraft.Client/MultiplayerClient.cs index f18f5ca..af29796 100644 --- a/TrueCraft.Client/MultiplayerClient.cs +++ b/TrueCraft.Client/MultiplayerClient.cs @@ -52,6 +52,7 @@ namespace TrueCraft.Client var repo = new BlockRepository(); repo.DiscoverBlockProviders(); World.World.BlockRepository = repo; + World.World.ChunkProvider = new EmptyGenerator(); Physics = new PhysicsEngine(World, repo); } diff --git a/TrueCraft.Core/TerrainGen/EmptyGenerator.cs b/TrueCraft.Core/TerrainGen/EmptyGenerator.cs new file mode 100644 index 0000000..bccbcb2 --- /dev/null +++ b/TrueCraft.Core/TerrainGen/EmptyGenerator.cs @@ -0,0 +1,27 @@ +using System; +using TrueCraft.API.World; +using System.Collections.Generic; +using TrueCraft.API; +using TrueCraft.Core.World; + +namespace TrueCraft.Core +{ + public class EmptyGenerator : IChunkProvider + { + public EmptyGenerator() + { + } + + public IChunk GenerateChunk(IWorld world, Coordinates2D coordinates) + { + return new Chunk(coordinates); + } + + public Coordinates3D GetSpawn(IWorld world) + { + return Coordinates3D.Zero; + } + + public IList ChunkDecorators { get; set; } + } +} \ No newline at end of file diff --git a/TrueCraft.Core/TrueCraft.Core.csproj b/TrueCraft.Core/TrueCraft.Core.csproj index e49c5f9..763d357 100644 --- a/TrueCraft.Core/TrueCraft.Core.csproj +++ b/TrueCraft.Core/TrueCraft.Core.csproj @@ -319,6 +319,7 @@ +