From dd0b497136ee9312f99116cff2fdd51285092686 Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Wed, 1 Mar 2017 15:54:52 +1100 Subject: [PATCH] Initial work on inventory that supports multiple hotbars. --- .../Inventory/InventoryScreen.Input.cs | 6 +-- .../2D/Screens/Inventory/InventoryScreen.cs | 2 +- ClassicalSharp/2D/Widgets/HotbarWidget.cs | 14 +++-- .../2D/Widgets/SurvivalHotbarWidget.cs | 7 +-- .../Commands/SinglePlayerCommands.cs | 2 +- ClassicalSharp/Game/InputHandler.cs | 11 ++-- ClassicalSharp/Game/Inventory.cs | 53 +++++++++++-------- ClassicalSharp/Game/PickingHandler.cs | 4 +- ClassicalSharp/Mode/Creative.cs | 17 +++--- ClassicalSharp/Mode/Survival.cs | 33 ++++++------ ClassicalSharp/Network/NetworkProcessor.cs | 2 +- ClassicalSharp/Network/Protocols/CPE.cs | 2 +- ClassicalSharp/Network/Protocols/Classic.cs | 2 +- .../Rendering/HeldBlockAnimation.cs | 4 +- ClassicalSharp/Rendering/HeldBlockRenderer.cs | 2 +- 15 files changed, 87 insertions(+), 74 deletions(-) diff --git a/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.Input.cs b/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.Input.cs index e683fa1ab..2fa96f0a7 100644 --- a/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.Input.cs +++ b/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.Input.cs @@ -43,7 +43,7 @@ namespace ClassicalSharp.Gui.Screens { ScrollbarClick(mouseY); } else if (button == MouseButton.Left) { if (selIndex != -1) { - game.Inventory.HeldBlock = blocksTable[selIndex]; + game.Inventory.Selected = blocksTable[selIndex]; } else if (Contains(TableX, TableY, TableWidth, TableHeight, mouseX, mouseY)) { return true; } @@ -60,7 +60,7 @@ namespace ClassicalSharp.Gui.Screens { key == game.Mapping(KeyBind.Inventory)) { game.Gui.SetNewScreen(null); } else if (key == Key.Enter && selIndex != -1) { - game.Inventory.HeldBlock = blocksTable[selIndex]; + game.Inventory.Selected = blocksTable[selIndex]; game.Gui.SetNewScreen(null); } else if ((key == Key.Left || key == Key.Keypad4) && selIndex != -1) { ArrowKeyMove(-1); @@ -71,7 +71,7 @@ namespace ClassicalSharp.Gui.Screens { } else if ((key == Key.Down || key == Key.Keypad2) && selIndex != -1) { ArrowKeyMove(blocksPerRow); } else if (key >= Key.Number1 && key <= Key.Number9) { - game.Inventory.HeldBlockIndex = (int)key - (int)Key.Number1; + game.Inventory.SelectedIndex = (int)key - (int)Key.Number1; } return true; } diff --git a/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs b/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs index c87a31527..e33ce5174 100644 --- a/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs +++ b/ClassicalSharp/2D/Screens/Inventory/InventoryScreen.cs @@ -136,7 +136,7 @@ namespace ClassicalSharp.Gui.Screens { game.Graphics.ContextRecreated += ContextRecreated; RecreateBlockTable(); - SetBlockTo(game.Inventory.HeldBlock); + SetBlockTo(game.Inventory.Selected); game.Keyboard.KeyRepeat = true; } diff --git a/ClassicalSharp/2D/Widgets/HotbarWidget.cs b/ClassicalSharp/2D/Widgets/HotbarWidget.cs index 9a36192cb..756c89c67 100644 --- a/ClassicalSharp/2D/Widgets/HotbarWidget.cs +++ b/ClassicalSharp/2D/Widgets/HotbarWidget.cs @@ -17,10 +17,8 @@ namespace ClassicalSharp.Gui.Widgets { public HotbarWidget(Game game) : base(game) { HorizontalAnchor = Anchor.Centre; VerticalAnchor = Anchor.BottomOrRight; - hotbarCount = game.Inventory.Hotbar.Length; } - protected int hotbarCount; Texture selTex, backTex; protected float barHeight, selBlockSize, elemSize; protected float barXOffset, borderSize; @@ -61,7 +59,7 @@ namespace ClassicalSharp.Gui.Widgets { backTex.ID = texId; backTex.Render(gfx); - int i = game.Inventory.HeldBlockIndex; + int i = game.Inventory.SelectedIndex; int x = (int)(X + barXOffset + (elemSize + borderSize) * i + elemSize / 2); selTex.ID = texId; @@ -73,8 +71,8 @@ namespace ClassicalSharp.Gui.Widgets { Model.ModelCache cache = game.ModelCache; drawer.BeginBatch(game, cache.vertices, cache.vb); - for (int i = 0; i < hotbarCount; i++) { - BlockID block = game.Inventory.Hotbar[i]; + for (int i = 0; i < Inventory.BlocksPerRow; i++) { + BlockID block = game.Inventory[i]; int x = (int)(X + barXOffset + (elemSize + borderSize) * i + elemSize / 2); int y = (int)(game.Height - barHeight / 2); @@ -103,7 +101,7 @@ namespace ClassicalSharp.Gui.Widgets { public override bool HandlesKeyDown(Key key) { if (key >= Key.Number1 && key <= Key.Number9) { - game.Inventory.HeldBlockIndex = (int)key - (int)Key.Number1; + game.Inventory.SelectedIndex = (int)key - (int)Key.Number1; return true; } return false; @@ -115,13 +113,13 @@ namespace ClassicalSharp.Gui.Widgets { InventoryScreen screen = game.Gui.ActiveScreen as InventoryScreen; if (screen == null) return false; - for (int i = 0; i < hotbarCount; i++) { + for (int i = 0; i < Inventory.BlocksPerRow; i++) { int x = (int)(X + (elemSize + borderSize) * i); int y = (int)(game.Height - barHeight); Rectangle bounds = new Rectangle(x, y, (int)(elemSize + borderSize), (int)barHeight); if (bounds.Contains(mouseX, mouseY)) { - game.Inventory.HeldBlockIndex = i; + game.Inventory.SelectedIndex = i; return true; } } diff --git a/ClassicalSharp/2D/Widgets/SurvivalHotbarWidget.cs b/ClassicalSharp/2D/Widgets/SurvivalHotbarWidget.cs index 63563c272..a0862f834 100644 --- a/ClassicalSharp/2D/Widgets/SurvivalHotbarWidget.cs +++ b/ClassicalSharp/2D/Widgets/SurvivalHotbarWidget.cs @@ -45,11 +45,12 @@ namespace ClassicalSharp.Gui.Widgets { int index = 0; posAtlas.tex.Y = (short)(game.Height - barHeight); - for (int i = 0; i < hotbarCount; i++) { + int offset = game.Inventory.Offset; + for (int i = 0; i < Inventory.BlocksPerRow; i++) { int x = (int)(X + (elemSize + borderSize) * i); posAtlas.curX = x; - if (surv.invCount[i] > 1) - posAtlas.AddInt(surv.invCount[i], vertices, ref index); + if (surv.invCount[offset + i] > 1) + posAtlas.AddInt(surv.invCount[offset + i], vertices, ref index); } gfx.BindTexture(posAtlas.tex.ID); diff --git a/ClassicalSharp/Commands/SinglePlayerCommands.cs b/ClassicalSharp/Commands/SinglePlayerCommands.cs index 87daf27c8..6f319fda5 100644 --- a/ClassicalSharp/Commands/SinglePlayerCommands.cs +++ b/ClassicalSharp/Commands/SinglePlayerCommands.cs @@ -116,7 +116,7 @@ namespace ClassicalSharp.Commands { if (!game.World.IsValidPos(min) || !game.World.IsValidPos(max)) return; BlockID toPlace = block; - if (toPlace == Block.Invalid) toPlace = game.Inventory.HeldBlock; + if (toPlace == Block.Invalid) toPlace = game.Inventory.Selected; for (int y = min.Y; y <= max.Y; y++) for (int z = min.Z; z <= max.Z; z++) diff --git a/ClassicalSharp/Game/InputHandler.cs b/ClassicalSharp/Game/InputHandler.cs index 02206133e..67131719c 100644 --- a/ClassicalSharp/Game/InputHandler.cs +++ b/ClassicalSharp/Game/InputHandler.cs @@ -150,11 +150,12 @@ namespace ClassicalSharp { int delta = (int)deltaAcc; deltaAcc -= delta; - int diff = -delta % inv.Hotbar.Length; - int newIndex = inv.HeldBlockIndex + diff; - if (newIndex < 0) newIndex += inv.Hotbar.Length; - if (newIndex >= inv.Hotbar.Length) newIndex -= inv.Hotbar.Length; - inv.HeldBlockIndex = newIndex; + const int blocksPerRow = Inventory.BlocksPerRow; + int diff = -delta % blocksPerRow; + int newIndex = inv.SelectedIndex + diff; + if (newIndex < 0) newIndex += blocksPerRow; + if (newIndex >= blocksPerRow) newIndex -= blocksPerRow; + inv.SelectedIndex = newIndex; } void KeyPressHandler(object sender, KeyPressEventArgs e) { diff --git a/ClassicalSharp/Game/Inventory.cs b/ClassicalSharp/Game/Inventory.cs index 92bc5df54..f84e63d30 100644 --- a/ClassicalSharp/Game/Inventory.cs +++ b/ClassicalSharp/Game/Inventory.cs @@ -23,48 +23,59 @@ namespace ClassicalSharp { public void OnNewMapLoaded(Game game) { } public void Dispose() { } - int hotbarIndex = 0; + int selectedI = 0; Game game; public bool CanChangeHeldBlock = true; - public BlockID[] Hotbar = new BlockID[9]; + public const int BlocksPerRow = 9, Rows = 2; + public int Offset = 0; + + public BlockID[] Hotbar = new BlockID[BlocksPerRow * Rows]; public InventoryPermissions CanPlace = new InventoryPermissions(); public InventoryPermissions CanDelete = new InventoryPermissions(); - /// Gets or sets the index of the held block. - /// Fails if the server has forbidden user from changing the held block. - public int HeldBlockIndex { - get { return hotbarIndex; } + /// Gets or sets the block at the given index within the current row. + public BlockID this[int index] { + get { return Hotbar[Offset + index]; } + set { Hotbar[Offset + index] = value; } + } + + /// Gets or sets the index of the selected block within the current row. + /// Fails if the server has forbidden user from changing the held block. + public int SelectedIndex { + get { return selectedI; } set { if (!CanChangeHeldBlock) { game.Chat.Add("&e/client: &cThe server has forbidden you from changing your held block."); return; } - hotbarIndex = value; + selectedI = value; game.Events.RaiseHeldBlockChanged(); } } - /// Gets or sets the block currently held by the player. - /// Fails if the server has forbidden user from changing the held block. - public BlockID HeldBlock { - get { return Hotbar[hotbarIndex]; } + /// Gets or sets the block currently selected by the player. + /// Fails if the server has forbidden user from changing the held block. + public BlockID Selected { + get { return Hotbar[Offset + selectedI]; } set { if (!CanChangeHeldBlock) { game.Chat.Add("&e/client: &cThe server has forbidden you from changing your held block."); return; } - for (int i = 0; i < Hotbar.Length; i++) { - if (Hotbar[i] == value) { - BlockID held = Hotbar[hotbarIndex]; - Hotbar[hotbarIndex] = Hotbar[i]; - Hotbar[i] = held; - - game.Events.RaiseHeldBlockChanged(); - return; - } + + for (int i = 0; i < BlocksPerRow; i++) { + if (this[i] != value) continue; + + BlockID prevSelected = this[selectedI]; + this[selectedI] = this[i]; + this[i] = prevSelected; + + game.Events.RaiseHeldBlockChanged(); + return; } - Hotbar[hotbarIndex] = value; + + this[selectedI] = value; game.Events.RaiseHeldBlockChanged(); } } diff --git a/ClassicalSharp/Game/PickingHandler.cs b/ClassicalSharp/Game/PickingHandler.cs index a2618dada..d03605413 100644 --- a/ClassicalSharp/Game/PickingHandler.cs +++ b/ClassicalSharp/Game/PickingHandler.cs @@ -39,7 +39,7 @@ namespace ClassicalSharp { } int btns = (left ? 1 : 0) + (right ? 1 : 0) + (middle ? 1 : 0); - if (btns > 1 || game.Gui.ActiveScreen.HandlesAllInput || inv.HeldBlock == Block.Invalid) return; + if (btns > 1 || game.Gui.ActiveScreen.HandlesAllInput || inv.Selected == Block.Invalid) return; // always play delete animations, even if we aren't picking a block. if (left) { @@ -67,7 +67,7 @@ namespace ClassicalSharp { if (!game.World.IsValidPos(pos)) return; BlockID old = game.World.GetBlock(pos); - BlockID block = inv.HeldBlock; + BlockID block = inv.Selected; if (game.autoRotate) block = AutoRotate.RotateBlock(game, block); diff --git a/ClassicalSharp/Mode/Creative.cs b/ClassicalSharp/Mode/Creative.cs index dc70e003b..06173a0d1 100644 --- a/ClassicalSharp/Mode/Creative.cs +++ b/ClassicalSharp/Mode/Creative.cs @@ -33,12 +33,12 @@ namespace ClassicalSharp.Mode { public void PickMiddle(BlockID old) { Inventory inv = game.Inventory; if (game.BlockInfo.Draw[old] != DrawType.Gas && (inv.CanPlace[old] || inv.CanDelete[old])) { - for (int i = 0; i < inv.Hotbar.Length; i++) { - if (inv.Hotbar[i] == old) { - inv.HeldBlockIndex = i; return; - } + for (int i = 0; i < Inventory.BlocksPerRow; i++) { + if (inv[i] != old) continue; + + inv.SelectedIndex = i; return; } - inv.HeldBlock = old; + inv.Selected = old; } } @@ -57,9 +57,10 @@ namespace ClassicalSharp.Mode { public void Init(Game game) { this.game = game; - game.Inventory.Hotbar = new BlockID[] { Block.Stone, - Block.Cobblestone, Block.Brick, Block.Dirt, Block.Wood, - Block.Log, Block.Leaves, Block.Grass, Block.Slab }; + Inventory inv = game.Inventory; + inv[0] = Block.Stone; inv[1] = Block.Cobblestone; inv[2] = Block.Brick; + inv[3] = Block.Dirt; inv[4] = Block.Wood; inv[5] = Block.Log; + inv[6] = Block.Leaves; inv[7] = Block.Grass; inv[8] = Block.Slab; } diff --git a/ClassicalSharp/Mode/Survival.cs b/ClassicalSharp/Mode/Survival.cs index 10ebdf520..85138b169 100644 --- a/ClassicalSharp/Mode/Survival.cs +++ b/ClassicalSharp/Mode/Survival.cs @@ -18,9 +18,11 @@ namespace ClassicalSharp.Mode { Game game; int score = 0; - internal byte[] invCount = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 10 }; + internal byte[] invCount = new byte[Inventory.BlocksPerRow * Inventory.Rows]; Random rnd = new Random(); + public SurvivalGameMode() { invCount[8] = 10; } // tnt + public bool HandlesKeyDown(Key key) { return false; } public void PickLeft(BlockID old) { @@ -34,18 +36,18 @@ namespace ClassicalSharp.Mode { } public void PickRight(BlockID old, BlockID block) { - int index = game.Inventory.HeldBlockIndex; - if (invCount[index] == 0) return; + int index = game.Inventory.SelectedIndex, offset = game.Inventory.Offset; + if (invCount[offset + index] == 0) return; Vector3I pos = game.SelectedPos.TranslatedPos; game.UpdateBlock(pos.X, pos.Y, pos.Z, block); game.UserEvents.RaiseBlockChanged(pos, old, block); - invCount[index]--; - if (invCount[index] != 0) return; + invCount[offset + index]--; + if (invCount[offset + index] != 0) return; // bypass HeldBlock's normal behaviour - game.Inventory.Hotbar[index] = Block.Air; + game.Inventory[index] = Block.Air; game.Events.RaiseHeldBlockChanged(); } @@ -80,24 +82,23 @@ namespace ClassicalSharp.Mode { } void AddToHotbar(BlockID block, int count) { - int index = -1; - BlockID[] hotbar = game.Inventory.Hotbar; + int index = -1, offset = game.Inventory.Offset; // Try searching for same block, then try invalid block - for (int i = 0; i < hotbar.Length; i++) { - if (hotbar[i] == block) index = i; + for (int i = 0; i < Inventory.BlocksPerRow; i++) { + if (game.Inventory[i] == block) index = i; } if (index == -1) { - for (int i = hotbar.Length - 1; i >= 0; i--) { - if (hotbar[i] == Block.Air) index = i; + for (int i = Inventory.BlocksPerRow - 1; i >= 0; i--) { + if (game.Inventory[i] == Block.Air) index = i; } } if (index == -1) return; // no free slots for (int j = 0; j < count; j++) { - if (invCount[index] >= 99) return; // no more count - hotbar[index] = block; - invCount[index]++; // TODO: do we need to raise an event if changing held block still? + if (invCount[offset + index] >= 99) return; // no more count + game.Inventory[index] = block; + invCount[offset + index]++; // TODO: do we need to raise an event if changing held block still? // TODO: we need to spawn block models instead } } @@ -123,7 +124,7 @@ namespace ClassicalSharp.Mode { BlockID[] hotbar = game.Inventory.Hotbar; for (int i = 0; i < hotbar.Length; i++) hotbar[i] = Block.Air; - hotbar[hotbar.Length - 1] = Block.TNT; + hotbar[Inventory.BlocksPerRow - 1] = Block.TNT; game.Server.AppName += " (survival)"; } diff --git a/ClassicalSharp/Network/NetworkProcessor.cs b/ClassicalSharp/Network/NetworkProcessor.cs index fb7336174..a6e037ea7 100644 --- a/ClassicalSharp/Network/NetworkProcessor.cs +++ b/ClassicalSharp/Network/NetworkProcessor.cs @@ -189,7 +189,7 @@ namespace ClassicalSharp.Network { void BlockChanged(object sender, BlockChangedEventArgs e) { Vector3I p = e.Coords; - BlockID block = game.Inventory.HeldBlock; + BlockID block = game.Inventory.Selected; if (e.Block == 0) { classic.SendSetBlock(p.X, p.Y, p.Z, false, block); diff --git a/ClassicalSharp/Network/Protocols/CPE.cs b/ClassicalSharp/Network/Protocols/CPE.cs index 768e5f85e..64194584f 100644 --- a/ClassicalSharp/Network/Protocols/CPE.cs +++ b/ClassicalSharp/Network/Protocols/CPE.cs @@ -94,7 +94,7 @@ namespace ClassicalSharp.Network.Protocols { bool canChange = reader.ReadUInt8() == 0; game.Inventory.CanChangeHeldBlock = true; - game.Inventory.HeldBlock = block; + game.Inventory.Selected = block; game.Inventory.CanChangeHeldBlock = canChange; } diff --git a/ClassicalSharp/Network/Protocols/Classic.cs b/ClassicalSharp/Network/Protocols/Classic.cs index f9af1f80f..a2d692737 100644 --- a/ClassicalSharp/Network/Protocols/Classic.cs +++ b/ClassicalSharp/Network/Protocols/Classic.cs @@ -283,7 +283,7 @@ namespace ClassicalSharp.Network.Protocols { } internal void SendPosition(Vector3 pos, float rotY, float headX) { - int payload = net.cpeData.sendHeldBlock ? game.Inventory.HeldBlock : 0xFF; + int payload = net.cpeData.sendHeldBlock ? game.Inventory.Selected : 0xFF; writer.WriteUInt8((byte)Opcode.EntityTeleport); writer.WriteUInt8((byte)payload); // held block when using HeldBlock, otherwise just 255 diff --git a/ClassicalSharp/Rendering/HeldBlockAnimation.cs b/ClassicalSharp/Rendering/HeldBlockAnimation.cs index 539f14119..30a5ba6ed 100644 --- a/ClassicalSharp/Rendering/HeldBlockAnimation.cs +++ b/ClassicalSharp/Rendering/HeldBlockAnimation.cs @@ -26,7 +26,7 @@ namespace ClassicalSharp.Renderers { internal void Init(Game game, HeldBlockRenderer held) { this.game = game; this.held = held; - lastType = game.Inventory.HeldBlock; + lastType = game.Inventory.Selected; game.Events.HeldBlockChanged += DoSwitchBlockAnim; game.UserEvents.BlockChanged += BlockChanged; @@ -131,7 +131,7 @@ namespace ClassicalSharp.Renderers { speed = Math.PI / period; if (updateLastType) - lastType = game.Inventory.HeldBlock; + lastType = game.Inventory.Selected; pos = Vector3.Zero; } } diff --git a/ClassicalSharp/Rendering/HeldBlockRenderer.cs b/ClassicalSharp/Rendering/HeldBlockRenderer.cs index 756dfe355..0df7fe70f 100644 --- a/ClassicalSharp/Rendering/HeldBlockRenderer.cs +++ b/ClassicalSharp/Rendering/HeldBlockRenderer.cs @@ -45,7 +45,7 @@ namespace ClassicalSharp.Renderers { Vector3 last = anim.pos; anim.pos = Vector3.Zero; - type = game.Inventory.HeldBlock; + type = game.Inventory.Selected; block.CosX = 1; block.SinX = 0; block.SwitchOrder = false; if (anim.doAnim) anim.Update(delta, last);