diff --git a/src/main/java/ru/windcorp/progressia/client/Client.java b/src/main/java/ru/windcorp/progressia/client/Client.java
index f356954..6bae089 100644
--- a/src/main/java/ru/windcorp/progressia/client/Client.java
+++ b/src/main/java/ru/windcorp/progressia/client/Client.java
@@ -18,14 +18,19 @@
package ru.windcorp.progressia.client;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+
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.world.Camera;
import ru.windcorp.progressia.client.graphics.world.EntityAnchor;
import ru.windcorp.progressia.client.graphics.world.LocalPlayer;
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.common.world.entity.EntityData;
public class Client {
@@ -33,6 +38,8 @@ public class Client {
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 ServerCommsChannel comms;
@@ -41,6 +48,7 @@ public class Client {
this.comms = comms;
comms.addListener(new DefaultClientCommsListener(this));
+ subscribe(this);
}
public WorldRender getWorld() {
@@ -63,17 +71,32 @@ public class Client {
return comms;
}
- public void onLocalPlayerEntityChanged(EntityData entity, EntityData lastKnownEntity) {
- if (entity == null) {
+ @Subscribe
+ private void onLocalPlayerEntityChanged(NewLocalEntityEvent e) {
+ if (e.getNewEntity() == null) {
getCamera().setAnchor(null);
return;
}
getCamera().setAnchor(
new EntityAnchor(
- getWorld().getEntityRenderable(entity)
+ getWorld().getEntityRenderable(e.getNewEntity())
)
);
}
+ public void subscribe(Object object) {
+ eventBus.register(object);
+ }
+
+ public void unsubscribe(Object object) {
+ eventBus.unregister(object);
+ }
+
+ public void postEvent(ClientEvent event) {
+ event.setClient(this);
+ eventBus.post(event);
+ event.setClient(null);
+ }
+
}
diff --git a/src/main/java/ru/windcorp/progressia/client/ClientState.java b/src/main/java/ru/windcorp/progressia/client/ClientState.java
index 36d36ed..5ba262b 100644
--- a/src/main/java/ru/windcorp/progressia/client/ClientState.java
+++ b/src/main/java/ru/windcorp/progressia/client/ClientState.java
@@ -20,6 +20,7 @@ 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.LayerHUD;
import ru.windcorp.progressia.client.graphics.world.LayerWorld;
import ru.windcorp.progressia.common.world.DefaultWorldData;
import ru.windcorp.progressia.server.ServerState;
@@ -56,6 +57,7 @@ public class ClientState {
GUI.addBottomLayer(new LayerWorld(client));
GUI.addTopLayer(new LayerTestUI());
+ GUI.addTopLayer(new LayerHUD(client));
TestInventoryGUIManager.setup();
GUI.addTopLayer(new LayerAbout());
diff --git a/src/main/java/ru/windcorp/progressia/client/events/ClientEvent.java b/src/main/java/ru/windcorp/progressia/client/events/ClientEvent.java
new file mode 100644
index 0000000..965dbf4
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/client/events/ClientEvent.java
@@ -0,0 +1,68 @@
+/*
+ * 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.events;
+
+import ru.windcorp.progressia.client.Client;
+
+/**
+ * An interface for all events issued by a {@link Client}.
+ */
+public interface ClientEvent {
+
+ /**
+ * Returns the client instance that this event happened on.
+ *
+ * @return the client
+ */
+ Client getClient();
+
+ /**
+ * Sets the client instance that the event is posted on. The value provided
+ * to this method must be returned by subsequent calls to
+ * {@link #getClient()}. Do not call this method when handling the event.
+ *
+ * @param client the client dispatching the event or {@code null} to unbind
+ * any previously bound client
+ */
+ void setClient(Client client);
+
+ /**
+ * A default implementation of {@link ClientEvent}. This is not necessarily
+ * extended by client events.
+ */
+ public static abstract class Default implements ClientEvent {
+
+ private Client client;
+
+ public Default(Client client) {
+ this.client = client;
+ }
+
+ @Override
+ public Client getClient() {
+ return client;
+ }
+
+ @Override
+ public void setClient(Client client) {
+ this.client = client;
+ }
+
+ }
+
+}
diff --git a/src/main/java/ru/windcorp/progressia/client/events/NewLocalEntityEvent.java b/src/main/java/ru/windcorp/progressia/client/events/NewLocalEntityEvent.java
new file mode 100644
index 0000000..6e77028
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/client/events/NewLocalEntityEvent.java
@@ -0,0 +1,51 @@
+/*
+ * 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.events;
+
+import ru.windcorp.progressia.client.Client;
+import ru.windcorp.progressia.common.world.entity.EntityDataPlayer;
+
+public interface NewLocalEntityEvent extends ClientEvent {
+
+ EntityDataPlayer getNewEntity();
+ EntityDataPlayer getPreviousEntity();
+
+ public class Immutable extends ClientEvent.Default implements NewLocalEntityEvent {
+
+ private final EntityDataPlayer newEntity;
+ private final EntityDataPlayer previousEntity;
+
+ public Immutable(Client client, EntityDataPlayer newEntity, EntityDataPlayer previousEntity) {
+ super(client);
+ this.newEntity = newEntity;
+ this.previousEntity = previousEntity;
+ }
+
+ @Override
+ public EntityDataPlayer getNewEntity() {
+ return newEntity;
+ }
+
+ @Override
+ public EntityDataPlayer getPreviousEntity() {
+ return previousEntity;
+ }
+
+ }
+
+}
diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerHUD.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerHUD.java
new file mode 100644
index 0000000..eb3f8d5
--- /dev/null
+++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LayerHUD.java
@@ -0,0 +1,69 @@
+/*
+ * 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;
+
+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.Component;
+import ru.windcorp.progressia.client.graphics.gui.GUILayer;
+import ru.windcorp.progressia.client.graphics.gui.Group;
+import ru.windcorp.progressia.client.graphics.gui.layout.LayoutBorderHorizontal;
+import ru.windcorp.progressia.client.graphics.gui.layout.LayoutBorderVertical;
+import ru.windcorp.progressia.client.graphics.gui.layout.LayoutFill;
+import ru.windcorp.progressia.client.graphics.texture.SimpleTextures;
+import ru.windcorp.progressia.test.inv.SlotComponent;
+
+public class LayerHUD extends GUILayer {
+
+ public LayerHUD(Client client) {
+ super("LayerHUD", new LayoutFill(15));
+ setCursorPolicy(CursorPolicy.INDIFFERENT);
+
+ client.subscribe(this);
+ }
+
+ @Subscribe
+ private void onEntityChanged(NewLocalEntityEvent e) {
+ while (!getRoot().getChildren().isEmpty()) {
+ getRoot().removeChild(getRoot().getChild(0));
+ }
+
+ if (e.getNewEntity() == null) {
+ return;
+ }
+
+ Component content = new Group(getName() + ".Content", new LayoutBorderVertical());
+
+ Group handDisplays = new Group(
+ getName() + ".Hands",
+ new LayoutBorderHorizontal(),
+ new SlotComponent(getName() + ".Hands.LeftHand", e.getNewEntity().getLeftHand(), 0)
+ .setBackground(SimpleTextures.get("gui/LeftHand")).setScale(4).setLayoutHint(LayoutBorderHorizontal.LEFT),
+ new SlotComponent(getName() + ".Hands.RightHand", e.getNewEntity().getRightHand(), 0)
+ .setBackground(SimpleTextures.get("gui/RightHand")).setScale(4).setLayoutHint(LayoutBorderHorizontal.RIGHT)
+ );
+
+ content.addChild(handDisplays.setLayoutHint(LayoutBorderVertical.UP));
+
+ getRoot().addChild(content);
+ getRoot().requestReassembly();
+ }
+
+}
diff --git a/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java b/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java
index e24c5b9..79d88c2 100644
--- a/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java
+++ b/src/main/java/ru/windcorp/progressia/client/graphics/world/LocalPlayer.java
@@ -21,6 +21,7 @@ package ru.windcorp.progressia.client.graphics.world;
import org.apache.logging.log4j.LogManager;
import ru.windcorp.progressia.client.Client;
+import ru.windcorp.progressia.client.events.NewLocalEntityEvent;
import ru.windcorp.progressia.client.world.WorldRender;
import ru.windcorp.progressia.client.world.entity.EntityRenderable;
import ru.windcorp.progressia.common.world.entity.EntityData;
@@ -82,7 +83,7 @@ public class LocalPlayer {
}
if (playerEntity != lastKnownEntity) {
- getClient().onLocalPlayerEntityChanged(playerEntity, lastKnownEntity);
+ getClient().postEvent(new NewLocalEntityEvent.Immutable(getClient(), playerEntity, lastKnownEntity));
this.lastKnownEntity = playerEntity;
}
diff --git a/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java b/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java
index 5880410..f0b88eb 100644
--- a/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java
+++ b/src/main/java/ru/windcorp/progressia/test/inv/DecoratedSlotComponent.java
@@ -28,8 +28,12 @@ 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 = new SlotComponent(name, container, index);
+ this.slotComponent = component;
Vec2i size = slotComponent.getPreferredSize().add(2 * BORDER);
setPreferredSize(size);
diff --git a/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java b/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java
index 2cb13ba..1260c7e 100644
--- a/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java
+++ b/src/main/java/ru/windcorp/progressia/test/inv/SlotComponent.java
@@ -18,11 +18,19 @@
package ru.windcorp.progressia.test.inv;
import glm.mat._4.Mat4;
+import glm.vec._3.Vec3;
+import ru.windcorp.progressia.client.graphics.Colors;
+import ru.windcorp.progressia.client.graphics.backend.Usage;
+import ru.windcorp.progressia.client.graphics.flat.FlatRenderProgram;
import ru.windcorp.progressia.client.graphics.flat.RenderTarget;
import ru.windcorp.progressia.client.graphics.font.Font;
import ru.windcorp.progressia.client.graphics.gui.Component;
import ru.windcorp.progressia.client.graphics.gui.DynamicLabel;
import ru.windcorp.progressia.client.graphics.gui.layout.LayoutAlign;
+import ru.windcorp.progressia.client.graphics.model.Renderable;
+import ru.windcorp.progressia.client.graphics.model.Shape;
+import ru.windcorp.progressia.client.graphics.model.ShapeParts;
+import ru.windcorp.progressia.client.graphics.texture.Texture;
import ru.windcorp.progressia.client.world.item.ItemRenderRegistry;
import ru.windcorp.progressia.client.world.item.ItemRenderable;
import ru.windcorp.progressia.common.world.item.ItemContainer;
@@ -32,26 +40,28 @@ import ru.windcorp.progressia.common.world.item.ItemSlot;
public class SlotComponent extends Component {
static final float TEXTURE_SIZE = 24;
- static final float SCALE = 2;
private final ItemContainer container;
private final int index;
-
+
+ private float scale = 2;
+
private ItemRenderable itemRenderer = null;
private int amountDisplayInt = 0;
private String amountDisplayString = "";
+ private Renderable background = null;
+
public SlotComponent(String name, ItemContainer container, int index) {
super(name);
this.container = container;
this.index = index;
- int side = (int) (TEXTURE_SIZE * SCALE);
- setPreferredSize(side, side);
+ setScale(2);
Font sizeFont = new Font().deriveOutlined().withScale(1);
- addChild(new DynamicLabel(name + ".Size", sizeFont, () -> amountDisplayString, side));
+ addChild(new DynamicLabel(getName() + ".Size", sizeFont, () -> amountDisplayString, getPreferredSize().x));
setLayout(new LayoutAlign(0, 0, 0));
}
@@ -60,12 +70,36 @@ public class SlotComponent extends Component {
return container.getSlot(index);
}
+ public SlotComponent setScale(float scale) {
+ this.scale = scale;
+
+ int side = (int) (TEXTURE_SIZE * scale);
+ setPreferredSize(side, side);
+ invalidate();
+
+ return this;
+ }
+
+ public SlotComponent setBackground(Texture texture) {
+ background = new Shape(
+ Usage.STATIC,
+ FlatRenderProgram.getDefault(),
+ ShapeParts.createRectangle(
+ FlatRenderProgram.getDefault(),
+ texture,
+ Colors.WHITE,
+ new Vec3(0, 0, 0),
+ new Vec3(24, 0, 0),
+ new Vec3(0, 24, 0),
+ false
+ )
+ );
+ return this;
+ }
+
@Override
protected void assembleSelf(RenderTarget target) {
super.assembleSelf(target);
-
- updateItemRenderer();
-
assembleItem(target);
}
@@ -90,11 +124,19 @@ public class SlotComponent extends Component {
}
private void assembleItem(RenderTarget target) {
- if (itemRenderer != null) {
- target.pushTransform(new Mat4().translate(getX(), getY(), 0).scale(SCALE));
- target.addCustomRenderer(itemRenderer);
- target.popTransform();
- }
+ target.pushTransform(new Mat4().translate(getX(), getY(), 0).scale(scale));
+ target.addCustomRenderer(renderer -> {
+
+ updateItemRenderer();
+
+ if (itemRenderer != null) {
+ itemRenderer.render(renderer);
+ } else if (background != null) {
+ background.render(renderer);
+ }
+
+ });
+ target.popTransform();
}
}
diff --git a/src/main/resources/assets/textures/gui/LeftHand.png b/src/main/resources/assets/textures/gui/LeftHand.png
new file mode 100644
index 0000000..febc326
Binary files /dev/null and b/src/main/resources/assets/textures/gui/LeftHand.png differ
diff --git a/src/main/resources/assets/textures/gui/RightHand.png b/src/main/resources/assets/textures/gui/RightHand.png
new file mode 100644
index 0000000..55b5049
Binary files /dev/null and b/src/main/resources/assets/textures/gui/RightHand.png differ