Skip to content

Commit

Permalink
Increment version [build] [publish]
Browse files Browse the repository at this point in the history
  • Loading branch information
Mrbysco committed Mar 27, 2024
1 parent d6e800a commit 172713b
Show file tree
Hide file tree
Showing 11 changed files with 349 additions and 3 deletions.
2 changes: 1 addition & 1 deletion changelog.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* Fix the lock button not immediately sending the update packet when pressed
* Add a button that shows a list of nearby armor stands, allowing you select armor stands that are inside walls / hidden
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.mrbysco.armorposer.client;

import java.util.UUID;

public class GlowHandler {
private static long glowStartTime = 0;
private static UUID glowingStand = null;

public static boolean shouldArmorStandGlow() {
if (glowStartTime == -1) {
return false;
}
boolean notEmpty = glowingStand != null;
if (notEmpty && System.currentTimeMillis() - glowStartTime > 5000) {
glowStartTime = -1;
glowingStand = null;
}
return notEmpty;
}

public static boolean isGlowing(UUID uuid) {
if (!shouldArmorStandGlow())
return false;
else
return glowingStand != null && glowingStand.equals(uuid);
}

public static void startGlowing(UUID uuid) {
glowStartTime = System.currentTimeMillis();
glowingStand = uuid;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
package com.mrbysco.armorposer.client.gui;

import com.mrbysco.armorposer.client.GlowHandler;
import com.mrbysco.armorposer.client.gui.widgets.ArmorGlowWidget;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.commands.arguments.EntityAnchorArgument;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.EntitySelector;
import net.minecraft.world.entity.decoration.ArmorStand;

import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

public class ArmorGlowScreen extends Screen {
private static final int PADDING = 6;

private ArmorGlowWidget armorListWidget;
private ArmorGlowWidget.ListEntry selected = null;
private List<ArmorStand> armorStands;
private Button locateButton;
private Button modifyButton;

public ArmorStandScreen parentScreen;

public ArmorGlowScreen(ArmorStandScreen parent) {
super(Component.translatable("armorposer.gui.armor_list.list"));
this.parentScreen = parent;

this.minecraft = Minecraft.getInstance();

//Add the armor stands to the list
if (minecraft.player == null)
this.onClose();

List<ArmorStand> armorStands = minecraft.level.getEntitiesOfClass(ArmorStand.class,
minecraft.player.getBoundingBox().inflate(30.0D), EntitySelector.LIVING_ENTITY_STILL_ALIVE).stream().collect(Collectors.toList());
//Sort the list based on how far the armor stand is from the player
armorStands.sort((armorStand, armorStand2) -> {
double distance1 = armorStand.distanceToSqr(minecraft.player);
double distance2 = armorStand2.distanceToSqr(minecraft.player);
return Double.compare(distance1, distance2);
});
this.armorStands = Collections.unmodifiableList(armorStands);
}

@Override
public boolean isPauseScreen() {
return false;
}

@Override
protected void init() {
int centerWidth = this.width / 2;
int listWidth = this.width / 4 + 20;
int structureWidth = this.width - listWidth - (PADDING * 3);
int closeButtonWidth = Math.min(structureWidth, 160);
int y = this.height - 20 - PADDING;
this.addRenderableWidget(Button.builder(Component.translatable("gui.cancel"), b -> ArmorGlowScreen.this.onClose())
.bounds(centerWidth - (closeButtonWidth / 2) + PADDING, y, closeButtonWidth, 20).build());

y -= 18 + PADDING;
int buttonWidth = (closeButtonWidth / 2) - 1;
this.addRenderableWidget(this.locateButton = Button.builder(Component.translatable("armorposer.gui.armor_list.locate"), b -> {
if (selected != null && minecraft.player != null) {
GlowHandler.startGlowing(this.selected.getArmorStand().getUUID());
minecraft.player.lookAt(EntityAnchorArgument.Anchor.EYES, selected.getArmorStand().position());
}
}).bounds(centerWidth - (closeButtonWidth / 2) + PADDING, y, buttonWidth, 20).build());
this.addRenderableWidget(this.modifyButton = Button.builder(Component.translatable("armorposer.gui.armor_list.modify"), b -> {
if (selected != null && minecraft.player != null) {
minecraft.setScreen(new ArmorStandScreen(selected.getArmorStand()));
}
}).bounds(centerWidth - (closeButtonWidth / 2) + PADDING + buttonWidth + 2, y, buttonWidth, 20).build());

int fullButtonHeight = PADDING + 20 + PADDING;
this.armorListWidget = new ArmorGlowWidget(this, Component.translatable("armorposer.gui.armor_list.list"), listWidth, fullButtonHeight, 14 - getScreenFont().lineHeight);
this.armorListWidget.setX(0);
this.armorListWidget.setY(10);
this.armorListWidget.setHeight(this.height);

addWidget(armorListWidget);

updateCache();
}

@Override
public void tick() {
armorListWidget.setSelected(selected);
}

public <T extends ObjectSelectionList.Entry<T>> void buildPositionList(Consumer<T> ListViewConsumer, Function<ArmorStand, T> newEntry) {
armorStands.forEach(stand -> ListViewConsumer.accept(newEntry.apply(stand)));
}

@Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) {
this.armorListWidget.render(guiGraphics, mouseX, mouseY, partialTicks);
super.render(guiGraphics, mouseX, mouseY, partialTicks);
}

@Override
public boolean keyPressed(int keyCode, int scanCode, int modifiers) {
return super.keyPressed(keyCode, scanCode, modifiers);
}

@Override
public void renderBackground(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) {
//Nope
}

public void setSelected(ArmorGlowWidget.ListEntry entry) {
this.selected = entry == this.selected ? null : entry;
updateCache();
}

private void updateCache() {
this.locateButton.active = selected != null;
this.modifyButton.active = selected != null;
}

/**
* Clear the search field when right-clicked on it
*/
@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
return super.mouseClicked(mouseX, mouseY, button);
}

@Override
public void resize(Minecraft mc, int width, int height) {
ArmorGlowWidget.ListEntry selected = this.selected;
this.init(mc, width, height);
this.selected = selected;
updateCache();
}

@Override
public void onClose() {
this.minecraft.setScreen(parentScreen);
}

public Minecraft getScreenMinecraft() {
return this.minecraft;
}

public Font getScreenFont() {
return this.font;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import com.mojang.math.Axis;
import com.mrbysco.armorposer.Reference;
import com.mrbysco.armorposer.client.GlowHandler;
import com.mrbysco.armorposer.client.gui.widgets.NumberFieldBox;
import com.mrbysco.armorposer.client.gui.widgets.ToggleButton;
import com.mrbysco.armorposer.data.SwapData;
import com.mrbysco.armorposer.platform.Services;
import com.mrbysco.armorposer.util.ArmorStandData;
import net.minecraft.ChatFormatting;
import net.minecraft.Util;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
Expand Down Expand Up @@ -516,6 +518,9 @@ public void init() {
this.updateEntity(this.armorStandData.writeToNBT());
this.minecraft.setScreen((Screen) null);
}).bounds(offsetX - 95, offsetY + 22, 97, 20).build());
this.addRenderableWidget(Button.builder(Component.literal("💡"), (button) -> {
this.minecraft.setScreen(new ArmorGlowScreen(this));
}).bounds(0, 0, 16, 16).build());
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package com.mrbysco.armorposer.client.gui.widgets;

import com.mrbysco.armorposer.client.gui.ArmorGlowScreen;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.screens.inventory.InventoryScreen;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.decoration.ArmorStand;
import org.joml.Quaternionf;
import org.joml.Vector3f;

public class ArmorGlowWidget extends ObjectSelectionList<ArmorGlowWidget.ListEntry> {
private static final Vector3f ARMOR_STAND_TRANSLATION = new Vector3f();
private static final Quaternionf ARMOR_STAND_ANGLE = new Quaternionf().rotationXYZ(0.43633232F, 0.0F, (float) Math.PI);

private final ArmorGlowScreen parent;
private final int listWidth;
private final Component title;

public ArmorGlowWidget(ArmorGlowScreen parent, Component title, int listWidth, int top, int bottom) {
super(parent.getScreenMinecraft(), listWidth, bottom - top, top, parent.getScreenFont().lineHeight * 2 + 16);
this.parent = parent;
this.title = title;
this.listWidth = listWidth;
this.refreshList();
this.setRenderBackground(false);
}

@Override
protected int getScrollbarPosition() {
return this.getX() + this.listWidth - 6;
}

@Override
public int getRowWidth() {
return this.listWidth;
}

public void refreshList() {
this.clearEntries();
parent.buildPositionList(this::addEntry, location -> new ListEntry(location, this.parent));
}

@Override
protected void renderSelection(GuiGraphics guiGraphics, int top, int width, int height, int outerColor, int innerColor) {
int xPos = this.getX() + (this.width - width) / 2;
int xPos2 = this.getX() + (this.width + width) / 2;
guiGraphics.fillGradient(xPos, top - 2, xPos2, top + height + 2, -1945083888, -1676648432);
}

@Override
public void renderWidget(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) {
guiGraphics.fillGradient(getX(), 0, getX() + this.listWidth, parent.height, -1945104368, -1676668912);
super.renderWidget(guiGraphics, mouseX, mouseY, partialTicks);
guiGraphics.drawCenteredString(this.parent.getScreenFont(), title, getX() + this.listWidth / 2, 2, 16777215);
}

public class ListEntry extends Entry<ListEntry> {
private final ArmorGlowScreen parent;
private ArmorStand armorStand;

ListEntry(ArmorStand armorStand, ArmorGlowScreen parent) {
this.armorStand = armorStand;
this.parent = parent;
}

@Override
public void render(GuiGraphics guiGraphics, int entryIdx, int top, int left, int entryWidth, int entryHeight,
int mouseX, int mouseY, boolean hovered, float partialTicks) {
Font font = this.parent.getScreenFont();
renderScrollingString(guiGraphics, font, getPositionComponent(), left + 36, top + 10, left + width - 18, top + 20, 0xFFFFFF);

renderPose(guiGraphics, left + 16, top + 28, 15);
}

public ArmorStand getArmorStand() {
return armorStand;
}

public void renderPose(GuiGraphics guiGraphics, int xPos, int yPos, int size) {
if (armorStand != null) {
InventoryScreen.renderEntityInInventory(guiGraphics, xPos, yPos, size,
ARMOR_STAND_TRANSLATION, ARMOR_STAND_ANGLE, (Quaternionf) null, this.armorStand);
}
}

@Override
public void renderBack(GuiGraphics guiGraphics, int mouseX, int mouseY, int $$3, int $$4, int $$5, int $$6, int $$7, boolean $$8, float $$9) {
super.renderBack(guiGraphics, mouseX, mouseY, $$3, $$4, $$5, $$6, $$7, $$8, $$9);
}

@Override
public boolean mouseClicked(double mouseX, double mouseY, int button) {
parent.setSelected(this);
ArmorGlowWidget.this.setSelected(this);
return false;
}

public Component getPositionComponent() {
return Component.literal(getArmorStand().blockPosition().toShortString());
}

@Override
public Component getNarration() {
return getPositionComponent();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.mrbysco.armorposer.mixin;

import com.mrbysco.armorposer.client.GlowHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.ArmorStand;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(Minecraft.class)
public class MinecraftMixin {

@Inject(method = "shouldEntityAppearGlowing(Lnet/minecraft/world/entity/Entity;)Z",
at = @At("HEAD"), cancellable = true)
public void armorposer$shouldEntityAppearGlowing(Entity entity, CallbackInfoReturnable<Boolean> cir) {
if (entity instanceof ArmorStand && GlowHandler.isGlowing(entity.getUUID()))
cir.setReturnValue(true);
}
}
4 changes: 4 additions & 0 deletions common/src/main/resources/assets/armorposer/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,10 @@
"armorposer.gui.delete_poose.title": "Delete pose",
"armorposer.gui.delete_poose.message": "Are you sure you want to remove this pose?",

"armorposer.gui.armor_list.list": "Armor Stands",
"armorposer.gui.armor_list.locate": "Locate",
"armorposer.gui.armor_list.modify": "Modify",

"armorposer.config.enableConfigGui": "Enable GUI",
"armorposer.config.enableConfigGui.tooltip": "Show the Armor Stand configuration GUI on shift right click",

Expand Down
1 change: 1 addition & 0 deletions fabric/src/main/resources/armorposer.fabric.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"ArmorStandMixin"
],
"client": [
"MinecraftMixin"
],
"injectors": {
"defaultRequire": 1
Expand Down
4 changes: 3 additions & 1 deletion forge/src/main/resources/META-INF/mods.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@ modId="neoforge"
type="REQUIRED"
versionRange="[20.4.70-beta,)"
ordering="NONE"
side="BOTH"
side="BOTH"
[[mixins]]
config="armorposer.neoforge.mixins.json"
15 changes: 15 additions & 0 deletions forge/src/main/resources/armorposer.neoforge.mixins.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"required": true,
"minVersion": "0.8.4",
"package": "com.mrbysco.armorposer.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
],
"client": [
"MinecraftMixin"
],
"injectors": {
"defaultRequire": 1
}
}

Loading

0 comments on commit 172713b

Please sign in to comment.