Redo setting inventory order to make more sense

This commit is contained in:
UnknownShadow200 2018-04-06 08:24:54 +10:00
parent f83eee14e4
commit 1cf621d9f6
21 changed files with 294 additions and 349 deletions

View File

@ -1,7 +1,6 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 // Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System; using System;
using ClassicalSharp.Gui.Widgets; using System.Drawing;
using ClassicalSharp.GraphicsAPI;
using OpenTK.Input; using OpenTK.Input;
namespace ClassicalSharp.Gui { namespace ClassicalSharp.Gui {
@ -10,10 +9,7 @@ namespace ClassicalSharp.Gui {
public abstract class GuiElement : IDisposable { public abstract class GuiElement : IDisposable {
protected Game game; protected Game game;
public GuiElement(Game game) { this.game = game; }
public GuiElement(Game game) {
this.game = game;
}
public abstract void Init(); public abstract void Init();
@ -49,4 +45,38 @@ namespace ClassicalSharp.Gui {
return x >= recX && y >= recY && x < recX + width && y < recY + height; return x >= recX && y >= recY && x < recX + width && y < recY + height;
} }
} }
/// <summary> Represents a container of widgets and other 2D elements. </summary>
/// <remarks> May cover the entire game window. </remarks>
public abstract class Screen : GuiElement {
public Screen(Game game) : base(game) { }
public bool HandlesAllInput, BlocksWorld, HidesHud, RenderHudOver;
public abstract void OnResize(int width, int height);
protected abstract void ContextLost();
protected abstract void ContextRecreated();
}
/// <summary> Represents an individual 2D gui component. </summary>
public abstract class Widget : GuiElement {
public Widget(Game game) : base(game) { }
public ClickHandler MenuClick;
public bool Active, Disabled;
public int X, Y, Width, Height;
public Anchor HorizontalAnchor, VerticalAnchor;
public int XOffset, YOffset;
public Rectangle Bounds { get { return new Rectangle(X, Y, Width, Height); } }
public virtual void Reposition() {
X = CalcPos(HorizontalAnchor, XOffset, Width, game.Width);
Y = CalcPos(VerticalAnchor, YOffset, Height, game.Height);
}
}
} }

View File

@ -52,7 +52,7 @@ namespace ClassicalSharp.Gui.Screens {
} }
return -1; return -1;
} }
protected ButtonWidget MakeBack(bool toGame, Font font, ClickHandler onClick) { protected ButtonWidget MakeBack(bool toGame, Font font, ClickHandler onClick) {
int width = game.UseClassicOptions ? 400 : 200; int width = game.UseClassicOptions ? 400 : 200;
return MakeBack(width, toGame ? "Back to game" : "Cancel", 25, font, onClick); return MakeBack(width, toGame ? "Back to game" : "Cancel", 25, font, onClick);
@ -65,5 +65,30 @@ namespace ClassicalSharp.Gui.Screens {
protected static void SwitchOptions(Game g, Widget w) { g.Gui.SetNewScreen(new OptionsGroupScreen(g)); } protected static void SwitchOptions(Game g, Widget w) { g.Gui.SetNewScreen(new OptionsGroupScreen(g)); }
protected static void SwitchPause(Game g, Widget w) { g.Gui.SetNewScreen(new PauseScreen(g)); } protected static void SwitchPause(Game g, Widget w) { g.Gui.SetNewScreen(new PauseScreen(g)); }
protected static void DisposeWidgets<T>(T[] widgets) where T : Widget {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] != null) widgets[i].Dispose();
}
}
protected static void RepositionWidgets<T>(T[] widgets) where T : Widget {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] != null) widgets[i].Reposition();
}
}
protected static void RenderWidgets<T>(T[] widgets, double delta) where T : Widget {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] != null) widgets[i].Render(delta);
}
}
} }
} }

View File

@ -12,7 +12,7 @@ namespace ClassicalSharp.Gui.Screens {
const int keyI = 0, modifyI = 1, actionI = 2; const int keyI = 0, modifyI = 1, actionI = 2;
HotkeyList hotkeys; HotkeyList hotkeys;
Hotkey curHotkey, origHotkey; Hotkey curHotkey, origHotkey;
Widget focusWidget; int selectedI = -1;
static FastColour grey = new FastColour(150, 150, 150); static FastColour grey = new FastColour(150, 150, 150);
public EditHotkeyScreen(Game game, Hotkey original) : base(game) { public EditHotkeyScreen(Game game, Hotkey original) : base(game) {
@ -41,7 +41,7 @@ namespace ClassicalSharp.Gui.Screens {
if (key == Key.Escape) { if (key == Key.Escape) {
game.Gui.SetNewScreen(null); game.Gui.SetNewScreen(null);
return true; return true;
} else if (focusWidget != null) { } else if (selectedI >= 0) {
FocusKeyDown(key); FocusKeyDown(key);
return true; return true;
} }
@ -84,7 +84,7 @@ namespace ClassicalSharp.Gui.Screens {
public override void Dispose() { public override void Dispose() {
game.Keyboard.KeyRepeat = false; game.Keyboard.KeyRepeat = false;
focusWidget = null; selectedI = -1;
base.Dispose(); base.Dispose();
} }
@ -98,7 +98,7 @@ namespace ClassicalSharp.Gui.Screens {
curHotkey.StaysOpen = !curHotkey.StaysOpen; curHotkey.StaysOpen = !curHotkey.StaysOpen;
string staysOpen = curHotkey.StaysOpen ? "ON" : "OFF"; string staysOpen = curHotkey.StaysOpen ? "ON" : "OFF";
staysOpen = "Input stays open: " + staysOpen; staysOpen = "Input stays open: " + staysOpen;
SetButton(widgets[3], staysOpen); SetButton(3, staysOpen);
} }
void SaveChangesClick(Game game, Widget widget) { void SaveChangesClick(Game game, Widget widget) {
@ -126,50 +126,50 @@ namespace ClassicalSharp.Gui.Screens {
} }
void BaseKeyClick(Game game, Widget widget) { void BaseKeyClick(Game game, Widget widget) {
focusWidget = widgets[keyI]; selectedI = keyI;
SetButton(widgets[keyI], "Key: press a key.."); SetButton(keyI, "Key: press a key..");
supressNextPress = true; supressNextPress = true;
} }
void ModifiersClick(Game game, Widget widget) { void ModifiersClick(Game game, Widget widget) {
focusWidget = widgets[modifyI]; selectedI = modifyI;
SetButton(widgets[modifyI], "Modifiers: press a key.."); SetButton(modifyI, "Modifiers: press a key..");
supressNextPress = true; supressNextPress = true;
} }
void FocusKeyDown(Key key) { void FocusKeyDown(Key key) {
if (focusWidget == widgets[keyI]) { if (selectedI == keyI) {
curHotkey.BaseKey = key; curHotkey.BaseKey = key;
SetButton(widgets[keyI], "Key: " + curHotkey.BaseKey); SetButton(keyI, "Key: " + curHotkey.BaseKey);
supressNextPress = true; supressNextPress = true;
} else if (focusWidget == widgets[modifyI]) { } else if (selectedI == modifyI) {
if (key == Key.ControlLeft || key == Key.ControlRight) curHotkey.Flags |= 1; if (key == Key.ControlLeft || key == Key.ControlRight) curHotkey.Flags |= 1;
else if (key == Key.ShiftLeft || key == Key.ShiftRight) curHotkey.Flags |= 2; else if (key == Key.ShiftLeft || key == Key.ShiftRight) curHotkey.Flags |= 2;
else if (key == Key.AltLeft || key == Key.AltRight) curHotkey.Flags |= 4; else if (key == Key.AltLeft || key == Key.AltRight) curHotkey.Flags |= 4;
else curHotkey.Flags = 0; else curHotkey.Flags = 0;
string flags = HotkeyListScreen.MakeFlagsString(curHotkey.Flags); string flags = HotkeyListScreen.MakeFlagsString(curHotkey.Flags);
SetButton(widgets[modifyI], "Modifiers:" + flags); SetButton(modifyI, "Modifiers:" + flags);
supressNextPress = true; supressNextPress = true;
} }
focusWidget = null; selectedI = -1;
} }
void LostFocus() { void LostFocus() {
if (focusWidget == null) return; if (selectedI == -1) return;
if (focusWidget == widgets[keyI]) { if (selectedI == keyI) {
SetButton(widgets[keyI], "Key: " + curHotkey.BaseKey); SetButton(keyI, "Key: " + curHotkey.BaseKey);
} else if (focusWidget == widgets[modifyI]) { } else if (selectedI == modifyI) {
string flags = HotkeyListScreen.MakeFlagsString(curHotkey.Flags); string flags = HotkeyListScreen.MakeFlagsString(curHotkey.Flags);
SetButton(widgets[modifyI], "Modifiers:" + flags); SetButton(modifyI, "Modifiers:" + flags);
} }
focusWidget = null; selectedI = -1;
supressNextPress = false; supressNextPress = false;
} }
void SetButton(Widget widget, string text) { void SetButton(int i, string text) {
((ButtonWidget)widget).SetText(text); ((ButtonWidget)widgets[i]).SetText(text);
} }
} }
} }

View File

@ -58,7 +58,6 @@ namespace ClassicalSharp.Gui.Screens {
} }
protected override void ContextLost() { protected override void ContextLost() {
input.Dispose();
DisposeDescWidget(); DisposeDescWidget();
base.ContextLost(); base.ContextLost();
} }

View File

@ -1,58 +0,0 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using ClassicalSharp.Gui.Widgets;
using OpenTK.Input;
namespace ClassicalSharp.Gui.Screens {
/// <summary> Represents a container of widgets and other 2D elements. </summary>
/// <remarks> May cover the entire game window. </remarks>
public abstract class Screen : GuiElement {
public Screen(Game game) : base(game) {
}
/// <summary> Whether this screen handles all mouse and keyboard input. </summary>
/// <remarks> This prevents the client from interacting with the world. </remarks>
public bool HandlesAllInput;
/// <summary> Whether this screen completely and opaquely covers the game world behind it. </summary>
public bool BlocksWorld;
/// <summary> Whether this screen hides the normal in-game hud. </summary>
public bool HidesHud;
/// <summary> Whether the normal in-game hud should be drawn over the top of this screen. </summary>
public bool RenderHudOver;
/// <summary> Called when the game window is resized. </summary>
public abstract void OnResize(int width, int height);
protected abstract void ContextLost();
protected abstract void ContextRecreated();
protected static void DisposeWidgets<T>(T[] widgets) where T : Widget {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] != null) widgets[i].Dispose();
}
}
protected static void RepositionWidgets<T>(T[] widgets) where T : Widget {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] != null) widgets[i].Reposition();
}
}
protected static void RenderWidgets<T>(T[] widgets, double delta) where T : Widget {
if (widgets == null) return;
for (int i = 0; i < widgets.Length; i++) {
if (widgets[i] != null) widgets[i].Render(delta);
}
}
}
}

View File

@ -206,6 +206,7 @@ namespace ClassicalSharp.Gui.Widgets {
public void MakeDescTex(BlockID block) { public void MakeDescTex(BlockID block) {
game.Graphics.DeleteTexture(ref descTex); game.Graphics.DeleteTexture(ref descTex);
if (block == Block.Air) return;
UpdateBlockInfoString(block); UpdateBlockInfoString(block);
string value = buffer.ToString(); string value = buffer.ToString();
@ -218,8 +219,13 @@ namespace ClassicalSharp.Gui.Widgets {
int totalElements = 0; int totalElements = 0;
BlockID[] map = game.Inventory.Map; BlockID[] map = game.Inventory.Map;
for (int i = 0; i < map.Length; i++) { for (int i = 0; i < map.Length;) {
if ((i % ElementsPerRow) == 0 && RowEmpty(i)) {
i += ElementsPerRow; continue;
}
if (Show(map[i])) { totalElements++; } if (Show(map[i])) { totalElements++; }
i++;
} }
totalRows = Utils.CeilDiv(totalElements, ElementsPerRow); totalRows = Utils.CeilDiv(totalElements, ElementsPerRow);
@ -228,13 +234,28 @@ namespace ClassicalSharp.Gui.Widgets {
Elements = new BlockID[totalElements]; Elements = new BlockID[totalElements];
int index = 0; int index = 0;
for (int i = 0; i < map.Length; i++) { for (int i = 0; i < map.Length;) {
if ((i % ElementsPerRow) == 0 && RowEmpty(i)) {
i += ElementsPerRow; continue;
}
if (Show(map[i])) { Elements[index++] = map[i]; } if (Show(map[i])) { Elements[index++] = map[i]; }
i++;
} }
} }
bool RowEmpty(int i) {
BlockID[] map = game.Inventory.Map;
int max = Math.Min(i + ElementsPerRow, map.Length);
for (int j = i; j < max; j++) {
if (map[j] != Block.Air) return false;
}
return true;
}
bool Show(BlockID block) { bool Show(BlockID block) {
if (block == Block.Air) return false; //if (block == Block.Air) return false;
if (block < Block.CpeCount) { if (block < Block.CpeCount) {
int count = game.SupportsCPEBlocks ? Block.CpeCount : Block.OriginalCount; int count = game.SupportsCPEBlocks ? Block.CpeCount : Block.OriginalCount;
@ -271,7 +292,7 @@ namespace ClassicalSharp.Gui.Widgets {
if (scroll.HandlesMouseDown(mouseX, mouseY, button)) { if (scroll.HandlesMouseDown(mouseX, mouseY, button)) {
return true; return true;
} else if (SelectedIndex != -1) { } else if (SelectedIndex != -1 && Elements[SelectedIndex] != Block.Air) {
game.Inventory.Selected = Elements[SelectedIndex]; game.Inventory.Selected = Elements[SelectedIndex];
PendingClose = true; PendingClose = true;
return true; return true;
@ -300,6 +321,7 @@ namespace ClassicalSharp.Gui.Widgets {
void ScrollRelative(int delta) { void ScrollRelative(int delta) {
int startIndex = SelectedIndex; int startIndex = SelectedIndex;
SelectedIndex += delta; SelectedIndex += delta;
if (SelectedIndex < 0) SelectedIndex -= delta; if (SelectedIndex < 0) SelectedIndex -= delta;
if (SelectedIndex >= Elements.Length) SelectedIndex -= delta; if (SelectedIndex >= Elements.Length) SelectedIndex -= delta;

View File

@ -1,56 +0,0 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System;
using System.Drawing;
using OpenTK.Input;
namespace ClassicalSharp.Gui.Widgets {
/// <summary> Represents an individual 2D gui component. </summary>
public abstract class Widget : GuiElement {
public Widget(Game game) : base(game) {
HorizontalAnchor = Anchor.Min;
VerticalAnchor = Anchor.Min;
}
/// <summary> Whether this widget is currently being moused over. </summary>
public bool Active;
/// <summary> Whether this widget is prevented from being interacted with. </summary>
public bool Disabled;
/// <summary> Invoked when this widget is clicked on. Can be null. </summary>
public ClickHandler MenuClick;
/// <summary> Horizontal coordinate of top left corner in pixels. </summary>
public int X;
/// <summary> Vertical coordinate of top left corner in pixels. </summary>
public int Y;
/// <summary> Horizontal length of widget's bounds in pixels. </summary>
public int Width;
/// <summary> Vertical length of widget's bounds in pixels. </summary>
public int Height;
/// <summary> Specifies the horizontal reference point for when the widget is resized. </summary>
public Anchor HorizontalAnchor;
/// <summary> Specifies the vertical reference point for when the widget is resized. </summary>
public Anchor VerticalAnchor;
/// <summary> Horizontal offset from the reference point in pixels. </summary>
public int XOffset;
/// <summary> Vertical offset from the reference point in pixels. </summary>
public int YOffset;
/// <summary> Specifies the boundaries of the widget in pixels. </summary>
public Rectangle Bounds { get { return new Rectangle(X, Y, Width, Height); } }
public virtual void Reposition() {
X = CalcPos(HorizontalAnchor, XOffset, Width, game.Width);
Y = CalcPos(VerticalAnchor, YOffset, Height, game.Height);
}
}
}

View File

@ -4,7 +4,7 @@
<ProjectGuid>{BEB1C785-5CAD-48FF-A886-876BF0A318D4}</ProjectGuid> <ProjectGuid>{BEB1C785-5CAD-48FF-A886-876BF0A318D4}</ProjectGuid>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<OutputType>WinExe</OutputType> <OutputType>Exe</OutputType>
<RootNamespace>ClassicalSharp</RootNamespace> <RootNamespace>ClassicalSharp</RootNamespace>
<AssemblyName>ClassicalSharp</AssemblyName> <AssemblyName>ClassicalSharp</AssemblyName>
<TargetFrameworkVersion>v2.0</TargetFrameworkVersion> <TargetFrameworkVersion>v2.0</TargetFrameworkVersion>
@ -114,7 +114,6 @@
<Compile Include="2D\Screens\Menu\SaveLevelScreen.cs" /> <Compile Include="2D\Screens\Menu\SaveLevelScreen.cs" />
<Compile Include="2D\Screens\Menu\TexturePackScreen.cs" /> <Compile Include="2D\Screens\Menu\TexturePackScreen.cs" />
<Compile Include="2D\Screens\HudScreen.cs" /> <Compile Include="2D\Screens\HudScreen.cs" />
<Compile Include="2D\Screens\Screen.cs" />
<Compile Include="2D\Texture.cs" /> <Compile Include="2D\Texture.cs" />
<Compile Include="2D\Utils\FastBitmap.cs" /> <Compile Include="2D\Utils\FastBitmap.cs" />
<Compile Include="2D\Utils\FastColour.cs" /> <Compile Include="2D\Utils\FastColour.cs" />
@ -132,7 +131,6 @@
<Compile Include="2D\Widgets\SurvivalHotbarWidget.cs" /> <Compile Include="2D\Widgets\SurvivalHotbarWidget.cs" />
<Compile Include="2D\Widgets\TableWidget.cs" /> <Compile Include="2D\Widgets\TableWidget.cs" />
<Compile Include="2D\Widgets\TextWidget.cs" /> <Compile Include="2D\Widgets\TextWidget.cs" />
<Compile Include="2D\Widgets\Widget.cs" />
<Compile Include="Audio\AudioPlayer.cs" /> <Compile Include="Audio\AudioPlayer.cs" />
<Compile Include="Audio\AudioPlayer.Sounds.cs" /> <Compile Include="Audio\AudioPlayer.Sounds.cs" />
<Compile Include="Audio\Soundboard.cs" /> <Compile Include="Audio\Soundboard.cs" />

View File

@ -3,6 +3,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using ClassicalSharp.Events; using ClassicalSharp.Events;
using ClassicalSharp.GraphicsAPI; using ClassicalSharp.GraphicsAPI;
using ClassicalSharp.Gui;
using ClassicalSharp.Gui.Screens; using ClassicalSharp.Gui.Screens;
using ClassicalSharp.Renderers; using ClassicalSharp.Renderers;

View File

@ -1,6 +1,7 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 // Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System; using System;
using ClassicalSharp.Entities; using ClassicalSharp.Entities;
using ClassicalSharp.Gui;
using ClassicalSharp.Gui.Screens; using ClassicalSharp.Gui.Screens;
using ClassicalSharp.Hotkeys; using ClassicalSharp.Hotkeys;
using OpenTK; using OpenTK;

View File

@ -92,78 +92,46 @@ namespace ClassicalSharp {
public BlockID[] Map; public BlockID[] Map;
public void SetDefaultMapping() { public void SetDefaultMapping() {
for (int i = 0; i < Map.Length; i++) Map[i] = (BlockID)i;
for (int i = 0; i < Map.Length; i++) { for (int i = 0; i < Map.Length; i++) {
BlockID mapping = DefaultMapping(i); Map[i] = DefaultMapping(i);
if (game.PureClassic && IsHackBlock(mapping)) mapping = Block.Air;
if (mapping != i) Map[i] = mapping;
} }
} }
BlockID DefaultMapping(int i) { static BlockID[] classicTable = new BlockID[] {
if (i >= Block.CpeCount || i == Block.Air) return Block.Air; Block.Stone, Block.Cobblestone, Block.Brick, Block.Dirt, Block.Wood, Block.Log, Block.Leaves, Block.Glass, Block.Slab,
if (!game.ClassicMode) return (BlockID)i; Block.MossyRocks, Block.Sapling, Block.Dandelion, Block.Rose, Block.BrownMushroom, Block.RedMushroom, Block.Sand, Block.Gravel, Block.Sponge,
Block.Red, Block.Orange, Block.Yellow, Block.Lime, Block.Green, Block.Teal, Block.Aqua, Block.Cyan, Block.Blue,
if (i >= 25 && i <= 40) { Block.Indigo, Block.Violet, Block.Magenta, Block.Pink, Block.Black, Block.Gray, Block.White, Block.CoalOre, Block.IronOre,
return (BlockID)(Block.Red + (i - 25)); Block.GoldOre, Block.Iron, Block.Gold, Block.Bookshelf, Block.TNT, Block.Obsidian,
} };
if (i >= 18 && i <= 21) { static BlockID[] classicHacksTable = new BlockID[] {
return (BlockID)(Block.Dandelion + (i - 18)); Block.Stone, Block.Grass, Block.Cobblestone, Block.Brick, Block.Dirt, Block.Wood, Block.Bedrock, Block.Water, Block.StillWater, Block.Lava,
} Block.StillLava, Block.Log, Block.Leaves, Block.Glass, Block.Slab, Block.MossyRocks, Block.Sapling, Block.Dandelion, Block.Rose, Block.BrownMushroom,
Block.RedMushroom, Block.Sand, Block.Gravel, Block.Sponge, Block.Red, Block.Orange, Block.Yellow, Block.Lime, Block.Green, Block.Teal,
switch (i) { Block.Aqua, Block.Cyan, Block.Blue, Block.Indigo, Block.Violet, Block.Magenta, Block.Pink, Block.Black, Block.Gray, Block.White,
// First row Block.CoalOre, Block.IronOre, Block.GoldOre, Block.DoubleSlab, Block.Iron, Block.Gold, Block.Bookshelf, Block.TNT, Block.Obsidian,
case 3: return Block.Cobblestone; };
case 4: return Block.Brick;
case 5: return Block.Dirt;
case 6: return Block.Wood;
// Second row
case 12: return Block.Log;
case 13: return Block.Leaves;
case 14: return Block.Glass;
case 15: return Block.Slab;
case 16: return Block.MossyRocks;
case 17: return Block.Sapling;
// Third row
case 22: return Block.Sand;
case 23: return Block.Gravel;
case 24: return Block.Sponge;
// Fifth row
case 41: return Block.CoalOre;
case 42: return Block.IronOre;
case 43: return Block.GoldOre;
case 44: return Block.DoubleSlab;
case 45: return Block.Iron;
case 46: return Block.Gold;
case 47: return Block.Bookshelf;
case 48: return Block.TNT;
}
return (BlockID)i;
}
static bool IsHackBlock(BlockID b) { BlockID DefaultMapping(int slot) {
return b == Block.DoubleSlab || b == Block.Bedrock || if (game.PureClassic) {
b == Block.Grass || BlockInfo.IsLiquid[b]; if (slot < 9 * 4 + 6) return classicTable[slot];
} else if (game.ClassicMode) {
if (slot < 10 * 4 + 9) return classicHacksTable[slot];
} else if (slot < Block.MaxCpeBlock) {
return (BlockID)(slot + 1);
}
return Block.Air;
} }
public void AddDefault(BlockID block) { public void AddDefault(BlockID block) {
if (block >= Block.CpeCount || DefaultMapping(block) == block) { if (block >= Block.CpeCount) {
Map[block] = block; Map[block - 1] = block; return;
return;
} }
for (int i = 0; i < Block.CpeCount; i++) { for (int slot = 0; slot < Block.MaxCpeBlock; slot++) {
if (DefaultMapping(i) != block) continue; if (DefaultMapping(slot) != block) continue;
Map[i] = block; return; Map[slot] = block;
} return;
}
public void Reset(BlockID block) {
for (int i = 0; i < Map.Length; i++) {
if (Map[i] == block) Map[i] = DefaultMapping(i);
} }
} }
@ -172,29 +140,5 @@ namespace ClassicalSharp {
if (Map[i] == block) Map[i] = Block.Air; if (Map[i] == block) Map[i] = Block.Air;
} }
} }
public void Insert(int i, BlockID block) {
if (Map[i] == block) return;
// Need to push the old block to a different slot if different block
if (Map[i] != Block.Air) PushToFreeSlots(i);
Map[i] = block;
}
void PushToFreeSlots(int i) {
BlockID block = Map[i];
// The slot was already pushed out in the past
// TODO: find a better way of fixing this
for (int j = 1; j < Map.Length; j++) {
if (j != i && Map[j] == block) return;
}
for (int j = block; j < Map.Length; j++) {
if (Map[j] == Block.Air) { Map[j] = block; return; }
}
for (int j = 1; j < block; j++) {
if (Map[j] == Block.Air) { Map[j] = block; return; }
}
}
} }
} }

View File

@ -1,6 +1,7 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 // Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System; using System;
using ClassicalSharp.Gui.Screens; using ClassicalSharp.Gui.Screens;
using ClassicalSharp.Gui;
using ClassicalSharp.Gui.Widgets; using ClassicalSharp.Gui.Widgets;
using OpenTK.Input; using OpenTK.Input;
using BlockID = System.UInt16; using BlockID = System.UInt16;

View File

@ -1,6 +1,6 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 // Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System; using System;
using ClassicalSharp.Gui.Widgets; using ClassicalSharp.Gui;
using OpenTK.Input; using OpenTK.Input;
using BlockID = System.UInt16; using BlockID = System.UInt16;

View File

@ -2,6 +2,7 @@
using System; using System;
using ClassicalSharp.Entities; using ClassicalSharp.Entities;
using ClassicalSharp.Entities.Mobs; using ClassicalSharp.Entities.Mobs;
using ClassicalSharp.Gui;
using ClassicalSharp.Gui.Screens; using ClassicalSharp.Gui.Screens;
using ClassicalSharp.Gui.Widgets; using ClassicalSharp.Gui.Widgets;
using OpenTK; using OpenTK;

View File

@ -43,7 +43,7 @@ namespace ClassicalSharp.Network.Protocols {
OnBlockUpdated(block, didBlockLight); OnBlockUpdated(block, didBlockLight);
BlockInfo.UpdateCulling(block); BlockInfo.UpdateCulling(block);
game.Inventory.Reset(block); game.Inventory.Remove(block);
if (block < Block.CpeCount) { if (block < Block.CpeCount) {
game.Inventory.AddDefault(block); game.Inventory.AddDefault(block);
} }

View File

@ -406,8 +406,8 @@ namespace ClassicalSharp.Network.Protocols {
BlockID order = reader.ReadBlock(); BlockID order = reader.ReadBlock();
game.Inventory.Remove(block); game.Inventory.Remove(block);
if (order != 255) { if (order != 255 && order != 0) {
game.Inventory.Insert(order, block); game.Inventory.Map[order - 1] = block;
} }
} }

View File

@ -1,5 +1,6 @@
// Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3 // Copyright 2014-2017 ClassicalSharp | Licensed under BSD-3
using System; using System;
using ClassicalSharp.Gui;
using ClassicalSharp.Gui.Screens; using ClassicalSharp.Gui.Screens;
using ClassicalSharp.Entities; using ClassicalSharp.Entities;
using OpenTK; using OpenTK;

View File

@ -99,6 +99,7 @@ namespace ClassicalSharp {
internal static void CleanupMainDirectory() { internal static void CleanupMainDirectory() {
string mapPath = Path.Combine(Program.AppDirectory, "maps"); string mapPath = Path.Combine(Program.AppDirectory, "maps");
Console.WriteLine(mapPath);
if (!Directory.Exists(mapPath)) if (!Directory.Exists(mapPath))
Directory.CreateDirectory(mapPath); Directory.CreateDirectory(mapPath);

View File

@ -41,130 +41,59 @@ void Inventory_SetSelectedBlock(BlockID block) {
Event_RaiseVoid(&UserEvents_HeldBlockChanged); Event_RaiseVoid(&UserEvents_HeldBlockChanged);
} }
bool Inventory_IsHackBlock(BlockID b) { BlockID inv_classicTable[] = {
return b == BLOCK_DOUBLE_SLAB || b == BLOCK_BEDROCK || b == BLOCK_GRASS || Block_IsLiquid[b]; BLOCK_STONE, BLOCK_COBBLE, BLOCK_BRICK, BLOCK_DIRT, BLOCK_WOOD, BLOCK_LOG, BLOCK_LEAVES, BLOCK_GLASS, BLOCK_SLAB,
} BLOCK_MOSSY_ROCKS, BLOCK_SAPLING, BLOCK_DANDELION, BLOCK_ROSE, BLOCK_BROWN_SHROOM, BLOCK_RED_SHROOM, BLOCK_SAND, BLOCK_GRAVEL, BLOCK_SPONGE,
BLOCK_RED, BLOCK_ORANGE, BLOCK_YELLOW, BLOCK_LIME, BLOCK_GREEN, BLOCK_TEAL, BLOCK_AQUA, BLOCK_CYAN, BLOCK_BLUE,
BLOCK_INDIGO, BLOCK_VIOLET, BLOCK_MAGENTA, BLOCK_PINK, BLOCK_BLACK, BLOCK_GRAY, BLOCK_WHITE, BLOCK_COAL_ORE, BLOCK_IRON_ORE,
BLOCK_GOLD_ORE, BLOCK_IRON, BLOCK_GOLD, BLOCK_BOOKSHELF, BLOCK_TNT, BLOCK_OBSIDIAN,
};
BlockID inv_classicHacksTable[] = {
BLOCK_STONE, BLOCK_GRASS, BLOCK_COBBLE, BLOCK_BRICK, BLOCK_DIRT, BLOCK_WOOD, BLOCK_BEDROCK, BLOCK_WATER, BLOCK_STILL_WATER, BLOCK_LAVA,
BLOCK_STILL_LAVA, BLOCK_LOG, BLOCK_LEAVES, BLOCK_GLASS, BLOCK_SLAB, BLOCK_MOSSY_ROCKS, BLOCK_SAPLING, BLOCK_DANDELION, BLOCK_ROSE, BLOCK_BROWN_SHROOM,
BLOCK_RED_SHROOM, BLOCK_SAND, BLOCK_GRAVEL, BLOCK_SPONGE, BLOCK_RED, BLOCK_ORANGE, BLOCK_YELLOW, BLOCK_LIME, BLOCK_GREEN, BLOCK_TEAL,
BLOCK_AQUA, BLOCK_CYAN, BLOCK_BLUE, BLOCK_INDIGO, BLOCK_VIOLET, BLOCK_MAGENTA, BLOCK_PINK, BLOCK_BLACK, BLOCK_GRAY, BLOCK_WHITE,
BLOCK_COAL_ORE, BLOCK_IRON_ORE, BLOCK_GOLD_ORE, BLOCK_DOUBLE_SLAB, BLOCK_IRON, BLOCK_GOLD, BLOCK_BOOKSHELF, BLOCK_TNT, BLOCK_OBSIDIAN,
};
BlockID Inventory_DefaultMapping(Int32 i) { BlockID Inventory_DefaultMapping(int slot) {
#if USE16_BIT if (Game_PureClassic) {
if ((i >= Block_CpeCount && i < 256) || i == BLOCK_AIR) return BLOCK_AIR; if (slot < 9 * 4 + 6) return inv_classicTable[slot];
#else } else if (Game_ClassicMode) {
if (i >= BLOCK_CPE_COUNT || i == BLOCK_AIR) return BLOCK_AIR; if (slot < 10 * 4 + 9) return inv_classicHacksTable[slot];
#endif } else if (slot < BLOCK_MAX_CPE) {
if (!Game_ClassicMode) return (BlockID)i; return (BlockID)(slot + 1);
if (i >= 25 && i <= 40) {
return (BlockID)(BLOCK_RED + (i - 25));
} }
if (i >= 18 && i <= 21) { return BLOCK_AIR;
return (BlockID)(BLOCK_DANDELION + (i - 18));
}
switch (i) {
/* First row */
case 3: return BLOCK_COBBLE;
case 4: return BLOCK_BRICK;
case 5: return BLOCK_DIRT;
case 6: return BLOCK_WOOD;
/* Second row */
case 12: return BLOCK_LOG;
case 13: return BLOCK_LEAVES;
case 14: return BLOCK_GLASS;
case 15: return BLOCK_SLAB;
case 16: return BLOCK_MOSSY_ROCKS;
case 17: return BLOCK_SAPLING;
/* Third row */
case 22: return BLOCK_SAND;
case 23: return BLOCK_GRAVEL;
case 24: return BLOCK_SPONGE;
/* Fifth row */
case 41: return BLOCK_COAL_ORE;
case 42: return BLOCK_IRON_ORE;
case 43: return BLOCK_GOLD_ORE;
case 44: return BLOCK_DOUBLE_SLAB;
case 45: return BLOCK_IRON;
case 46: return BLOCK_GOLD;
case 47: return BLOCK_BOOKSHELF;
case 48: return BLOCK_TNT;
}
return (BlockID)i;
} }
void Inventory_SetDefaultMapping(void) { void Inventory_SetDefaultMapping(void) {
Int32 i; Int32 slot;
for (i = 0; i < Array_Elems(Inventory_Map); i++) { for (slot = 0; slot < Array_Elems(Inventory_Map); slot++) {
Inventory_Map[i] = (BlockID)i; Inventory_Map[slot] = Inventory_DefaultMapping(slot);
}
for (i = 0; i < Array_Elems(Inventory_Map); i++) {
BlockID mapping = Inventory_DefaultMapping(i);
if (Game_PureClassic && Inventory_IsHackBlock(mapping)) {
mapping = BLOCK_AIR;
}
if (mapping != i) Inventory_Map[i] = mapping;
} }
} }
void Inventory_AddDefault(BlockID block) { void Inventory_AddDefault(BlockID block) {
if (block >= BLOCK_CPE_COUNT || Inventory_DefaultMapping(block) == block) { if (block >= BLOCK_CPE_COUNT) {
Inventory_Map[block] = block; Inventory_Map[block - 1] = block; return;
return;
} }
Int32 i; Int32 slot;
for (i = 0; i < BLOCK_CPE_COUNT; i++) { for (slot = 0; slot < BLOCK_MAX_CPE; slot++) {
if (Inventory_DefaultMapping(i) != block) continue; if (Inventory_DefaultMapping(slot) != block) continue;
Inventory_Map[i] = block; Inventory_Map[slot] = block;
return; return;
} }
} }
void Inventory_Reset(BlockID block) {
Int32 i;
for (i = 0; i < Array_Elems(Inventory_Map); i++) {
if (Inventory_Map[i] != block) continue;
Inventory_Map[i] = Inventory_DefaultMapping(i);
}
}
void Inventory_Remove(BlockID block) { void Inventory_Remove(BlockID block) {
Int32 i; Int32 slot;
for (i = 0; i < Array_Elems(Inventory_Map); i++) { for (slot = 0; slot < Array_Elems(Inventory_Map); slot++) {
if (Inventory_Map[i] != block) continue; if (Inventory_Map[slot] == block) Inventory_Map[slot] = BLOCK_AIR;
Inventory_Map[i] = BLOCK_AIR;
} }
} }
void Inventory_PushToFreeSlots(Int32 i) {
BlockID block = Inventory_Map[i];
Int32 j;
/* The slot was already pushed out in the past
TODO: find a better way of fixing this */
for (j = 1; j < Array_Elems(Inventory_Map); j++) {
if (j != i && Inventory_Map[j] == block) return;
}
for (j = block; j < Array_Elems(Inventory_Map); j++) {
if (Inventory_Map[j] == BLOCK_AIR) {
Inventory_Map[j] = block; return;
}
}
for (j = 1; j < block; j++) {
if (Inventory_Map[j] == BLOCK_AIR) {
Inventory_Map[j] = block; return;
}
}
}
void Inventory_Insert(Int32 i, BlockID block) {
if (Inventory_Map[i] == block) return;
/* Need to push the old block to a different slot if different block. */
if (Inventory_Map[i] != BLOCK_AIR) Inventory_PushToFreeSlots(i);
Inventory_Map[i] = block;
}
void Inventory_ResetState(void) { void Inventory_ResetState(void) {
Inventory_SetDefaultMapping(); Inventory_SetDefaultMapping();
Inventory_CanChangeHeldBlock = true; Inventory_CanChangeHeldBlock = true;

View File

@ -81,10 +81,10 @@ void Menu_MakeDefaultBack(ButtonWidget* widget, bool toGame, FontDesc* font, Wid
Int32 width = Game_UseClassicOptions ? 400 : 200; Int32 width = Game_UseClassicOptions ? 400 : 200;
if (toGame) { if (toGame) {
String msg = String_FromConst("Back to game"); String msg = String_FromConst("Back to game");
Screen_MakeBack(widget, width, &msg, 25, font, onClick); Menu_MakeBack(widget, width, &msg, 25, font, onClick);
} else { } else {
String msg = String_FromConst("Cancel"); String msg = String_FromConst("Cancel");
Screen_MakeBack(widget, width, &msg, 25, font, onClick); Menu_MakeBack(widget, width, &msg, 25, font, onClick);
} }
} }
@ -217,7 +217,7 @@ void ListScreen_ContextRecreated(void* obj) {
ListScreen_Make(screen, 5, -220, 0, &lArrow, ListScreen_MoveBackwards); ListScreen_Make(screen, 5, -220, 0, &lArrow, ListScreen_MoveBackwards);
String rArrow = String_FromConst(">"); String rArrow = String_FromConst(">");
ListScreen_Make(screen, 6, 220, 0, &rArrow, ListScreen_MoveForwards); ListScreen_Make(screen, 6, 220, 0, &rArrow, ListScreen_MoveForwards);
Screen_MakeDefaultBack(&screen->Buttons[7], false, &screen->Font, Menu_SwitchPause); Menu_MakeDefaultBack(&screen->Buttons[7], false, &screen->Font, Menu_SwitchPause);
screen->Widgets[0] = (Widget*)(&screen->Title); screen->Widgets[0] = (Widget*)(&screen->Title);
for (i = 0; i < FILES_SCREEN_BUTTONS; i++) { for (i = 0; i < FILES_SCREEN_BUTTONS; i++) {
@ -495,7 +495,7 @@ bool PauseScreen_HandlesKeyDown(GuiElement* elem, Key key) {
Screen* PauseScreen_MakeInstance(void) { Screen* PauseScreen_MakeInstance(void) {
PauseScreen* screen = &PauseScreen_Instance; PauseScreen* screen = &PauseScreen_Instance;
MenuScreen_MakeInstance(&screen->Base, screen->Widgets, Array_Elems(screen->Buttons), PauseScreen_ContextRecreated); MenuScreen_MakeInstance(&screen->Base, screen->Widgets, Array_Elems(screen->Widgets), PauseScreen_ContextRecreated);
PauseScreen_VTABLE = *screen->Base.VTABLE; PauseScreen_VTABLE = *screen->Base.VTABLE;
screen->Base.VTABLE = &PauseScreen_VTABLE; screen->Base.VTABLE = &PauseScreen_VTABLE;
@ -504,3 +504,108 @@ Screen* PauseScreen_MakeInstance(void) {
screen->Base.VTABLE->HandlesKeyDown = PauseScreen_HandlesKeyDown; screen->Base.VTABLE->HandlesKeyDown = PauseScreen_HandlesKeyDown;
return screen; return screen;
} }
typedef struct OptionsGroupScreen_ {
MenuScreen Base;
Widget* Widgets[9];
ButtonWidget Buttons[8];
TextWidget Desc;
Int32 SelectedI;
} OptionsGroupScreen;
GuiElementVTABLE OptionsGroupScreen_VTABLE;
OptionsGroupScreen OptionsGroupScreen_Instance;
Screen* OptionsGroupScreen_MakeInstance(void) {
OptionsGroupScreen* screen = &OptionsGroupScreen_Instance;
MenuScreen_MakeInstance(&screen->Base, screen->Widgets, Array_Elems(screen->Widgets), OptionsGroupScreen_ContextRecreated);
OptionsGroupScreen_VTABLE = *screen->Base.VTABLE;
screen->Base.VTABLE = &OptionsGroupScreen_VTABLE;
screen->Base.VTABLE->Init = OptionsGroupScreen_Init;
screen->Base.VTABLE->Free = OptionsGroupScreen_Free;
screen->Base.VTABLE->HandlesMouseMove = OptionsGroupScreen_HandlesMouseMove;
/* Pause screen key down behaviour is same for options group screen*/
screen->Base.VTABLE->HandlesKeyDown = PauseScreen_HandlesKeyDown;
screen->SelectedI = -1;
return screen;
}
void OptionsGroupScreen_Init(GuiElement* elem) {
MenuScreen_Init(elem);
game.Events.HackPermissionsChanged += CheckHacksAllowed;
titleFont = new Font(game.FontName, 16, FontStyle.Bold);
regularFont = new Font(game.FontName, 16);
ContextRecreated();
}
void OptionsGroupScreen_ContextRecreated(void* obj) {
OptionsGroupScreen* screen = (OptionsGroupScreen*)obj;
widgets = new Widget[]{
Make(-1, -100, "Misc options...", SwitchMiscOptions),
Make(-1, -50, "Gui options...", SwitchGuiOptions),
Make(-1, 0, "Graphics options...", SwitchGfxOptions),
Make(-1, 50, "Controls...", SwitchControls),
Make(1, -50, "Hacks settings...", SwitchHacksOptions),
Make(1, 0, "Env settings...", SwitchEnvOptions),
Make(1, 50, "Nostalgia options...", SwitchNostalgiaOptions),
MakeBack(false, titleFont, SwitchPause),
null, // description text widget placeholder
};
if (screen->SelectedI >= 0) {
MakeDescWidget(descriptions[selectedI]);
}
CheckHacksAllowed(null, null);
}
static void SwitchMiscOptions(Game g, Widget w) { g.Gui.SetNewScreen(new MiscOptionsScreen(g)); }
static void SwitchGuiOptions(Game g, Widget w) { g.Gui.SetNewScreen(new GuiOptionsScreen(g)); }
static void SwitchGfxOptions(Game g, Widget w) { g.Gui.SetNewScreen(new GraphicsOptionsScreen(g)); }
static void SwitchControls(Game g, Widget w) { g.Gui.SetNewScreen(new NormalKeyBindingsScreen(g)); }
static void SwitchHacksOptions(Game g, Widget w) { g.Gui.SetNewScreen(new HacksSettingsScreen(g)); }
static void SwitchEnvOptions(Game g, Widget w) { g.Gui.SetNewScreen(new EnvSettingsScreen(g)); }
static void SwitchNostalgiaOptions(Game g, Widget w) { g.Gui.SetNewScreen(new NostalgiaScreen(g)); }
void CheckHacksAllowed(object sender, EventArgs e) {
widgets[5].Disabled = !game.LocalPlayer.Hacks.CanAnyHacks; // env settings
}
void MakeDescWidget(string text) {
widgets[widgets.Length - 1] = TextWidget.Create(game, text, regularFont)
.SetLocation(Anchor.Centre, Anchor.Centre, 0, 100);
}
ButtonWidget Make(int dir, int y, string text, ClickHandler onClick) {
return ButtonWidget.Create(game, 300, text, titleFont, onClick)
.SetLocation(Anchor.Centre, Anchor.Centre, dir * 160, y);
}
bool OptionsGroupScreen_HandlesMouseMove(GuiElement* elem, Int32 x, Int32 y) {
int i = HandleMouseMove(widgets, mouseX, mouseY);
if (i == -1 || i == selectedI) return true;
if (i >= Array_Elems(OptionsGroupScreen_descs)) return true;
selectedI = i;
Widget desc = widgets[widgets.Length - 1];
if (desc != null) desc.Dispose();
MakeDescWidget(descriptions[i]);
return true;
}
void OptionsGroupScreen_Free(GuiElement* elem) {
MenuScreen_Free(elem);
game.Events.HackPermissionsChanged -= CheckHacksAllowed;
}
const UInt8* OptionsGroupScreen_descs[7] = {
"&eMusic/Sound, view bobbing, and more",
"&eChat options, gui scale, font settings, and more",
"&eFPS limit, view distance, entity names/shadows",
"&eSet key bindings, bind keys to act as mouse clicks",
"&eHacks allowed, jump settings, and more",
"&eEnv colours, water level, weather, and more",
"&eSettings for resembling the original classic",
};

View File

@ -576,6 +576,7 @@ void TableWidget_RecreateDescTex(TableWidget* widget) {
void TableWidget_MakeDescTex(TableWidget* widget, BlockID block) { void TableWidget_MakeDescTex(TableWidget* widget, BlockID block) {
Gfx_DeleteTexture(&widget->DescTex.ID); Gfx_DeleteTexture(&widget->DescTex.ID);
if (block == BLOCK_AIR) return;
UInt8 descBuffer[String_BufferSize(STRING_SIZE * 2)]; UInt8 descBuffer[String_BufferSize(STRING_SIZE * 2)];
String desc = String_InitAndClearArray(descBuffer); String desc = String_InitAndClearArray(descBuffer);