Initial work on inventory that supports multiple hotbars.

This commit is contained in:
UnknownShadow200 2017-03-01 15:54:52 +11:00
parent 35fd58f893
commit dd0b497136
15 changed files with 87 additions and 74 deletions

View File

@ -43,7 +43,7 @@ namespace ClassicalSharp.Gui.Screens {
ScrollbarClick(mouseY); ScrollbarClick(mouseY);
} else if (button == MouseButton.Left) { } else if (button == MouseButton.Left) {
if (selIndex != -1) { if (selIndex != -1) {
game.Inventory.HeldBlock = blocksTable[selIndex]; game.Inventory.Selected = blocksTable[selIndex];
} else if (Contains(TableX, TableY, TableWidth, TableHeight, mouseX, mouseY)) { } else if (Contains(TableX, TableY, TableWidth, TableHeight, mouseX, mouseY)) {
return true; return true;
} }
@ -60,7 +60,7 @@ namespace ClassicalSharp.Gui.Screens {
key == game.Mapping(KeyBind.Inventory)) { key == game.Mapping(KeyBind.Inventory)) {
game.Gui.SetNewScreen(null); game.Gui.SetNewScreen(null);
} else if (key == Key.Enter && selIndex != -1) { } else if (key == Key.Enter && selIndex != -1) {
game.Inventory.HeldBlock = blocksTable[selIndex]; game.Inventory.Selected = blocksTable[selIndex];
game.Gui.SetNewScreen(null); game.Gui.SetNewScreen(null);
} else if ((key == Key.Left || key == Key.Keypad4) && selIndex != -1) { } else if ((key == Key.Left || key == Key.Keypad4) && selIndex != -1) {
ArrowKeyMove(-1); ArrowKeyMove(-1);
@ -71,7 +71,7 @@ namespace ClassicalSharp.Gui.Screens {
} else if ((key == Key.Down || key == Key.Keypad2) && selIndex != -1) { } else if ((key == Key.Down || key == Key.Keypad2) && selIndex != -1) {
ArrowKeyMove(blocksPerRow); ArrowKeyMove(blocksPerRow);
} else if (key >= Key.Number1 && key <= Key.Number9) { } 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; return true;
} }

View File

@ -136,7 +136,7 @@ namespace ClassicalSharp.Gui.Screens {
game.Graphics.ContextRecreated += ContextRecreated; game.Graphics.ContextRecreated += ContextRecreated;
RecreateBlockTable(); RecreateBlockTable();
SetBlockTo(game.Inventory.HeldBlock); SetBlockTo(game.Inventory.Selected);
game.Keyboard.KeyRepeat = true; game.Keyboard.KeyRepeat = true;
} }

View File

@ -17,10 +17,8 @@ namespace ClassicalSharp.Gui.Widgets {
public HotbarWidget(Game game) : base(game) { public HotbarWidget(Game game) : base(game) {
HorizontalAnchor = Anchor.Centre; HorizontalAnchor = Anchor.Centre;
VerticalAnchor = Anchor.BottomOrRight; VerticalAnchor = Anchor.BottomOrRight;
hotbarCount = game.Inventory.Hotbar.Length;
} }
protected int hotbarCount;
Texture selTex, backTex; Texture selTex, backTex;
protected float barHeight, selBlockSize, elemSize; protected float barHeight, selBlockSize, elemSize;
protected float barXOffset, borderSize; protected float barXOffset, borderSize;
@ -61,7 +59,7 @@ namespace ClassicalSharp.Gui.Widgets {
backTex.ID = texId; backTex.ID = texId;
backTex.Render(gfx); backTex.Render(gfx);
int i = game.Inventory.HeldBlockIndex; int i = game.Inventory.SelectedIndex;
int x = (int)(X + barXOffset + (elemSize + borderSize) * i + elemSize / 2); int x = (int)(X + barXOffset + (elemSize + borderSize) * i + elemSize / 2);
selTex.ID = texId; selTex.ID = texId;
@ -73,8 +71,8 @@ namespace ClassicalSharp.Gui.Widgets {
Model.ModelCache cache = game.ModelCache; Model.ModelCache cache = game.ModelCache;
drawer.BeginBatch(game, cache.vertices, cache.vb); drawer.BeginBatch(game, cache.vertices, cache.vb);
for (int i = 0; i < hotbarCount; i++) { for (int i = 0; i < Inventory.BlocksPerRow; i++) {
BlockID block = game.Inventory.Hotbar[i]; BlockID block = game.Inventory[i];
int x = (int)(X + barXOffset + (elemSize + borderSize) * i + elemSize / 2); int x = (int)(X + barXOffset + (elemSize + borderSize) * i + elemSize / 2);
int y = (int)(game.Height - barHeight / 2); int y = (int)(game.Height - barHeight / 2);
@ -103,7 +101,7 @@ namespace ClassicalSharp.Gui.Widgets {
public override bool HandlesKeyDown(Key key) { public override bool HandlesKeyDown(Key key) {
if (key >= Key.Number1 && key <= Key.Number9) { 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 true;
} }
return false; return false;
@ -115,13 +113,13 @@ namespace ClassicalSharp.Gui.Widgets {
InventoryScreen screen = game.Gui.ActiveScreen as InventoryScreen; InventoryScreen screen = game.Gui.ActiveScreen as InventoryScreen;
if (screen == null) return false; 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 x = (int)(X + (elemSize + borderSize) * i);
int y = (int)(game.Height - barHeight); int y = (int)(game.Height - barHeight);
Rectangle bounds = new Rectangle(x, y, (int)(elemSize + borderSize), (int)barHeight); Rectangle bounds = new Rectangle(x, y, (int)(elemSize + borderSize), (int)barHeight);
if (bounds.Contains(mouseX, mouseY)) { if (bounds.Contains(mouseX, mouseY)) {
game.Inventory.HeldBlockIndex = i; game.Inventory.SelectedIndex = i;
return true; return true;
} }
} }

View File

@ -45,11 +45,12 @@ namespace ClassicalSharp.Gui.Widgets {
int index = 0; int index = 0;
posAtlas.tex.Y = (short)(game.Height - barHeight); 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); int x = (int)(X + (elemSize + borderSize) * i);
posAtlas.curX = x; posAtlas.curX = x;
if (surv.invCount[i] > 1) if (surv.invCount[offset + i] > 1)
posAtlas.AddInt(surv.invCount[i], vertices, ref index); posAtlas.AddInt(surv.invCount[offset + i], vertices, ref index);
} }
gfx.BindTexture(posAtlas.tex.ID); gfx.BindTexture(posAtlas.tex.ID);

View File

@ -116,7 +116,7 @@ namespace ClassicalSharp.Commands {
if (!game.World.IsValidPos(min) || !game.World.IsValidPos(max)) return; if (!game.World.IsValidPos(min) || !game.World.IsValidPos(max)) return;
BlockID toPlace = block; 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 y = min.Y; y <= max.Y; y++)
for (int z = min.Z; z <= max.Z; z++) for (int z = min.Z; z <= max.Z; z++)

View File

@ -150,11 +150,12 @@ namespace ClassicalSharp {
int delta = (int)deltaAcc; int delta = (int)deltaAcc;
deltaAcc -= delta; deltaAcc -= delta;
int diff = -delta % inv.Hotbar.Length; const int blocksPerRow = Inventory.BlocksPerRow;
int newIndex = inv.HeldBlockIndex + diff; int diff = -delta % blocksPerRow;
if (newIndex < 0) newIndex += inv.Hotbar.Length; int newIndex = inv.SelectedIndex + diff;
if (newIndex >= inv.Hotbar.Length) newIndex -= inv.Hotbar.Length; if (newIndex < 0) newIndex += blocksPerRow;
inv.HeldBlockIndex = newIndex; if (newIndex >= blocksPerRow) newIndex -= blocksPerRow;
inv.SelectedIndex = newIndex;
} }
void KeyPressHandler(object sender, KeyPressEventArgs e) { void KeyPressHandler(object sender, KeyPressEventArgs e) {

View File

@ -23,48 +23,59 @@ namespace ClassicalSharp {
public void OnNewMapLoaded(Game game) { } public void OnNewMapLoaded(Game game) { }
public void Dispose() { } public void Dispose() { }
int hotbarIndex = 0; int selectedI = 0;
Game game; Game game;
public bool CanChangeHeldBlock = true; 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 CanPlace = new InventoryPermissions();
public InventoryPermissions CanDelete = new InventoryPermissions(); public InventoryPermissions CanDelete = new InventoryPermissions();
/// <summary> Gets or sets the index of the held block. /// <summary> Gets or sets the block at the given index within the current row. </summary>
/// Fails if the server has forbidden user from changing the held block. </summary> public BlockID this[int index] {
public int HeldBlockIndex { get { return Hotbar[Offset + index]; }
get { return hotbarIndex; } set { Hotbar[Offset + index] = value; }
}
/// <summary> Gets or sets the index of the selected block within the current row. </summary>
/// <remarks> Fails if the server has forbidden user from changing the held block. </remarks>
public int SelectedIndex {
get { return selectedI; }
set { set {
if (!CanChangeHeldBlock) { if (!CanChangeHeldBlock) {
game.Chat.Add("&e/client: &cThe server has forbidden you from changing your held block."); game.Chat.Add("&e/client: &cThe server has forbidden you from changing your held block.");
return; return;
} }
hotbarIndex = value; selectedI = value;
game.Events.RaiseHeldBlockChanged(); game.Events.RaiseHeldBlockChanged();
} }
} }
/// <summary> Gets or sets the block currently held by the player. /// <summary> Gets or sets the block currently selected by the player. </summary>
/// Fails if the server has forbidden user from changing the held block. </summary> /// <remarks> Fails if the server has forbidden user from changing the held block. </remarks>
public BlockID HeldBlock { public BlockID Selected {
get { return Hotbar[hotbarIndex]; } get { return Hotbar[Offset + selectedI]; }
set { set {
if (!CanChangeHeldBlock) { if (!CanChangeHeldBlock) {
game.Chat.Add("&e/client: &cThe server has forbidden you from changing your held block."); game.Chat.Add("&e/client: &cThe server has forbidden you from changing your held block.");
return; 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(); for (int i = 0; i < BlocksPerRow; i++) {
return; 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(); game.Events.RaiseHeldBlockChanged();
} }
} }

View File

@ -39,7 +39,7 @@ namespace ClassicalSharp {
} }
int btns = (left ? 1 : 0) + (right ? 1 : 0) + (middle ? 1 : 0); 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. // always play delete animations, even if we aren't picking a block.
if (left) { if (left) {
@ -67,7 +67,7 @@ namespace ClassicalSharp {
if (!game.World.IsValidPos(pos)) return; if (!game.World.IsValidPos(pos)) return;
BlockID old = game.World.GetBlock(pos); BlockID old = game.World.GetBlock(pos);
BlockID block = inv.HeldBlock; BlockID block = inv.Selected;
if (game.autoRotate) if (game.autoRotate)
block = AutoRotate.RotateBlock(game, block); block = AutoRotate.RotateBlock(game, block);

View File

@ -33,12 +33,12 @@ namespace ClassicalSharp.Mode {
public void PickMiddle(BlockID old) { public void PickMiddle(BlockID old) {
Inventory inv = game.Inventory; Inventory inv = game.Inventory;
if (game.BlockInfo.Draw[old] != DrawType.Gas && (inv.CanPlace[old] || inv.CanDelete[old])) { if (game.BlockInfo.Draw[old] != DrawType.Gas && (inv.CanPlace[old] || inv.CanDelete[old])) {
for (int i = 0; i < inv.Hotbar.Length; i++) { for (int i = 0; i < Inventory.BlocksPerRow; i++) {
if (inv.Hotbar[i] == old) { if (inv[i] != old) continue;
inv.HeldBlockIndex = i; return;
} inv.SelectedIndex = i; return;
} }
inv.HeldBlock = old; inv.Selected = old;
} }
} }
@ -57,9 +57,10 @@ namespace ClassicalSharp.Mode {
public void Init(Game game) { public void Init(Game game) {
this.game = game; this.game = game;
game.Inventory.Hotbar = new BlockID[] { Block.Stone, Inventory inv = game.Inventory;
Block.Cobblestone, Block.Brick, Block.Dirt, Block.Wood, inv[0] = Block.Stone; inv[1] = Block.Cobblestone; inv[2] = Block.Brick;
Block.Log, Block.Leaves, Block.Grass, Block.Slab }; inv[3] = Block.Dirt; inv[4] = Block.Wood; inv[5] = Block.Log;
inv[6] = Block.Leaves; inv[7] = Block.Grass; inv[8] = Block.Slab;
} }

View File

@ -18,9 +18,11 @@ namespace ClassicalSharp.Mode {
Game game; Game game;
int score = 0; 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(); Random rnd = new Random();
public SurvivalGameMode() { invCount[8] = 10; } // tnt
public bool HandlesKeyDown(Key key) { return false; } public bool HandlesKeyDown(Key key) { return false; }
public void PickLeft(BlockID old) { public void PickLeft(BlockID old) {
@ -34,18 +36,18 @@ namespace ClassicalSharp.Mode {
} }
public void PickRight(BlockID old, BlockID block) { public void PickRight(BlockID old, BlockID block) {
int index = game.Inventory.HeldBlockIndex; int index = game.Inventory.SelectedIndex, offset = game.Inventory.Offset;
if (invCount[index] == 0) return; if (invCount[offset + index] == 0) return;
Vector3I pos = game.SelectedPos.TranslatedPos; Vector3I pos = game.SelectedPos.TranslatedPos;
game.UpdateBlock(pos.X, pos.Y, pos.Z, block); game.UpdateBlock(pos.X, pos.Y, pos.Z, block);
game.UserEvents.RaiseBlockChanged(pos, old, block); game.UserEvents.RaiseBlockChanged(pos, old, block);
invCount[index]--; invCount[offset + index]--;
if (invCount[index] != 0) return; if (invCount[offset + index] != 0) return;
// bypass HeldBlock's normal behaviour // bypass HeldBlock's normal behaviour
game.Inventory.Hotbar[index] = Block.Air; game.Inventory[index] = Block.Air;
game.Events.RaiseHeldBlockChanged(); game.Events.RaiseHeldBlockChanged();
} }
@ -80,24 +82,23 @@ namespace ClassicalSharp.Mode {
} }
void AddToHotbar(BlockID block, int count) { void AddToHotbar(BlockID block, int count) {
int index = -1; int index = -1, offset = game.Inventory.Offset;
BlockID[] hotbar = game.Inventory.Hotbar;
// Try searching for same block, then try invalid block // Try searching for same block, then try invalid block
for (int i = 0; i < hotbar.Length; i++) { for (int i = 0; i < Inventory.BlocksPerRow; i++) {
if (hotbar[i] == block) index = i; if (game.Inventory[i] == block) index = i;
} }
if (index == -1) { if (index == -1) {
for (int i = hotbar.Length - 1; i >= 0; i--) { for (int i = Inventory.BlocksPerRow - 1; i >= 0; i--) {
if (hotbar[i] == Block.Air) index = i; if (game.Inventory[i] == Block.Air) index = i;
} }
} }
if (index == -1) return; // no free slots if (index == -1) return; // no free slots
for (int j = 0; j < count; j++) { for (int j = 0; j < count; j++) {
if (invCount[index] >= 99) return; // no more count if (invCount[offset + index] >= 99) return; // no more count
hotbar[index] = block; game.Inventory[index] = block;
invCount[index]++; // TODO: do we need to raise an event if changing held block still? invCount[offset + index]++; // TODO: do we need to raise an event if changing held block still?
// TODO: we need to spawn block models instead // TODO: we need to spawn block models instead
} }
} }
@ -123,7 +124,7 @@ namespace ClassicalSharp.Mode {
BlockID[] hotbar = game.Inventory.Hotbar; BlockID[] hotbar = game.Inventory.Hotbar;
for (int i = 0; i < hotbar.Length; i++) for (int i = 0; i < hotbar.Length; i++)
hotbar[i] = Block.Air; hotbar[i] = Block.Air;
hotbar[hotbar.Length - 1] = Block.TNT; hotbar[Inventory.BlocksPerRow - 1] = Block.TNT;
game.Server.AppName += " (survival)"; game.Server.AppName += " (survival)";
} }

View File

@ -189,7 +189,7 @@ namespace ClassicalSharp.Network {
void BlockChanged(object sender, BlockChangedEventArgs e) { void BlockChanged(object sender, BlockChangedEventArgs e) {
Vector3I p = e.Coords; Vector3I p = e.Coords;
BlockID block = game.Inventory.HeldBlock; BlockID block = game.Inventory.Selected;
if (e.Block == 0) { if (e.Block == 0) {
classic.SendSetBlock(p.X, p.Y, p.Z, false, block); classic.SendSetBlock(p.X, p.Y, p.Z, false, block);

View File

@ -94,7 +94,7 @@ namespace ClassicalSharp.Network.Protocols {
bool canChange = reader.ReadUInt8() == 0; bool canChange = reader.ReadUInt8() == 0;
game.Inventory.CanChangeHeldBlock = true; game.Inventory.CanChangeHeldBlock = true;
game.Inventory.HeldBlock = block; game.Inventory.Selected = block;
game.Inventory.CanChangeHeldBlock = canChange; game.Inventory.CanChangeHeldBlock = canChange;
} }

View File

@ -283,7 +283,7 @@ namespace ClassicalSharp.Network.Protocols {
} }
internal void SendPosition(Vector3 pos, float rotY, float headX) { 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)Opcode.EntityTeleport);
writer.WriteUInt8((byte)payload); // held block when using HeldBlock, otherwise just 255 writer.WriteUInt8((byte)payload); // held block when using HeldBlock, otherwise just 255

View File

@ -26,7 +26,7 @@ namespace ClassicalSharp.Renderers {
internal void Init(Game game, HeldBlockRenderer held) { internal void Init(Game game, HeldBlockRenderer held) {
this.game = game; this.game = game;
this.held = held; this.held = held;
lastType = game.Inventory.HeldBlock; lastType = game.Inventory.Selected;
game.Events.HeldBlockChanged += DoSwitchBlockAnim; game.Events.HeldBlockChanged += DoSwitchBlockAnim;
game.UserEvents.BlockChanged += BlockChanged; game.UserEvents.BlockChanged += BlockChanged;
@ -131,7 +131,7 @@ namespace ClassicalSharp.Renderers {
speed = Math.PI / period; speed = Math.PI / period;
if (updateLastType) if (updateLastType)
lastType = game.Inventory.HeldBlock; lastType = game.Inventory.Selected;
pos = Vector3.Zero; pos = Vector3.Zero;
} }
} }

View File

@ -45,7 +45,7 @@ namespace ClassicalSharp.Renderers {
Vector3 last = anim.pos; Vector3 last = anim.pos;
anim.pos = Vector3.Zero; anim.pos = Vector3.Zero;
type = game.Inventory.HeldBlock; type = game.Inventory.Selected;
block.CosX = 1; block.SinX = 0; block.CosX = 1; block.SinX = 0;
block.SwitchOrder = false; block.SwitchOrder = false;
if (anim.doAnim) anim.Update(delta, last); if (anim.doAnim) anim.Update(delta, last);