-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
349 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
32 changes: 32 additions & 0 deletions
32
common/src/main/java/com/mrbysco/armorposer/client/GlowHandler.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
157 changes: 157 additions & 0 deletions
157
common/src/main/java/com/mrbysco/armorposer/client/gui/ArmorGlowScreen.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
109 changes: 109 additions & 0 deletions
109
common/src/main/java/com/mrbysco/armorposer/client/gui/widgets/ArmorGlowWidget.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
common/src/main/java/com/mrbysco/armorposer/mixin/MinecraftMixin.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,6 +8,7 @@ | |
"ArmorStandMixin" | ||
], | ||
"client": [ | ||
"MinecraftMixin" | ||
], | ||
"injectors": { | ||
"defaultRequire": 1 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} | ||
} | ||
|
Oops, something went wrong.