From 0320bbc6a650743dbbca0fd8cac035ddad7de8c0 Mon Sep 17 00:00:00 2001 From: MasterGordon Date: Tue, 20 Dec 2022 22:59:09 +0100 Subject: [PATCH] added inventory events --- .editorconfig | 3 + Mine2d/.vscode/settings.json | 2 + Mine2d/engine/EventPublisher.cs | 15 ++-- .../system/annotations/EventListener.cs | 6 ++ Mine2d/game/frontend/events/InventoryInput.cs | 34 +++++++- Mine2d/game/frontend/inventory/Inventory.cs | 14 ++++ .../frontend/inventory/InventoryRegistry.cs | 8 +- .../frontend/inventory/InventoryRenderer.cs | 11 --- .../inventory/PlayerInventoryRenderer.cs | 83 ++++++++++++++----- .../frontend/renderer/InventoryRenderer.cs | 4 +- Mine2d/game/state/FrontendGameState.cs | 4 +- Mine2d/game/state/PlayerInventory.cs | 6 ++ 12 files changed, 140 insertions(+), 50 deletions(-) create mode 100644 Mine2d/.vscode/settings.json create mode 100644 Mine2d/game/frontend/inventory/Inventory.cs delete mode 100644 Mine2d/game/frontend/inventory/InventoryRenderer.cs diff --git a/.editorconfig b/.editorconfig index b81ceac..a7511ca 100644 --- a/.editorconfig +++ b/.editorconfig @@ -81,3 +81,6 @@ resharper_suggest_var_or_type_simple_types_highlighting = hint resharper_web_config_module_not_resolved_highlighting = warning resharper_web_config_type_not_resolved_highlighting = warning resharper_web_config_wrong_module_highlighting = warning + +# ignore RCS1102 +dotnet_diagnostic.RCS1102.severity = none \ No newline at end of file diff --git a/Mine2d/.vscode/settings.json b/Mine2d/.vscode/settings.json new file mode 100644 index 0000000..7a73a41 --- /dev/null +++ b/Mine2d/.vscode/settings.json @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/Mine2d/engine/EventPublisher.cs b/Mine2d/engine/EventPublisher.cs index b6b0673..82bb10d 100644 --- a/Mine2d/engine/EventPublisher.cs +++ b/Mine2d/engine/EventPublisher.cs @@ -1,3 +1,4 @@ +using System.Reflection; using Mine2d.engine.system; using Mine2d.engine.system.annotations; using Mine2d.game.core.extensions; @@ -23,7 +24,7 @@ public class EventPublisher { var types = this.GetType().Assembly .GetTypesSafe() - .Where(t => t.Namespace != null && t.Namespace.StartsWith("Mine2d.game.frontend.events", StringComparison.Ordinal)); + .Where(t => t.Namespace?.StartsWith("Mine2d.game.frontend.events", StringComparison.Ordinal) == true); foreach (var type in types) { var methods = type.GetMethods() @@ -57,7 +58,7 @@ public class EventPublisher foreach (var (_, value) in this.eventListeners) { - value.Sort((a, b) => a.Priority.CompareTo(b.Priority)); + value.Sort((a, b) => b.Priority.CompareTo(a.Priority)); } } @@ -75,11 +76,11 @@ public class EventPublisher public void Publish(EventType eventType, SDL_Event e) { - if (this.eventListeners.ContainsKey(eventType)) + if (this.eventListeners.TryGetValue(eventType, out var value)) { try { - foreach (var action in this.eventListeners[eventType]) + foreach (var action in value) { if (action.Del.Method.GetParameters().Length == 0) { @@ -91,9 +92,8 @@ public class EventPublisher } } } - catch (CancelEventException) + catch (TargetInvocationException ex) when (ex.InnerException is CancelEventException) { - } } } @@ -101,7 +101,8 @@ public class EventPublisher public class CancelEventException : Exception { - public CancelEventException(string message) : base(message) + [System.Diagnostics.DebuggerHidden] + public CancelEventException() : base("Event cancelled") { } } diff --git a/Mine2d/engine/system/annotations/EventListener.cs b/Mine2d/engine/system/annotations/EventListener.cs index a8db8bc..9b99983 100644 --- a/Mine2d/engine/system/annotations/EventListener.cs +++ b/Mine2d/engine/system/annotations/EventListener.cs @@ -10,4 +10,10 @@ public class EventListenerAttribute : Attribute { this.Type = type; } + + public EventListenerAttribute(EventType type, EventPriority priority) + { + this.Type = type; + this.Priority = priority; + } } diff --git a/Mine2d/game/frontend/events/InventoryInput.cs b/Mine2d/game/frontend/events/InventoryInput.cs index 31302a8..f54f1e2 100644 --- a/Mine2d/game/frontend/events/InventoryInput.cs +++ b/Mine2d/game/frontend/events/InventoryInput.cs @@ -1,3 +1,4 @@ +using Mine2d.engine; using Mine2d.engine.system; using Mine2d.engine.system.annotations; using Mine2d.game.state; @@ -40,17 +41,42 @@ public class InventoryInput } } - [EventListener(EventType.KeyDown)] + [EventListener(EventType.KeyDown, EventPriority.Highest)] public static void OnKeyDownOpenInventory(SDL_Event e) { var frontendGameState = Context.Get().FrontendGameState; if(e.key.keysym.sym == SDL_Keycode.SDLK_TAB) { - if(frontendGameState.OpenInventory != Inventory.Player) { - frontendGameState.OpenInventory = Inventory.Player; + if(frontendGameState.OpenInventory != InventoryKind.Player) { + frontendGameState.OpenInventory = InventoryKind.Player; } else { - frontendGameState.OpenInventory = Inventory.None; + frontendGameState.OpenInventory = InventoryKind.None; } } + if(frontendGameState.OpenInventory != InventoryKind.None) + { + throw new CancelEventException(); + } + } + + [EventListener(EventType.KeyUp, EventPriority.Highest)] + public static void OnKeyUpOpenInventory(SDL_Event e) + { + var frontendGameState = Context.Get().FrontendGameState; + if(frontendGameState.OpenInventory != InventoryKind.None) + { + throw new CancelEventException(); + } + } + + [EventListener(EventType.MouseButtonDown, EventPriority.Highest)] + public static void OnMouseButtonDownOpenInventory(SDL_Event e) + { + var frontendGameState = Context.Get().FrontendGameState; + Context.Get().InventoryRegistry.GetInventory(frontendGameState.OpenInventory)?.OnClick(e); + if(frontendGameState.OpenInventory != InventoryKind.None) + { + throw new CancelEventException(); + } } } diff --git a/Mine2d/game/frontend/inventory/Inventory.cs b/Mine2d/game/frontend/inventory/Inventory.cs new file mode 100644 index 0000000..4165e93 --- /dev/null +++ b/Mine2d/game/frontend/inventory/Inventory.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading.Tasks; +using Mine2d.engine; + +namespace Mine2d.game.frontend.inventory; + +public class Inventory : IRenderer +{ + public virtual void Render() { } + public virtual void OnKeyDown(SDL_Event e) { } + public virtual void OnClick(SDL_Event e) { } +} \ No newline at end of file diff --git a/Mine2d/game/frontend/inventory/InventoryRegistry.cs b/Mine2d/game/frontend/inventory/InventoryRegistry.cs index c484ae4..265bdaa 100644 --- a/Mine2d/game/frontend/inventory/InventoryRegistry.cs +++ b/Mine2d/game/frontend/inventory/InventoryRegistry.cs @@ -8,15 +8,17 @@ namespace Mine2d.game.frontend.inventory; public class InventoryRegistry { - private readonly Dictionary inventoryRenderers = new(); + private readonly Dictionary inventoryRenderers = new(); public InventoryRegistry() { - this.inventoryRenderers.Add(Inventory.Player, new PlayerInventoryRenderer()); + this.inventoryRenderers.Add(InventoryKind.Player, new PlayerInventoryRenderer()); } - public IInventoryRenderer GetRenderer(Inventory inventory) + public Inventory GetInventory(InventoryKind inventory) { + if(!this.inventoryRenderers.ContainsKey(inventory)) + return null; return this.inventoryRenderers[inventory]; } } diff --git a/Mine2d/game/frontend/inventory/InventoryRenderer.cs b/Mine2d/game/frontend/inventory/InventoryRenderer.cs deleted file mode 100644 index 27df789..0000000 --- a/Mine2d/game/frontend/inventory/InventoryRenderer.cs +++ /dev/null @@ -1,11 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Mine2d.engine; - -namespace Mine2d.game.frontend.inventory; - -public interface IInventoryRenderer : IRenderer -{ -} \ No newline at end of file diff --git a/Mine2d/game/frontend/inventory/PlayerInventoryRenderer.cs b/Mine2d/game/frontend/inventory/PlayerInventoryRenderer.cs index 252fd67..424ec79 100644 --- a/Mine2d/game/frontend/inventory/PlayerInventoryRenderer.cs +++ b/Mine2d/game/frontend/inventory/PlayerInventoryRenderer.cs @@ -1,12 +1,15 @@ +using System.Diagnostics; using Mine2d.game.core; namespace Mine2d.game.frontend.inventory { - public class PlayerInventoryRenderer : IInventoryRenderer + + public class PlayerInventoryRenderer : Inventory { private IntPtr texture = IntPtr.Zero; + private int x, y; - public void Render() + public override void Render() { var ctx = Context.Get(); if (this.texture == IntPtr.Zero) @@ -19,9 +22,9 @@ namespace Mine2d.game.frontend.inventory height *= uiScale; var extraSlotsWidth = InventoryConstants.ExtraSlotsWidth * uiScale; var (windowWidth, windowHeight) = (ctx.FrontendGameState.WindowWidth, ctx.FrontendGameState.WindowHeight); - var x = (windowWidth - (width - extraSlotsWidth)) / 2; - var y = (windowHeight - height) / 2; - ctx.Renderer.DrawTexture(this.texture, x, y, width, height); + this.x = (windowWidth - (width - extraSlotsWidth)) / 2; + this.y = (windowHeight - height) / 2; + ctx.Renderer.DrawTexture(this.texture, this.x, this.y, width, height); var player = PlayerEntity.GetSelf(); var inventory = player.Inventory.Inventory; @@ -38,20 +41,21 @@ namespace Mine2d.game.frontend.inventory var itemTexture = stack.GetTexture(); ctx.Renderer.DrawTexture( itemTexture, - ((4 + (i * 22)) * uiScale) + x, - (4 * uiScale) + y, + ((4 + (i * 21)) * uiScale) + this.x, + (4 * uiScale) + this.y, 16 * uiScale, 16 * uiScale ); ctx.Renderer.DrawText( "" + stack.Count, - ((4 + (i * 22)) * uiScale) + x, - (14 * uiScale) + y + ((4 + (i * 21)) * uiScale) + this.x, + (14 * uiScale) + this.y ); - if (cursorPosition.X >= ((4 + (i * 22)) * uiScale) + x - && cursorPosition.X <= ((4 + (i * 22)) * uiScale) + x + (16 * uiScale) - && cursorPosition.Y >= (4 * uiScale) + y - && cursorPosition.Y <= (4 * uiScale) + y + (16 * uiScale) + if (player.Inventory.cursor == null && + cursorPosition.X >= ((4 + (i * 21)) * uiScale) + this.x + && cursorPosition.X <= ((4 + (i * 21)) * uiScale) + this.x + (16 * uiScale) + && cursorPosition.Y >= (4 * uiScale) + this.y + && cursorPosition.Y <= (4 * uiScale) + this.y + (16 * uiScale) ) { Context.Get().FrontendGameState.Tooltip = stack.GetName(); @@ -68,25 +72,62 @@ namespace Mine2d.game.frontend.inventory var itemTexture = stack.GetTexture(); ctx.Renderer.DrawTexture( itemTexture, - ((4 + ((i % 9) * 22)) * uiScale) + x, - ((4 + 21 + ((i / 9) * 22)) * uiScale) + y, + ((4 + ((i % 9) * 21)) * uiScale) + this.x, + ((4 + 21 + ((i / 9) * 21)) * uiScale) + this.y, 16 * uiScale, 16 * uiScale ); ctx.Renderer.DrawText( "" + stack.Count, - ((4 + ((i % 9) * 22)) * uiScale) + x, - ((14 + 21 + ((i / 9) * 22)) * uiScale) + y + ((4 + ((i % 9) * 21)) * uiScale) + this.x, + ((14 + 21 + ((i / 9) * 21)) * uiScale) + this.y ); - if (cursorPosition.X >= ((4 + ((i % 9) * 22)) * uiScale) + x - && cursorPosition.X <= ((4 + ((i % 9) * 22)) * uiScale) + x + (16 * uiScale) - && cursorPosition.Y >= ((4 + 21 + ((i / 9) * 22)) * uiScale) + y - && cursorPosition.Y <= ((4 + 21 + ((i / 9) * 22)) * uiScale) + y + (16 * uiScale) + if (player.Inventory.cursor == null && + cursorPosition.X >= ((4 + ((i % 9) * 21)) * uiScale) + this.x + && cursorPosition.X <= ((4 + ((i % 9) * 21)) * uiScale) + this.x + (16 * uiScale) + && cursorPosition.Y >= ((4 + 21 + ((i / 9) * 21)) * uiScale) + this.y + && cursorPosition.Y <= ((4 + 21 + ((i / 9) * 21)) * uiScale) + this.y + (16 * uiScale) ) { Context.Get().FrontendGameState.Tooltip = stack.GetName(); } } } + + public override void OnClick(SDL_Event e) + { + var cursorPosition = Context.Get().FrontendGameState.CursorPosition; + // is hotbar + if (cursorPosition.X >= this.x + (4 * Context.Get().FrontendGameState.Settings.UiScale) + && cursorPosition.X <= this.x + (4 * Context.Get().FrontendGameState.Settings.UiScale) + (21 * 9 * Context.Get().FrontendGameState.Settings.UiScale) + && cursorPosition.Y >= this.y + (4 * Context.Get().FrontendGameState.Settings.UiScale) + && cursorPosition.Y <= this.y + (4 * Context.Get().FrontendGameState.Settings.UiScale) + (21 * Context.Get().FrontendGameState.Settings.UiScale) + ) + { + var player = PlayerEntity.GetSelf(); + var hotbar = player.Inventory.Hotbar; + var index = (int)((cursorPosition.X - (this.x + (4 * Context.Get().FrontendGameState.Settings.UiScale))) / (21 * Context.Get().FrontendGameState.Settings.UiScale)); + if (e.button.button == SDL_BUTTON_LEFT) + { + player.Inventory.SwapWithCursor(index, hotbar); + } + } + // is inventory + if (cursorPosition.X >= this.x + (4 * Context.Get().FrontendGameState.Settings.UiScale) + && cursorPosition.X <= this.x + (4 * Context.Get().FrontendGameState.Settings.UiScale) + (21 * 9 * Context.Get().FrontendGameState.Settings.UiScale) + && cursorPosition.Y >= this.y + (4 * Context.Get().FrontendGameState.Settings.UiScale) + (21 * Context.Get().FrontendGameState.Settings.UiScale) + && cursorPosition.Y <= this.y + (4 * Context.Get().FrontendGameState.Settings.UiScale) + (21 * 5 * Context.Get().FrontendGameState.Settings.UiScale) + ) + { + var player = PlayerEntity.GetSelf(); + var inventory = player.Inventory.Inventory; + var index = (int)((cursorPosition.X - (this.x + (4 * Context.Get().FrontendGameState.Settings.UiScale))) / (21 * Context.Get().FrontendGameState.Settings.UiScale)) + + ((int)((cursorPosition.Y - (this.y + (4 * Context.Get().FrontendGameState.Settings.UiScale) + (21 * Context.Get().FrontendGameState.Settings.UiScale))) / (21 * Context.Get().FrontendGameState.Settings.UiScale)) * 9); + if (e.button.button == SDL_BUTTON_LEFT) + { + player.Inventory.SwapWithCursor(index, inventory); + } + } + } } } diff --git a/Mine2d/game/frontend/renderer/InventoryRenderer.cs b/Mine2d/game/frontend/renderer/InventoryRenderer.cs index 789cb95..f16fd7a 100644 --- a/Mine2d/game/frontend/renderer/InventoryRenderer.cs +++ b/Mine2d/game/frontend/renderer/InventoryRenderer.cs @@ -8,11 +8,11 @@ namespace Mine2d.game.frontend.renderer public void Render() { var ctx = Context.Get(); var inventory = ctx.FrontendGameState.OpenInventory; - if(inventory == Inventory.None) return; + if(inventory == InventoryKind.None) return; ctx.Renderer.SetColor(0, 0, 0, 200); ctx.Renderer.SetDrawBlendMode(SDL_BlendMode.SDL_BLENDMODE_BLEND); ctx.Renderer.DrawRect(0, 0, ctx.FrontendGameState.WindowWidth, ctx.FrontendGameState.WindowHeight); - var inventoryRenderer = ctx.InventoryRegistry.GetRenderer(inventory); + var inventoryRenderer = ctx.InventoryRegistry.GetInventory(inventory); inventoryRenderer.Render(); } } diff --git a/Mine2d/game/state/FrontendGameState.cs b/Mine2d/game/state/FrontendGameState.cs index 07fa2f6..49b77a9 100644 --- a/Mine2d/game/state/FrontendGameState.cs +++ b/Mine2d/game/state/FrontendGameState.cs @@ -2,7 +2,7 @@ using Mine2d.game.core; namespace Mine2d.game.state; -public enum Inventory { +public enum InventoryKind { None, Player } @@ -20,7 +20,7 @@ public class FrontendGameState public string PlayerName { get; set; } = "Player"; public int HotbarIndex { get; set; } public string Tooltip { get; set; } = "Test"; - public Inventory OpenInventory { get; set; } = Inventory.None; + public InventoryKind OpenInventory { get; set; } = InventoryKind.None; } public class Settings diff --git a/Mine2d/game/state/PlayerInventory.cs b/Mine2d/game/state/PlayerInventory.cs index 57e4643..20d241e 100644 --- a/Mine2d/game/state/PlayerInventory.cs +++ b/Mine2d/game/state/PlayerInventory.cs @@ -7,6 +7,7 @@ public class PlayerInventory { public ItemStack[] Hotbar { get; set; } = new ItemStack[9]; public ItemStack[] Inventory { get; set; } = new ItemStack[5 * 9]; + public ItemStack cursor { get; set; } public bool PickupItemStack(ItemStack itemStack) { @@ -30,4 +31,9 @@ public class PlayerInventory } return true; } + + public void SwapWithCursor(int slot, ItemStack[] inventory) + { + (inventory[slot], this.cursor) = (this.cursor, inventory[slot]); + } }