diff --git a/src/main/java/ru/windcorp/progressia/client/Client.java b/src/main/java/ru/windcorp/progressia/client/Client.java index 6bae089..3251dff 100644 --- a/src/main/java/ru/windcorp/progressia/client/Client.java +++ b/src/main/java/ru/windcorp/progressia/client/Client.java @@ -25,21 +25,33 @@ import ru.windcorp.progressia.client.comms.DefaultClientCommsListener; import ru.windcorp.progressia.client.comms.ServerCommsChannel; import ru.windcorp.progressia.client.events.ClientEvent; import ru.windcorp.progressia.client.events.NewLocalEntityEvent; +import ru.windcorp.progressia.client.graphics.GUI; import ru.windcorp.progressia.client.graphics.world.Camera; import ru.windcorp.progressia.client.graphics.world.EntityAnchor; +import ru.windcorp.progressia.client.graphics.world.LayerWorld; import ru.windcorp.progressia.client.graphics.world.LocalPlayer; +import ru.windcorp.progressia.client.graphics.world.hud.HUDManager; import ru.windcorp.progressia.client.world.WorldRender; import ru.windcorp.progressia.common.util.crash.ReportingEventBus; import ru.windcorp.progressia.common.world.DefaultWorldData; +import ru.windcorp.progressia.test.LayerAbout; +import ru.windcorp.progressia.test.LayerTestUI; public class Client { private final WorldRender world; + + private final LayerWorld layerWorld = new LayerWorld(this); + private final LayerTestUI layerTestUI = new LayerTestUI(); + private final LayerAbout layerAbout = new LayerAbout(); + private final LocalPlayer localPlayer = new LocalPlayer(this); private final Camera camera = new Camera((float) Math.toRadians(70)); private final EventBus eventBus = ReportingEventBus.create("ClientEvents"); + + private final HUDManager hudManager = new HUDManager(this); private final ServerCommsChannel comms; @@ -50,6 +62,20 @@ public class Client { comms.addListener(new DefaultClientCommsListener(this)); subscribe(this); } + + public void install() { + GUI.addBottomLayer(layerWorld); + GUI.addTopLayer(layerTestUI); + hudManager.install(); + GUI.addTopLayer(layerAbout); + } + + public void remove() { + GUI.removeLayer(layerWorld); + GUI.removeLayer(layerTestUI); + hudManager.remove(); + GUI.removeLayer(layerAbout); + } public WorldRender getWorld() { return world; @@ -70,6 +96,10 @@ public class Client { public ServerCommsChannel getComms() { return comms; } + + public HUDManager getHUD() { + return hudManager; + } @Subscribe private void onLocalPlayerEntityChanged(NewLocalEntityEvent e) { diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java index fe9153a..fae2b5d 100644 --- a/src/main/java/ru/windcorp/progressia/client/ClientState.java +++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java @@ -19,15 +19,9 @@ package ru.windcorp.progressia.client; import ru.windcorp.progressia.client.comms.localhost.LocalServerCommsChannel; -import ru.windcorp.progressia.client.graphics.GUI; -import ru.windcorp.progressia.client.graphics.world.LayerWorld; -import ru.windcorp.progressia.client.graphics.world.hud.LayerHUD; import ru.windcorp.progressia.common.world.DefaultWorldData; import ru.windcorp.progressia.server.ServerState; -import ru.windcorp.progressia.test.LayerAbout; -import ru.windcorp.progressia.test.LayerTestUI; import ru.windcorp.progressia.test.TestContent; -import ru.windcorp.progressia.test.inv.TestInventoryGUIManager; public class ClientState { @@ -55,12 +49,7 @@ public class ClientState { setInstance(client); - GUI.addBottomLayer(new LayerWorld(client)); - GUI.addTopLayer(new LayerTestUI()); - GUI.addTopLayer(new LayerHUD(client)); - TestInventoryGUIManager.setup(); - GUI.addTopLayer(new LayerAbout()); - + client.install(); } private ClientState() { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java index 79cfddc..724c80a 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Component.java @@ -43,6 +43,7 @@ import ru.windcorp.progressia.client.graphics.gui.event.HoverEvent; import ru.windcorp.progressia.client.graphics.gui.event.ParentChangedEvent; import ru.windcorp.progressia.client.graphics.input.InputEvent; import ru.windcorp.progressia.client.graphics.input.KeyEvent; +import ru.windcorp.progressia.client.graphics.input.KeyMatcher; import ru.windcorp.progressia.client.graphics.input.bus.Input; import ru.windcorp.progressia.client.graphics.input.bus.InputBus; import ru.windcorp.progressia.client.graphics.input.bus.InputListener; @@ -557,13 +558,36 @@ public class Component extends Named { inputBus.register(type, handlesConsumed, listener); } - public void addListener(Class type, InputListener listener) { + public void addListener(Class type, InputListener listener) { if (inputBus == null) { inputBus = new InputBus(); } inputBus.register(type, listener); } + + public void addListener(Class type, Runnable listener) { + addListener(type, event -> { + listener.run(); + return true; + }); + } + + public void addListener(KeyMatcher matcher, InputListener listener) { + addListener(KeyEvent.class, event -> { + if (matcher.test(event)) { + return listener.handle(event); + } + return false; + }); + } + + public void addListener(KeyMatcher matcher, Runnable listener) { + addListener(matcher, event -> { + listener.run(); + return true; + }); + } public void removeListener(InputListener listener) { if (inputBus != null) { diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java index a760106..c2dee12 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Components.java @@ -17,6 +17,8 @@ */ package ru.windcorp.progressia.client.graphics.gui; +import java.util.function.BooleanSupplier; + import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; public class Components { @@ -24,6 +26,10 @@ public class Components { public static Component center(Component c) { return new Group(c.getName() + ".Centerer", new LayoutAlign(), c); } + + public static Component hide(Component c, BooleanSupplier shouldHide) { + return new Hider(c.getName() + ".Hider", c, shouldHide); + } private Components() { } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/gui/Hider.java b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Hider.java new file mode 100644 index 0000000..849a134 --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/gui/Hider.java @@ -0,0 +1,60 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.client.graphics.gui; + +import java.util.function.BooleanSupplier; + +import ru.windcorp.progressia.client.graphics.flat.RenderTarget; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; +import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.client.graphics.model.Renderable; + +public class Hider extends Component { + + private final BooleanSupplier shouldHide; + private final Component contents; + + public Hider(String name, Component contents, BooleanSupplier shouldHide) { + super(name); + this.contents = contents; + this.shouldHide = shouldHide; + + setLayout(new LayoutFill()); + addChild(contents); + } + + @Override + protected void handleInput(Input input) { + if (shouldHide.getAsBoolean()) { + return; + } + + super.handleInput(input); + } + + @Override + protected void assembleChildren(RenderTarget target) { + Renderable renderable = contents.assembleToRenderable(); + target.addCustomRenderer(renderer -> { + if (!shouldHide.getAsBoolean()) { + renderable.render(renderer); + } + }); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java index 6fedcd6..6d96ca2 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/input/KeyMatcher.java @@ -18,22 +18,33 @@ package ru.windcorp.progressia.client.graphics.input; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.function.Predicate; import org.lwjgl.glfw.GLFW; -public class KeyMatcher { +import ru.windcorp.progressia.common.util.crash.CrashReports; + +public class KeyMatcher implements Predicate { + + private static final int ANY_ACTION = -1; private final int key; private final int mods; + private final int action; - protected KeyMatcher(int key, int mods) { + protected KeyMatcher(int key, int mods, int action) { this.key = key; this.mods = mods; + this.action = action; } - public boolean matches(KeyEvent event) { - if (!event.isPress()) + @Override + public boolean test(KeyEvent event) { + if (action != ANY_ACTION && event.getAction() != action) return false; if (event.getKey() != getKey()) return false; @@ -50,49 +61,80 @@ public class KeyMatcher { public int getMods() { return mods; } - - public static KeyMatcher.Builder of(int key) { - return new KeyMatcher.Builder(key); + + public int getAction() { + return action; } - public static class Builder { + public static KeyMatcher of(int key) { + return new KeyMatcher(key, 0, GLFW.GLFW_PRESS); + } + + private static final Map RESOLVED_KEYS = Collections.synchronizedMap(new HashMap<>()); + + public static KeyMatcher of(String glfwConstantName) { + return RESOLVED_KEYS.computeIfAbsent(glfwConstantName, givenName -> { + String expectedName = "GLFW_KEY_" + givenName.toUpperCase(); + + try { + Field field = GLFW.class.getDeclaredField(expectedName); + return of(field.getInt(null)); + } catch (NoSuchFieldException e) { + String hint = ""; + + if (glfwConstantName.startsWith("GLFW_KEY_")) { + hint = " (remove prefix \"GLFW_KEY_\")"; + } + + throw new IllegalArgumentException("Unknown key constant \"" + glfwConstantName + "\"" + hint); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw CrashReports.report(e, "Could not access GLFW key field {}", expectedName); + } + }); + } + + public static KeyMatcher ofLeftMouseButton() { + return new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_LEFT, 0, GLFW.GLFW_PRESS); + } + + public static KeyMatcher ofRightMouseButton() { + return new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_RIGHT, 0, GLFW.GLFW_PRESS); + } + + public static KeyMatcher ofMiddleMouseButton() { + return new KeyMatcher(GLFW.GLFW_MOUSE_BUTTON_MIDDLE, 0, GLFW.GLFW_PRESS); + } - private final int key; - private int mods = 0; + public KeyMatcher with(int modifier) { + return new KeyMatcher(key, this.mods + modifier, action); + } - public Builder(int key) { - this.key = key; - } + public KeyMatcher withShift() { + return with(GLFW.GLFW_MOD_SHIFT); + } - public Builder with(int modifier) { - this.mods += modifier; - return this; - } + public KeyMatcher withCtrl() { + return with(GLFW.GLFW_MOD_CONTROL); + } - public Builder withShift() { - return with(GLFW.GLFW_MOD_SHIFT); - } - - public Builder withCtrl() { - return with(GLFW.GLFW_MOD_CONTROL); - } - - public Builder withAlt() { - return with(GLFW.GLFW_MOD_ALT); - } - - public Builder withSuper() { - return with(GLFW.GLFW_MOD_SUPER); - } - - public KeyMatcher build() { - return new KeyMatcher(key, mods); - } - - public Predicate matcher() { - return build()::matches; - } + public KeyMatcher withAlt() { + return with(GLFW.GLFW_MOD_ALT); + } + public KeyMatcher withSuper() { + return with(GLFW.GLFW_MOD_SUPER); + } + + public KeyMatcher onRelease() { + return new KeyMatcher(key, mods, GLFW.GLFW_RELEASE); + } + + public KeyMatcher onRepeat() { + return new KeyMatcher(key, mods, GLFW.GLFW_REPEAT); + } + + public KeyMatcher onAnyAction() { + return new KeyMatcher(key, mods, ANY_ACTION); } } diff --git a/src/main/java/ru/windcorp/progressia/test/inv/Bar.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/Bar.java similarity index 98% rename from src/main/java/ru/windcorp/progressia/test/inv/Bar.java rename to src/main/java/ru/windcorp/progressia/client/graphics/world/hud/Bar.java index 8b15e87..4a71de0 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/Bar.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/Bar.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.inv; +package ru.windcorp.progressia.client.graphics.world.hud; import glm.vec._3.Vec3; import glm.vec._4.Vec4; diff --git a/src/main/java/ru/windcorp/progressia/test/inv/HandSlots.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/CursorHUD.java similarity index 93% rename from src/main/java/ru/windcorp/progressia/test/inv/HandSlots.java rename to src/main/java/ru/windcorp/progressia/client/graphics/world/hud/CursorHUD.java index 828c029..fc9e446 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/HandSlots.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/CursorHUD.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.inv; +package ru.windcorp.progressia.client.graphics.world.hud; import glm.vec._2.i.Vec2i; import ru.windcorp.progressia.client.graphics.ExponentAnimation; @@ -24,14 +24,13 @@ import ru.windcorp.progressia.client.graphics.flat.RenderTarget; import ru.windcorp.progressia.client.graphics.gui.Component; import ru.windcorp.progressia.client.graphics.model.Renderable; import ru.windcorp.progressia.client.graphics.model.ShapeRenderHelper; -import ru.windcorp.progressia.client.graphics.world.hud.SlotComponent; import ru.windcorp.progressia.client.world.entity.SpeciesRender; import ru.windcorp.progressia.client.world.entity.SpeciesRenderRegistry; import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; import ru.windcorp.progressia.common.world.entity.SpeciesData.Hand; import ru.windcorp.progressia.common.world.item.ItemContainerHand; -public class HandSlots extends Component { +public class CursorHUD extends Component { private class CursorBoundSlot { @@ -64,7 +63,7 @@ public class HandSlots extends Component { float target = player.getSelectedHand() == component.getSlot().getContainer() ? 1 : 0; float sel = selection.updateForFrame(target); - float distance = HandSlots.this.distance * (1 - sel); + float distance = CursorHUD.this.distance * (1 - sel); float x = (float) Math.cos(angle) * distance; float y = (float) Math.sin(angle) * distance; float scale = 0.5f + 0.5f * sel; @@ -97,7 +96,7 @@ public class HandSlots extends Component { private final CursorBoundSlot[] slots; - public HandSlots(String name, EntityDataPlayer player) { + public CursorHUD(String name, EntityDataPlayer player) { super(name); this.player = player; diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HUDManager.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HUDManager.java new file mode 100644 index 0000000..af6be9c --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HUDManager.java @@ -0,0 +1,71 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.client.graphics.world.hud; + +import ru.windcorp.progressia.client.Client; +import ru.windcorp.progressia.client.graphics.GUI; + +public class HUDManager implements HUDWorkspace { + + private final Client client; + private final LayerHUD layer; + + public HUDManager(Client client) { + this.client = client; + this.layer = new LayerHUD(this); + } + + public void install() { + GUI.addTopLayer(layer); + } + + public void remove() { + GUI.removeLayer(layer); + } + + @Override + public void openContainer(InventoryComponent component) { + System.err.println("openContainer NYI"); + } + + public void closeEverything() { + System.err.println("closeEverything NYI"); + } + + public boolean isHidden() { + return layer.isHidden(); + } + + public void setHidden(boolean hide) { + layer.setHidden(hide); + } + + public boolean isInventoryShown() { + return layer.isInventoryShown(); + } + + public void setInventoryShown(boolean showInventory) { + layer.setInventoryShown(showInventory); + } + + @Override + public Client getClient() { + return client; + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUIManager.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HUDWorkspace.java similarity index 52% rename from src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUIManager.java rename to src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HUDWorkspace.java index 287db88..bbcb055 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUIManager.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HUDWorkspace.java @@ -15,45 +15,29 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.inv; +package ru.windcorp.progressia.client.graphics.world.hud; import ru.windcorp.progressia.client.Client; -import ru.windcorp.progressia.client.ClientState; -import ru.windcorp.progressia.client.graphics.GUI; +import ru.windcorp.progressia.client.graphics.world.LocalPlayer; import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; +import ru.windcorp.progressia.common.world.item.ItemContainerHand; -public class TestInventoryGUIManager { +public interface HUDWorkspace { - public static TestInventoryGUILayer layer; + Client getClient(); - public static void setup() { - layer = new TestInventoryGUILayer(); - GUI.addTopLayer(layer); + default LocalPlayer getPlayer() { + return getClient().getLocalPlayer(); } - public static void shutdown() { - GUI.getLayers().stream().filter(TestInventoryGUILayer.class::isInstance).forEach(GUI::removeLayer); - layer = null; + default EntityDataPlayer getPlayerEntity() { + return getClient().getLocalPlayer().getEntity(); } - public static void openGUI() { - - Client client = ClientState.getInstance(); - if (client == null) { - return; - } - - if (layer == null) { - return; - } - - EntityDataPlayer entity = client.getLocalPlayer().getEntity(); - if (entity == null) { - return; - } - - layer.setContainer(entity.getInventory(), entity); - + default ItemContainerHand getHand() { + return getClient().getLocalPlayer().getEntity().getSelectedHand(); } + + void openContainer(InventoryComponent component); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HandsHUD.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HandsHUD.java index cfd92b1..af598f7 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HandsHUD.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/HandsHUD.java @@ -36,7 +36,6 @@ import ru.windcorp.progressia.client.world.entity.SpeciesRender; import ru.windcorp.progressia.client.world.entity.SpeciesRenderRegistry; import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; import ru.windcorp.progressia.common.world.entity.SpeciesData.Hand; -import ru.windcorp.progressia.test.inv.TestInventoryGUIManager; public class HandsHUD extends Component { @@ -91,11 +90,11 @@ public class HandsHUD extends Component { private final LocalPlayer player; - public HandsHUD(String name, LocalPlayer player) { + public HandsHUD(String name, HUDManager manager) { super(name); - this.player = player; + this.player = manager.getPlayer(); - EntityDataPlayer entity = player.getEntity(); + EntityDataPlayer entity = manager.getPlayerEntity(); String speciesId = entity.getSpecies().getId(); SpeciesRender speciesRender = SpeciesRenderRegistry.getInstance().get(speciesId); @@ -130,7 +129,7 @@ public class HandsHUD extends Component { } private boolean shouldRenderHandPlaceholder() { - return TestInventoryGUIManager.layer.hasContainer(); + return true; } } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InteractiveSlotComponent.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InteractiveSlotComponent.java new file mode 100644 index 0000000..5d27cfc --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InteractiveSlotComponent.java @@ -0,0 +1,156 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.client.graphics.world.hud; + +import glm.vec._2.i.Vec2i; +import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; +import ru.windcorp.progressia.client.graphics.gui.Button; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; +import ru.windcorp.progressia.client.graphics.input.KeyMatcher; +import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent; +import ru.windcorp.progressia.common.Units; +import ru.windcorp.progressia.common.world.item.ItemContainer; +import ru.windcorp.progressia.common.world.item.ItemSlot; +import ru.windcorp.progressia.common.world.item.Items; + +public class InteractiveSlotComponent extends Button { + + private static final double MIN_PICK_ALL_DELAY = Units.get("0.5 s"); + + private double lastMainAction = Double.NEGATIVE_INFINITY; + + private final SlotComponent slotComponent; + private final HUDWorkspace workspace; + + public InteractiveSlotComponent(String name, ItemContainer container, int index, HUDWorkspace workspace) { + this(name, new SlotComponent(name, container, index), workspace); + } + + public InteractiveSlotComponent(SlotComponent component, HUDWorkspace workspace) { + this(component.getName() + ".Interactive", component, workspace); + } + + public InteractiveSlotComponent(String name, SlotComponent component, HUDWorkspace workspace) { + super(name, null, null); + this.slotComponent = component; + this.workspace = workspace; + + Vec2i size = slotComponent.getPreferredSize().add(2 * BORDER); + setPreferredSize(size); + + addChild(this.slotComponent); + setLayout(new LayoutFill(MARGIN)); + + addListeners(); + } + + private void addListeners() { + addAction(button -> onMainAction()); + + addListener(KeyMatcher.ofRightMouseButton(), this::onAltAction); + + addListener(WheelScrollEvent.class, event -> { + if (event.hasVerticalMovement()) { + onSingleMoveAction(event.isDown()); + return true; + } + return false; + }); + } + + private void onMainAction() { + ItemSlot handSlot = workspace.getHand().slot(); + ItemSlot invSlot = getSlot(); + + boolean success = false; + + double now = GraphicsInterface.getTime(); + if (now - lastMainAction < MIN_PICK_ALL_DELAY) { + lastMainAction = Double.NEGATIVE_INFINITY; + pickAll(handSlot); + success = true; + } else { + lastMainAction = now; + } + + if (!success) { + success = Items.pour(handSlot, invSlot) != 0; + } + + if (!success) { + success = Items.swap(handSlot, invSlot); + } + + if (!success && handSlot.isEmpty()) { + success = Items.pour(invSlot, handSlot) != 0; + } + + if (success) { + requestReassembly(); + } + } + + private void pickAll(ItemSlot handSlot) { + for (ItemSlot invSlot : getSlot().getContainer()) { + Items.pour(invSlot, handSlot); + if (handSlot.isEmpty()) { + break; + } + } + } + + private void onAltAction() { + ItemSlot handSlot = workspace.getHand().slot(); + ItemSlot invSlot = getSlot(); + + boolean success = false; + + if (handSlot.isEmpty()) { + success = Items.pour(invSlot, handSlot, invSlot.getAmount() / 2) != 0; + } + + if (!success) { + success = Items.pour(handSlot, invSlot, 1) != 0; + } + + if (!success) { + success = Items.swap(handSlot, invSlot); + } + + if (success) { + requestReassembly(); + } + } + + private void onSingleMoveAction(boolean fromHand) { + ItemSlot handSlot = workspace.getHand().slot(); + ItemSlot invSlot = getSlot(); + + ItemSlot from = fromHand ? handSlot : invSlot; + ItemSlot into = fromHand ? invSlot : handSlot; + + if (Items.pour(from, into, 1) != 0) { + requestReassembly(); + } + } + + public ItemSlot getSlot() { + return slotComponent.getSlot(); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/test/inv/InventoryComponent.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InventoryComponent.java similarity index 88% rename from src/main/java/ru/windcorp/progressia/test/inv/InventoryComponent.java rename to src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InventoryComponent.java index 8941b9e..ba0bb1d 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/InventoryComponent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InventoryComponent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.inv; +package ru.windcorp.progressia.client.graphics.world.hud; import java.util.Collection; @@ -27,6 +27,6 @@ public abstract class InventoryComponent extends Component { super(name); } - public abstract Collection getSlots(); + public abstract Collection getSlots(); } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InventoryHUD.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InventoryHUD.java new file mode 100644 index 0000000..76d121e --- /dev/null +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/InventoryHUD.java @@ -0,0 +1,88 @@ +/* + * Progressia + * Copyright (C) 2020-2021 Wind Corporation and contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +package ru.windcorp.progressia.client.graphics.world.hud; + +import java.util.Arrays; +import java.util.Map; + +import com.google.common.collect.Maps; + +import ru.windcorp.progressia.client.graphics.gui.Component; +import ru.windcorp.progressia.client.graphics.gui.Group; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutBorderHorizontal; +import ru.windcorp.progressia.client.graphics.gui.layout.LayoutVertical; +import ru.windcorp.progressia.client.world.entity.SpeciesRender; +import ru.windcorp.progressia.client.world.entity.SpeciesRenderRegistry; +import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; +import ru.windcorp.progressia.common.world.entity.SpeciesData.EquipmentSlot; + +public class InventoryHUD extends Component { + + public enum Side { + LEFT("Left", LayoutBorderHorizontal.LEFT), + RIGHT("Right", LayoutBorderHorizontal.RIGHT); + + private final String ccName; + private final Object lbhHint; + + private Side(String ccName, Object lbhHint) { + this.ccName = ccName; + this.lbhHint = lbhHint; + } + } + + public InventoryHUD(String name, HUDWorkspace workspace) { + super(name); + setLayout(new LayoutBorderHorizontal()); + + EntityDataPlayer entity = workspace.getPlayerEntity(); + String speciesId = entity.getSpecies().getId(); + SpeciesRender speciesRender = SpeciesRenderRegistry.getInstance().get(speciesId); + + Map containers = Maps.toMap( + Arrays.asList(Side.values()), + side -> new Group(name + "." + side.ccName, new LayoutVertical(15)) + ); + + for (int i = 0; i < entity.getEquipmentCount(); ++i) { + + EquipmentSlot slot = entity.getSpecies().getEquipmentSlots().get(i); + + SlotComponent display = new SlotComponent(name + "." + slot.getName(), entity.getEquipmentSlot(i), 0) + .setBackground(speciesRender.getEquipmentSlotBackground(slot)) + .setScale(2); + + InteractiveSlotComponent interactiveDisplay = new InteractiveSlotComponent( + display, + workspace + ); + + containers.get(speciesRender.getEquipmentSlotSide(slot)).addChild(interactiveDisplay); + + } + + containers.forEach((side, comp) -> { + addChild( + new Group(name + "." + side.ccName + ".Aligner", new LayoutAlign(0, 1, 0), comp) + .setLayoutHint(side.lbhHint) + ); + }); + } + +} diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/LayerHUD.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/LayerHUD.java index 2d1e45e..5a73bc4 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/LayerHUD.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/LayerHUD.java @@ -17,34 +17,116 @@ */ package ru.windcorp.progressia.client.graphics.world.hud; +import org.lwjgl.glfw.GLFW; + import com.google.common.eventbus.Subscribe; -import ru.windcorp.progressia.client.Client; import ru.windcorp.progressia.client.events.NewLocalEntityEvent; +import ru.windcorp.progressia.client.graphics.GUI; +import ru.windcorp.progressia.client.graphics.gui.Components; import ru.windcorp.progressia.client.graphics.gui.GUILayer; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; +import ru.windcorp.progressia.client.graphics.input.KeyEvent; +import ru.windcorp.progressia.client.graphics.input.bus.Input; +import ru.windcorp.progressia.test.TestPlayerControls; public class LayerHUD extends GUILayer { - public LayerHUD(Client client) { + private final HUDManager manager; + + private boolean showInventory = false; + private boolean isHidden = false; + + public LayerHUD(HUDManager manager) { super("LayerHUD", new LayoutFill(15)); + this.manager = manager; + setCursorPolicy(CursorPolicy.INDIFFERENT); - client.subscribe(this); + manager.getClient().subscribe(this); } - + @Subscribe private void onEntityChanged(NewLocalEntityEvent e) { while (!getRoot().getChildren().isEmpty()) { getRoot().removeChild(getRoot().getChild(0)); } - + if (e.getNewEntity() == null) { + getRoot().requestReassembly(); return; } - - getRoot().addChild(new PermanentHUD(getName(), e.getClient().getLocalPlayer())); + + getRoot().addChild(new PermanentHUD(getName() + ".Permanent", manager)); + getRoot().addChild(Components.hide(new InventoryHUD(getName() + ".Equipment", manager), () -> !showInventory)); + getRoot().addChild(Components.hide(new CursorHUD(getName() + ".Equipment", manager.getPlayerEntity()), () -> !showInventory)); + getRoot().requestReassembly(); } + public boolean isInventoryShown() { + return showInventory; + } + + public void setInventoryShown(boolean showInventory) { + this.showInventory = showInventory; + updateCursorPolicy(); + } + + public boolean isHidden() { + return isHidden; + } + + public void setHidden(boolean isHidden) { + this.isHidden = isHidden; + updateCursorPolicy(); + } + + private void updateCursorPolicy() { + if (showInventory && !isHidden) { + setCursorPolicy(CursorPolicy.REQUIRE); + } else { + setCursorPolicy(CursorPolicy.INDIFFERENT); + } + + GUI.updateLayer(this); + } + + @Override + protected void handleInput(Input input) { + if (isHidden) { + return; + } + + super.handleInput(input); + + if (showInventory) { + TestPlayerControls.getInstance().handleCtrlIfApplicable(input); + if (!input.isConsumed()) { + handleCloseInventoryIfApplicable(input); + } + input.consume(); + } + } + + private void handleCloseInventoryIfApplicable(Input input) { + if (input.getEvent() instanceof KeyEvent) { + KeyEvent event = (KeyEvent) input.getEvent(); + + if (event.isPress() && (event.getKey() == GLFW.GLFW_KEY_E || event.getKey() == GLFW.GLFW_KEY_ESCAPE)) { + setInventoryShown(false); + input.consume(); + } + } + } + + @Override + protected void doRender() { + if (isHidden) { + return; + } + + super.doRender(); + } + } diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/PermanentHUD.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/PermanentHUD.java index ae1fcde..288f1d2 100644 --- a/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/PermanentHUD.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/PermanentHUD.java @@ -19,21 +19,20 @@ package ru.windcorp.progressia.client.graphics.world.hud; import ru.windcorp.progressia.client.graphics.gui.Component; import ru.windcorp.progressia.client.graphics.gui.layout.LayoutBorderVertical; -import ru.windcorp.progressia.client.graphics.world.LocalPlayer; import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; public class PermanentHUD extends Component { - public PermanentHUD(String name, LocalPlayer player) { + public PermanentHUD(String name, HUDManager manager) { super(name); setLayout(new LayoutBorderVertical()); - EntityDataPlayer entity = player.getEntity(); + EntityDataPlayer entity = manager.getPlayerEntity(); if (entity == null) { - throw new IllegalStateException("Player " + player + " does not have an associated entity"); + throw new IllegalStateException("Player " + manager.getPlayer() + " does not have an associated entity"); } - addChild(new HandsHUD(name + ".Hands", player).setLayoutHint(LayoutBorderVertical.UP)); + addChild(new HandsHUD(name + ".Hands", manager).setLayoutHint(LayoutBorderVertical.UP)); } } diff --git a/src/main/java/ru/windcorp/progressia/test/inv/SimpleInventoryComponent.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/SimpleInventoryComponent.java similarity index 81% rename from src/main/java/ru/windcorp/progressia/test/inv/SimpleInventoryComponent.java rename to src/main/java/ru/windcorp/progressia/client/graphics/world/hud/SimpleInventoryComponent.java index b7d3caf..ea318e4 100644 --- a/src/main/java/ru/windcorp/progressia/test/inv/SimpleInventoryComponent.java +++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/hud/SimpleInventoryComponent.java @@ -15,7 +15,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -package ru.windcorp.progressia.test.inv; +package ru.windcorp.progressia.client.graphics.world.hud; import java.util.ArrayList; import java.util.Collection; @@ -32,9 +32,9 @@ import ru.windcorp.progressia.common.world.item.ItemContainer; public class SimpleInventoryComponent extends InventoryComponent { private final Group slots = new Group("Inventory.Slots", new LayoutGrid(15)); - private final Collection slotCollection = new ArrayList<>(); + private final Collection slotCollection = new ArrayList<>(); - public SimpleInventoryComponent(ItemContainer container) { + public SimpleInventoryComponent(ItemContainer container, HUDWorkspace workspace) { super("Inventory"); setLayout(new LayoutBorderHorizontal(15)); @@ -65,14 +65,14 @@ public class SimpleInventoryComponent extends InventoryComponent { addChild(massBar.setLayoutHint(LayoutBorderHorizontal.LEFT)); for (int i = 0; i < container.getSlotCount(); ++i) { - addSlot(container, i); + addSlot(container, i, workspace); } } - private void addSlot(ItemContainer container, int index) { + private void addSlot(ItemContainer container, int index, HUDWorkspace workspace) { final int maxX = 6; - DecoratedSlotComponent component = new DecoratedSlotComponent("Inventory.Slot." + index, container, index); + InteractiveSlotComponent component = new InteractiveSlotComponent("Inventory.Slot." + index, container, index, workspace); Vec2i pos = new Vec2i(index % maxX, index / maxX); slots.addChild(component.setLayoutHint(pos)); @@ -80,7 +80,7 @@ public class SimpleInventoryComponent extends InventoryComponent { } @Override - public Collection getSlots() { + public Collection getSlots() { return slotCollection; } diff --git a/src/main/java/ru/windcorp/progressia/client/world/entity/SpeciesRender.java b/src/main/java/ru/windcorp/progressia/client/world/entity/SpeciesRender.java index 9f63c2e..1846b19 100644 --- a/src/main/java/ru/windcorp/progressia/client/world/entity/SpeciesRender.java +++ b/src/main/java/ru/windcorp/progressia/client/world/entity/SpeciesRender.java @@ -18,6 +18,7 @@ package ru.windcorp.progressia.client.world.entity; import ru.windcorp.progressia.client.graphics.texture.Texture; +import ru.windcorp.progressia.client.graphics.world.hud.InventoryHUD; import ru.windcorp.progressia.client.graphics.world.hud.HUDTextures; import ru.windcorp.progressia.client.graphics.world.hud.HandsHUD; import ru.windcorp.progressia.common.util.namespaces.Namespaced; @@ -34,6 +35,7 @@ public abstract class SpeciesRender extends Namespaced { public abstract EntityRenderable createRenderable(EntityDataPlayer entity); public abstract HandsHUD.Side getHandSide(Hand hand); + public abstract InventoryHUD.Side getEquipmentSlotSide(EquipmentSlot equipmentSlot); public Texture getTexture(String name) { return HUDTextures.getHUDTexture(getNamespace() + "_" + getName() + "/" + name); diff --git a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java index 44fb56a..da173c7 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java +++ b/src/main/java/ru/windcorp/progressia/common/world/entity/EntityDataPlayer.java @@ -20,6 +20,7 @@ package ru.windcorp.progressia.common.world.entity; import ru.windcorp.progressia.common.Units; import ru.windcorp.progressia.common.state.IntStateField; import ru.windcorp.progressia.common.state.ObjectStateField; +import ru.windcorp.progressia.common.world.item.ItemContainerEquipment; import ru.windcorp.progressia.common.world.item.ItemContainerHand; import ru.windcorp.progressia.common.world.item.ItemContainerMixedSimple; @@ -61,6 +62,10 @@ public class EntityDataPlayer extends EntityData { return speciesDatalet.get(this).getHands().length; } + public ItemContainerEquipment getEquipmentSlot(int index) { + return speciesDatalet.get(this).getEquipment()[index]; + } + public int getEquipmentCount() { return speciesDatalet.get(this).getEquipment().length; } diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java index 0b5d655..f4f1a0f 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainer.java @@ -17,6 +17,8 @@ */ package ru.windcorp.progressia.common.world.item; +import java.util.Iterator; +import java.util.NoSuchElementException; import java.util.function.Consumer; import ru.windcorp.progressia.common.state.Encodable; @@ -31,7 +33,7 @@ import ru.windcorp.progressia.common.util.namespaces.Namespaced; * unique index. If a container has n slots, its slots are numbered 0 * through n - 1. */ -public abstract class ItemContainer extends Namespaced implements Encodable { +public abstract class ItemContainer extends Namespaced implements Encodable, Iterable { public ItemContainer(String id) { super(id); @@ -52,7 +54,32 @@ public abstract class ItemContainer extends Namespaced implements Encodable { */ public abstract int getSlotCount(); - public abstract void forEach(Consumer action); + @Override + public abstract void forEach(Consumer action); + + @Override + public Iterator iterator() { + return new Iterator() { + + private int index = 0; + + @Override + public boolean hasNext() { + return index < getSlotCount(); + } + + @Override + public ItemSlot next() { + if (!hasNext()) { + throw new NoSuchElementException("index = " + index + ", size = " + getSlotCount()); + } + ItemSlot slot = getSlot(index); + index++; + return slot; + } + + }; + } /** * Computes and returns the mass limit that the container imposes. diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java index 567f9f3..0f0a6c9 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerMixed.java @@ -79,7 +79,7 @@ public abstract class ItemContainerMixed extends ItemContainer { } @Override - public void forEach(Consumer action) { + public void forEach(Consumer action) { getSlots().forEach(action); } diff --git a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerSingle.java b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerSingle.java index f930ff9..b8b430c 100644 --- a/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerSingle.java +++ b/src/main/java/ru/windcorp/progressia/common/world/item/ItemContainerSingle.java @@ -74,7 +74,7 @@ public abstract class ItemContainerSingle extends ItemContainer { } @Override - public void forEach(Consumer action) { + public void forEach(Consumer action) { action.accept(slot); } diff --git a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java index 851bf82..c59c12b 100644 --- a/src/main/java/ru/windcorp/progressia/server/PlayerManager.java +++ b/src/main/java/ru/windcorp/progressia/server/PlayerManager.java @@ -70,6 +70,8 @@ public class PlayerManager { player.getInventory().getSlot(9).setContents(ItemDataRegistry.getInstance().create("Test:RedGraniteCobblestone"), 1); player.getInventory().getSlot(6).setContents(ItemDataRegistry.getInstance().create("Test:MoonTypeIceCream"), 1); + player.getHand(0).slot().setContents(ItemDataRegistry.getInstance().create("Test:Stick"), 7); + player.setPosition(getServer().getWorld().getGenerator().suggestSpawnLocation()); player.setUpVector(new Vec3(0, 0, 1)); player.setLookingAt(new Vec3(2, 1, 0)); diff --git a/src/main/java/ru/windcorp/progressia/test/SpeciesDataHuman.java b/src/main/java/ru/windcorp/progressia/test/SpeciesDataHuman.java index 19889c5..a63ffea 100644 --- a/src/main/java/ru/windcorp/progressia/test/SpeciesDataHuman.java +++ b/src/main/java/ru/windcorp/progressia/test/SpeciesDataHuman.java @@ -31,7 +31,7 @@ public class SpeciesDataHuman extends SpeciesData { super(id); withHands(new Hand("Right"), new Hand("Left")); - withEquipmentSlots(/* ._. nope */); + withEquipmentSlots(new EquipmentSlot("Backpack", i -> true)); } @Override diff --git a/src/main/java/ru/windcorp/progressia/test/SpeciesRenderHuman.java b/src/main/java/ru/windcorp/progressia/test/SpeciesRenderHuman.java index 43a6299..498b7bd 100644 --- a/src/main/java/ru/windcorp/progressia/test/SpeciesRenderHuman.java +++ b/src/main/java/ru/windcorp/progressia/test/SpeciesRenderHuman.java @@ -17,10 +17,12 @@ */ package ru.windcorp.progressia.test; -import ru.windcorp.progressia.client.graphics.world.hud.HandsHUD.Side; +import ru.windcorp.progressia.client.graphics.world.hud.InventoryHUD; +import ru.windcorp.progressia.client.graphics.world.hud.HandsHUD; import ru.windcorp.progressia.client.world.entity.EntityRenderable; import ru.windcorp.progressia.client.world.entity.SpeciesRender; import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; +import ru.windcorp.progressia.common.world.entity.SpeciesData.EquipmentSlot; import ru.windcorp.progressia.common.world.entity.SpeciesData.Hand; public class SpeciesRenderHuman extends SpeciesRender { @@ -37,8 +39,13 @@ public class SpeciesRenderHuman extends SpeciesRender { } @Override - public Side getHandSide(Hand hand) { - return hand.getIndex() == 0 ? Side.RIGHT : Side.LEFT; + public HandsHUD.Side getHandSide(Hand hand) { + return hand.getIndex() == 0 ? HandsHUD.Side.RIGHT : HandsHUD.Side.LEFT; + } + + @Override + public InventoryHUD.Side getEquipmentSlotSide(EquipmentSlot equipmentSlot) { + return InventoryHUD.Side.LEFT; } } diff --git a/src/main/java/ru/windcorp/progressia/test/TestContent.java b/src/main/java/ru/windcorp/progressia/test/TestContent.java index 8b39117..ad9ed98 100644 --- a/src/main/java/ru/windcorp/progressia/test/TestContent.java +++ b/src/main/java/ru/windcorp/progressia/test/TestContent.java @@ -28,7 +28,6 @@ import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; -import org.lwjgl.glfw.GLFW; import glm.vec._3.i.Vec3i; import ru.windcorp.progressia.client.ClientState; @@ -70,7 +69,6 @@ import ru.windcorp.progressia.server.world.generation.planet.PlanetGravityModel; import ru.windcorp.progressia.server.world.tile.*; import ru.windcorp.progressia.test.Rocks.RockType; import ru.windcorp.progressia.test.gen.TestGravityModel; -import ru.windcorp.progressia.test.inv.TestInventoryGUIManager; public class TestContent { @@ -311,7 +309,7 @@ public class TestContent { "Test:BreakBlock", KeyEvent.class, TestContent::onBlockBreakTrigger, - KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_LEFT).matcher(), + KeyMatcher.ofLeftMouseButton(), i -> isAnythingSelected() ) ); @@ -323,7 +321,7 @@ public class TestContent { "Test:PlaceBlock", KeyEvent.class, TestContent::onBlockPlaceTrigger, - KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_RIGHT).matcher(), + KeyMatcher.ofRightMouseButton(), i -> isAnythingSelected() && TestPlayerControls.getInstance().isBlockSelected() ) ); @@ -336,7 +334,7 @@ public class TestContent { "Test:PlaceTile", KeyEvent.class, TestContent::onTilePlaceTrigger, - KeyMatcher.of(GLFW.GLFW_MOUSE_BUTTON_RIGHT).matcher(), + KeyMatcher.ofRightMouseButton(), i -> isAnythingSelected() && !TestPlayerControls.getInstance().isBlockSelected() ) ); @@ -347,16 +345,25 @@ public class TestContent { "Test:StartNextMusic", KeyEvent.class, TestMusicPlayer::startNextNow, - KeyMatcher.of(GLFW.GLFW_KEY_M).matcher() + KeyMatcher.of("M") ) ); triggers.register( ControlTriggers.localOf( - "Test:OpenInventory", + "Test:ShowInventory", KeyEvent.class, - TestInventoryGUIManager::openGUI, - KeyMatcher.of(GLFW.GLFW_KEY_E).matcher() + TestContent::switchInventory, + KeyMatcher.of("E") + ) + ); + + triggers.register( + ControlTriggers.localOf( + "Test:HideHUD", + KeyEvent.class, + TestContent::switchHUD, + KeyMatcher.of("F1") ) ); } @@ -496,6 +503,22 @@ public class TestContent { } tileContext.addTile(tile); } + + private static void switchInventory() { + ru.windcorp.progressia.client.Client client = ClientState.getInstance(); + if (client == null || !client.isReady()) + return; + + client.getHUD().setInventoryShown(!client.getHUD().isInventoryShown()); + } + + private static void switchHUD() { + ru.windcorp.progressia.client.Client client = ClientState.getInstance(); + if (client == null || !client.isReady()) + return; + + client.getHUD().setHidden(!client.getHUD().isHidden()); + } private static void registerMisc() { ChunkIO.registerCodec(new TestChunkCodec()); diff --git a/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java b/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java deleted file mode 100644 index 10889b4..0000000 --- a/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Progressia - * Copyright (C) 2020-2021 Wind Corporation and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package ru.windcorp.progressia.test.inv; - -import glm.vec._2.i.Vec2i; -import ru.windcorp.progressia.client.graphics.gui.Button; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; -import ru.windcorp.progressia.client.graphics.world.hud.SlotComponent; -import ru.windcorp.progressia.common.world.item.ItemContainer; -import ru.windcorp.progressia.common.world.item.ItemSlot; - -public class DecoratedSlotComponent extends Button { - - private final SlotComponent slotComponent; - - public DecoratedSlotComponent(String name, ItemContainer container, int index) { - this(name, new SlotComponent(name, container, index)); - } - - public DecoratedSlotComponent(String name, SlotComponent component) { - super(name, null, null); - this.slotComponent = component; - - Vec2i size = slotComponent.getPreferredSize().add(2 * BORDER); - setPreferredSize(size); - - addChild(this.slotComponent); - setLayout(new LayoutFill(MARGIN)); - } - - public ItemSlot getSlot() { - return slotComponent.getSlot(); - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/inv/InventoryScreen.java b/src/main/java/ru/windcorp/progressia/test/inv/InventoryScreen.java deleted file mode 100644 index 863279e..0000000 --- a/src/main/java/ru/windcorp/progressia/test/inv/InventoryScreen.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Progressia - * Copyright (C) 2020-2021 Wind Corporation and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package ru.windcorp.progressia.test.inv; - -import java.util.function.Consumer; -import java.util.function.Supplier; - -import ru.windcorp.progressia.client.graphics.Colors; -import ru.windcorp.progressia.client.graphics.backend.GraphicsInterface; -import ru.windcorp.progressia.client.graphics.gui.BasicButton; -import ru.windcorp.progressia.client.graphics.gui.Component; -import ru.windcorp.progressia.client.graphics.gui.Components; -import ru.windcorp.progressia.client.graphics.gui.Panel; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; -import ru.windcorp.progressia.client.graphics.input.KeyEvent; -import ru.windcorp.progressia.client.graphics.input.WheelScrollEvent; -import ru.windcorp.progressia.client.graphics.input.bus.InputListener; -import ru.windcorp.progressia.common.Units; -import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; -import ru.windcorp.progressia.common.world.item.ItemSlot; -import ru.windcorp.progressia.common.world.item.Items; - -public class InventoryScreen extends Component { - - private static final double MIN_PICK_ALL_DELAY = Units.get("0.5 s"); - - private final InventoryComponent mainInventory; - - private final EntityDataPlayer player; - - private double lastLeftClick = Double.NEGATIVE_INFINITY; - private ItemSlot lastLeftClickSlot = null; - - public InventoryScreen(String name, InventoryComponent mainInventory, EntityDataPlayer player) { - super(name); - - this.mainInventory = mainInventory; - - this.player = player; - - setLayout(new LayoutFill(0)); - - addChild(new Panel(name + ".Background", new LayoutAlign(10), Colors.toVector(0x66000000), null)); - - Panel mainInventoryPanel = new Panel(name + ".Content", new LayoutFill(20)); - mainInventoryPanel.addChild(mainInventory); - addChild(Components.center(mainInventoryPanel)); - - addChild(new HandSlots(name + ".Hands", player)); - - addListeners(mainInventory); - - mainInventory.focusNext(); - } - - private void addListeners(InventoryComponent mainInventory) { - Supplier handSlot = () -> player.getSelectedHand().slot(); - - Consumer pickAll = createPickAllAction(handSlot); - - for (DecoratedSlotComponent component : mainInventory.getSlots()) { - component.addAction(pickAll); - component.addListener(KeyEvent.class, createRMBAction(component.getSlot(), handSlot)); - component.addListener(WheelScrollEvent.class, createWheelAction(component.getSlot(), handSlot)); - } - } - - private Consumer createPickAllAction(Supplier handSlotChooser) { - return button -> { - - ItemSlot handSlot = handSlotChooser.get(); - ItemSlot invSlot = ((DecoratedSlotComponent) button).getSlot(); - - boolean success = false; - - double now = GraphicsInterface.getTime(); - if (lastLeftClickSlot == invSlot && now - lastLeftClick < MIN_PICK_ALL_DELAY) { - - lastLeftClickSlot = null; - lastLeftClick = Double.NEGATIVE_INFINITY; - - pickAll(handSlot); - - success = true; - - } else { - lastLeftClick = now; - lastLeftClickSlot = invSlot; - } - - if (!success) { - success = Items.pour(handSlot, invSlot) != 0; - } - - if (!success) { - success = Items.swap(handSlot, invSlot); - } - - if (!success && handSlot.isEmpty()) { - success = Items.pour(invSlot, handSlot) != 0; - } - - if (success) { - requestReassembly(); - } - - }; - } - - private void pickAll(ItemSlot handSlot) { - for (DecoratedSlotComponent component : mainInventory.getSlots()) { - - Items.pour(component.getSlot(), handSlot); - if (handSlot.isEmpty()) { - break; - } - - } - } - - private InputListener createRMBAction(ItemSlot invSlot, Supplier handSlotChooser) { - return input -> { - - if (input.isPress() && input.isRightMouseButton()) { - ItemSlot handSlot = handSlotChooser.get(); - - boolean success = false; - - if (handSlot.isEmpty()) { - success = Items.pour(invSlot, handSlot, invSlot.getAmount() / 2) != 0; - } - - if (!success) { - success = Items.pour(handSlot, invSlot, 1) != 0; - } - - if (!success) { - success = Items.swap(handSlot, invSlot); - } - - if (success) { - requestReassembly(); - } - - return true; - } - - return false; - - }; - } - - private InputListener createWheelAction(ItemSlot invSlot, Supplier handSlotChooser) { - return input -> { - - if (!input.hasVerticalMovement()) { - return false; - } - - ItemSlot handSlot = handSlotChooser.get(); - - ItemSlot from = input.isDown() ? handSlot : invSlot; - ItemSlot into = input.isDown() ? invSlot : handSlot; - - if (Items.pour(from, into, 1) != 0) { - requestReassembly(); - } - - return true; - - }; - } - -} diff --git a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUILayer.java b/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUILayer.java deleted file mode 100644 index b91da2f..0000000 --- a/src/main/java/ru/windcorp/progressia/test/inv/TestInventoryGUILayer.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Progressia - * Copyright (C) 2020-2021 Wind Corporation and contributors - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ -package ru.windcorp.progressia.test.inv; - -import org.lwjgl.glfw.GLFW; - -import ru.windcorp.progressia.client.graphics.GUI; -import ru.windcorp.progressia.client.graphics.gui.GUILayer; -import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill; -import ru.windcorp.progressia.client.graphics.input.InputEvent; -import ru.windcorp.progressia.client.graphics.input.KeyEvent; -import ru.windcorp.progressia.client.graphics.input.bus.Input; -import ru.windcorp.progressia.common.world.entity.EntityDataPlayer; -import ru.windcorp.progressia.common.world.item.ItemContainerMixed; -import ru.windcorp.progressia.test.TestPlayerControls; - -public class TestInventoryGUILayer extends GUILayer { - - private ItemContainerMixed container; - - private InventoryScreen display = null; - - public TestInventoryGUILayer() { - super("Inventory", new LayoutFill(0)); - setCursorPolicy(CursorPolicy.INDIFFERENT); - } - - public boolean hasContainer() { - return container != null; - } - - public void setContainer(ItemContainerMixed container, EntityDataPlayer player) { - this.container = container; - - getRoot().removeChild(display); - display = null; - - if (container != null) { - display = new InventoryScreen("Screen", new SimpleInventoryComponent(container), player); - - getRoot().addChild(display); - invalidate(); - - setCursorPolicy(CursorPolicy.REQUIRE); - } else { - setCursorPolicy(CursorPolicy.INDIFFERENT); - } - - GUI.updateLayer(this); - } - - @Override - protected void doRender() { - if (container != null) { - super.doRender(); - } - } - - @Override - protected void handleInput(Input input) { - if (container != null) { - if (!input.isConsumed()) { - InputEvent event = input.getEvent(); - - if (event instanceof KeyEvent) { - KeyEvent keyEvent = (KeyEvent) event; - if ( - keyEvent.isPress() - && (keyEvent.getKey() == GLFW.GLFW_KEY_E || keyEvent.getKey() == GLFW.GLFW_KEY_ESCAPE) - ) { - setContainer(null, null); - input.consume(); - } - } - } - - TestPlayerControls.getInstance().handleCtrlIfApplicable(input); - - super.handleInput(input); - input.consume(); - } - } - -} diff --git a/src/main/resources/assets/textures/gui/Core_Human/EquipmentSlotBackpack.png b/src/main/resources/assets/textures/gui/Core_Human/EquipmentSlotBackpack.png new file mode 100644 index 0000000..5534e5b Binary files /dev/null and b/src/main/resources/assets/textures/gui/Core_Human/EquipmentSlotBackpack.png differ diff --git a/src/main/resources/assets/textures/items/CardboardBackpack.png b/src/main/resources/assets/textures/items/CardboardBackpack.png new file mode 100644 index 0000000..5fe25ad Binary files /dev/null and b/src/main/resources/assets/textures/items/CardboardBackpack.png differ