Skip to content

Commit

Permalink
More fixes to gui buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
kill05 committed Jun 17, 2024
1 parent dec317d commit 77474f7
Show file tree
Hide file tree
Showing 8 changed files with 142 additions and 48 deletions.
2 changes: 1 addition & 1 deletion src/main/java/turniplabs/halplibe/HalpLibe.java
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ public void onInitialize() {
NetworkHelper.register(PacketOpenGui.class, false, true);
NetworkHelper.register(PacketOpenItemGui.class, false, true);
NetworkHelper.register(PacketOpenBlockGui.class, false, true);
NetworkHelper.register(PacketGuiButtonClick.class, true, false);
NetworkHelper.register(PacketGuiButtonClick.class, true, true);

LOGGER.info("HalpLibe initialized.");
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package turniplabs.halplibe.mixin.accessors.gui;
package turniplabs.halplibe.helper.gui;

import turniplabs.halplibe.helper.gui.GuiHelper;
import turniplabs.halplibe.helper.gui.registered.RegisteredGui;

public interface GuiScreenAccessor {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import net.minecraft.core.item.ItemStack;
import net.minecraft.core.player.inventory.Container;
import net.minecraft.server.entity.player.EntityPlayerMP;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import turniplabs.halplibe.helper.gui.packet.PacketOpenBlockGui;
Expand All @@ -15,14 +16,52 @@

public interface IGuiFactory {

/**
* Called to create a gui screen on a client.
*
* @param gui the registered gui that needs to create a gui
* @param player the player that will see the gui
* @param itemStack an item, in case the gui is an item gui
* @param x x coordinate, in case the gui is a block gui
* @param y y coordinate, in case the gui is a block gui
* @param z z coordinate, in case the gui is a block gui
* @return a new gui
*/
@ApiStatus.Internal
@NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @Nullable ItemStack itemStack, int x, int y, int z);

/**
* Called to create a gui container on a server.
*
* @param gui the registered gui that needs to create a container
* @param player the player that will open the container
* @param itemStack an item, in case the gui is an item gui
* @param x x coordinate, in case the gui is a block gui
* @param y y coordinate, in case the gui is a block gui
* @param z z coordinate, in case the gui is a block gui
* @return a new container
*/
@ApiStatus.Internal
@Nullable Container createContainer(@NotNull RegisteredGui gui, @NotNull EntityPlayerMP player, @Nullable ItemStack itemStack, int x, int y, int z);

default void onButtonPress(@NotNull RegisteredGui gui, @NotNull EntityPlayer player, int button) {
/**
* Called when a gui interaction happens.<p>
* The player and clicker parameter are not the same when a client acknowledges
* that another player has pressed a button.<p>
* As an example, if player1 clicked a button on a server,
* this method will be called on player2's client
* with player2 as the player argument and player1 as the clicker argument
*
* @param gui the registered gui that was clicked
* @param player the player that acknowledges that a player has pressed a button
* @param clicker the player that clicked the button
* @param buttonId the id of the button
*/
default void onButtonClick(@NotNull RegisteredGui gui, @NotNull EntityPlayer player, @NotNull EntityPlayer clicker, int buttonId) {

}

@ApiStatus.Internal
default @NotNull GuiScreen createGui(@NotNull RegisteredGui gui, @NotNull EntityPlayerSP player, @NotNull PacketOpenGui packet) {
if(!gui.isServerSide()) throw new IllegalStateException("Gui is client side!");

Expand All @@ -38,6 +77,7 @@ default void onButtonPress(@NotNull RegisteredGui gui, @NotNull EntityPlayer pla
return createGui(gui, player, null, 0, -100, 0);
}

@ApiStatus.Internal
default @NotNull PacketOpenGui createGuiPacket(@NotNull RegisteredGui gui, int windowId, @NotNull EntityPlayerMP player, @Nullable ItemStack itemStack, int x, int y, int z) {
if(!gui.isServerSide()) throw new IllegalStateException("Gui is client side!");

Expand All @@ -52,6 +92,7 @@ default void onButtonPress(@NotNull RegisteredGui gui, @NotNull EntityPlayer pla
return new PacketOpenGui(gui, windowId);
}

@ApiStatus.Internal
default void throwInvalidException(String message) {
throw new IllegalArgumentException(String.format("Invalid arguments for gui factory '%s': %s", getClass(), message));
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
package turniplabs.halplibe.helper.gui.packet;

import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.EntityPlayerSP;
import net.minecraft.client.world.WorldClient;
import net.minecraft.core.entity.Entity;
import net.minecraft.core.entity.player.EntityPlayer;
import net.minecraft.core.net.handler.NetHandler;
import net.minecraft.core.net.packet.Packet;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.entity.player.EntityPlayerMP;
import org.apache.commons.lang3.reflect.FieldUtils;
import turniplabs.halplibe.HalpLibe;
import turniplabs.halplibe.helper.gui.GuiHelper;
import turniplabs.halplibe.helper.gui.registered.RegisteredGui;
import turniplabs.halplibe.util.PlayerUtils;

import java.io.DataInputStream;
import java.io.DataOutputStream;
Expand All @@ -14,11 +21,17 @@
public class PacketGuiButtonClick extends Packet {

public String guiNamespace;
public int id;
public int buttonId;
public int clickerId;

public PacketGuiButtonClick(String guiNamespace, int id) {
public PacketGuiButtonClick(String guiNamespace, int buttonId, int clickerId) {
this.guiNamespace = guiNamespace;
this.id = id;
this.buttonId = buttonId;
this.clickerId = clickerId;
}

public PacketGuiButtonClick(String guiNamespace, int buttonId) {
this(guiNamespace, buttonId, -1);
}

public PacketGuiButtonClick() {
Expand All @@ -28,29 +41,52 @@ public PacketGuiButtonClick() {
@Override
public void readPacketData(DataInputStream input) throws IOException {
this.guiNamespace = input.readUTF();
this.id = input.readInt();
this.buttonId = input.readInt();
this.clickerId = input.readInt();
}

@Override
public void writePacketData(DataOutputStream output) throws IOException {
if(guiNamespace == null) throw new IOException("GUI Namespace can't be null!");
output.writeUTF(guiNamespace);
output.writeInt(id);
output.writeInt(buttonId);
output.writeInt(clickerId);
}

@Override
public void processPacket(NetHandler netHandler) {
try {
EntityPlayerMP playerMP = (EntityPlayerMP) FieldUtils.readField(netHandler, "playerEntity", true);
RegisteredGui gui = GuiHelper.getGui(guiNamespace);
gui.getFactory().onButtonPress(gui, playerMP, id);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
RegisteredGui gui = GuiHelper.getGui(guiNamespace);
if(gui == null) {
HalpLibe.LOGGER.warn("Invalid gui id in packet: " + guiNamespace);
return;
}

EntityPlayer player = PlayerUtils.getPlayer(netHandler);
EntityPlayer clicker = null;
if(player.craftingInventory == null) return;

if(player instanceof EntityPlayerMP) {
Packet packet = new PacketGuiButtonClick(guiNamespace, buttonId, player.id);
clicker = player;

for (EntityPlayerMP other : MinecraftServer.getInstance().playerList.playerEntities) {
if(other == player) continue;
if(other.craftingInventory == null || other.craftingInventory.windowId != player.craftingInventory.windowId) continue;
other.playerNetServerHandler.sendPacket(packet);
}
}

if(player instanceof EntityPlayerSP) {
WorldClient world = (WorldClient) Minecraft.getMinecraft(this).theWorld;
Entity entity = world.getEntityFromId(clickerId);
if(entity instanceof EntityPlayer) clicker = (EntityPlayer) entity;
}

if(clicker != null) gui.getFactory().onButtonClick(gui, player, clicker, buttonId);
}

@Override
public int getPacketSize() {
return guiNamespace.length() + 4;
return guiNamespace.length() + 4 * 2;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import net.minecraft.core.net.handler.NetHandler;
import net.minecraft.core.net.packet.Packet;
import org.jetbrains.annotations.NotNull;
import turniplabs.halplibe.HalpLibe;
import turniplabs.halplibe.helper.gui.GuiHelper;
import turniplabs.halplibe.helper.gui.registered.RegisteredGui;

Expand Down Expand Up @@ -39,7 +40,13 @@ public void writePacketData(DataOutputStream output) throws IOException {

@Override
public void processPacket(NetHandler netHandler) {
GuiHelper.getGui(guiNamespace).handleOpenPacket(this);
RegisteredGui gui = GuiHelper.getGui(guiNamespace);
if(gui == null) {
HalpLibe.LOGGER.warn("Invalid gui id in packet: " + guiNamespace);
return;
}

gui.handleOpenPacket(this);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
import turniplabs.halplibe.helper.gui.factory.block.TileGuiFactory;
import turniplabs.halplibe.helper.gui.factory.item.ItemGuiFactory;
import turniplabs.halplibe.helper.gui.packet.PacketOpenGui;
import turniplabs.halplibe.mixin.accessors.gui.GuiScreenAccessor;
import turniplabs.halplibe.helper.gui.GuiScreenAccessor;

import java.util.Random;
import java.util.regex.Pattern;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,20 @@

import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.EntityClientPlayerMP;
import net.minecraft.client.entity.player.EntityPlayerSP;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.core.util.helper.Listener;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import turniplabs.halplibe.helper.gui.GuiScreenAccessor;
import turniplabs.halplibe.helper.gui.packet.PacketGuiButtonClick;
import turniplabs.halplibe.helper.gui.registered.RegisteredGui;
import turniplabs.halplibe.mixin.accessors.gui.GuiScreenAccessor;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;

@SuppressWarnings("AddedMixinMembersNamePattern")
@Mixin(
Expand All @@ -28,37 +27,27 @@ public class GuiScreenMixin implements GuiScreenAccessor {
@Unique
private String guiNamespace;

@Shadow
public List<GuiButton> controlList;


@Inject(
method = "init",
at = @At("RETURN")
method = "mouseClicked",
locals = LocalCapture.CAPTURE_FAILHARD,
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/sound/SoundManager;playSound(Ljava/lang/String;Lnet/minecraft/core/sound/SoundCategory;FF)V",
shift = At.Shift.AFTER
)
)
public void injectInit(CallbackInfo ci) {
Minecraft mc = Minecraft.getMinecraft(GuiScreenMixin.class);
public void injectMouseClicked(int mouseX, int mouseY, int mouseButton, CallbackInfo ci, Iterator<GuiButton> unused, GuiButton button) {
RegisteredGui gui = getRegisteredGui();
if(gui == null) return;

List<Integer> ids = new ArrayList<>(controlList.size());
for (GuiButton button : controlList) {
if (ids.contains(button.id))
throw new IllegalStateException(String.format("Found button in gui '%s' with duplicate id: '%s'.", gui, button.id));

final Listener<GuiButton> oldListener = button.listener;
button.setListener(aButton -> {
if (mc.thePlayer instanceof EntityClientPlayerMP) {
EntityClientPlayerMP playerMP = (EntityClientPlayerMP) mc.thePlayer;
playerMP.sendQueue.addToSendQueue(new PacketGuiButtonClick(getGuiNamespace(), aButton.id));
}
EntityPlayerSP player = Minecraft.getMinecraft(GuiScreenMixin.class).thePlayer;

gui.getFactory().onButtonPress(gui, mc.thePlayer, aButton.id);
if(oldListener != null) oldListener.listen(aButton);
});

ids.add(button.id);
if (player instanceof EntityClientPlayerMP) {
EntityClientPlayerMP playerMP = (EntityClientPlayerMP) player;
playerMP.sendQueue.addToSendQueue(new PacketGuiButtonClick(getGuiNamespace(), button.id));
}

gui.getFactory().onButtonClick(gui, player, player, button.id);
}

@Override
Expand Down
22 changes: 22 additions & 0 deletions src/main/java/turniplabs/halplibe/util/PlayerUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package turniplabs.halplibe.util;

import net.minecraft.client.Minecraft;
import net.minecraft.core.entity.player.EntityPlayer;
import net.minecraft.core.net.handler.NetHandler;
import org.apache.commons.lang3.reflect.FieldUtils;

public final class PlayerUtils {

public static EntityPlayer getPlayer(NetHandler handler) {
if(handler.isServerHandler()) {
try {
return (EntityPlayer) FieldUtils.readField(handler, "playerEntity", true);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}

return Minecraft.getMinecraft(PlayerUtils.class).thePlayer;
}

}

0 comments on commit 77474f7

Please sign in to comment.