Created
May 15, 2015 07:55
-
-
Save jarcode-foss/36a82d097f7fb9c926c8 to your computer and use it in GitHub Desktop.
This file contains hidden or 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
package jarcode.consoles; | |
import net.minecraft.server.v1_8_R2.*; | |
import java.lang.reflect.Field; | |
import java.util.Arrays; | |
public class CommandBlockListenerWrapper extends CommandBlockListenerAbstract { | |
private static final Field COMMAND_RESULT, CHAT_COMPONENT; | |
private static final String[] OVERRIDEN_COMMANDS = {"link"}; | |
private ConsoleListener consoleListener; | |
static { | |
try { | |
COMMAND_RESULT = CommandBlockListenerAbstract.class.getDeclaredField("b"); | |
CHAT_COMPONENT = CommandBlockListenerAbstract.class.getDeclaredField("d"); | |
COMMAND_RESULT.setAccessible(true); | |
CHAT_COMPONENT.setAccessible(true); | |
} | |
catch (Throwable e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private void setResult(int result) { | |
try { | |
COMMAND_RESULT.setInt(this, result); | |
} | |
catch (Throwable e) { | |
throw new RuntimeException(e); | |
} | |
} | |
private void setChatComponent(Object obj) { | |
try { | |
CHAT_COMPONENT.set(this, obj); | |
} | |
catch (Throwable e) { | |
throw new RuntimeException(e); | |
} | |
} | |
CommandBlockListenerAbstract underlying; | |
// this is a cheat to make this act like an inner class when we get this$0 via reflection later | |
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) | |
private final TileEntityCommand this$0; | |
CommandBlockListenerWrapper(CommandBlockListenerAbstract underlying, TileEntityCommand command) { | |
this.underlying = underlying; | |
this.this$0 = command; | |
} | |
public void setConsoleListener(ConsoleListener listener) { | |
consoleListener = listener; | |
} | |
public boolean listening() { | |
return consoleListener != null; | |
} | |
@Override | |
public int j() { | |
return underlying.j(); | |
} | |
@Override | |
public IChatBaseComponent k() { | |
return underlying.k(); | |
} | |
@Override | |
public void a(NBTTagCompound nbttagcompound) { | |
underlying.a(nbttagcompound); | |
} | |
@Override | |
public void b(NBTTagCompound nbttagcompound) { | |
underlying.b(nbttagcompound); | |
} | |
@Override | |
public boolean a(int i, String s) { | |
return underlying.a(i, s); | |
} | |
@Override | |
public void setCommand(String s) { | |
underlying.setCommand(s); | |
} | |
@Override | |
public String getCommand() { | |
return underlying.getCommand(); | |
} | |
private boolean override() { | |
String command = getCommand().toLowerCase(); | |
if(command.startsWith("/")) { | |
command = command.substring(1); | |
} | |
command = command.split(" ")[0]; | |
return Arrays.asList(OVERRIDEN_COMMANDS).contains(command); | |
} | |
@Override | |
public void a(World world) { | |
if (consoleListener != null) { | |
sendMessage(new ChatComponentText(consoleListener.execute(this.sender, getCommand()))); | |
setResult(0); | |
return; | |
} | |
if (!ConsoleHandler.getInstance().commandBlocksEnabled && !override()) { | |
setChatComponent(new ChatComponentText("You cannot use server commands")); | |
h(); | |
setResult(0); | |
return; | |
} | |
if(world.isClientSide) { | |
setResult(0); | |
} | |
MinecraftServer minecraftserver = MinecraftServer.getServer(); | |
if(minecraftserver != null && minecraftserver.N()) { | |
minecraftserver.getCommandHandler(); | |
try { | |
setChatComponent(null); | |
setResult(executeCommand(this, this.sender, getCommand())); | |
} catch (Throwable var6) { | |
var6.printStackTrace(); | |
} | |
} else { | |
setResult(0); | |
} | |
} | |
@Override | |
public String getName() { | |
return underlying.getName(); | |
} | |
@Override | |
public IChatBaseComponent getScoreboardDisplayName() { | |
return underlying.getScoreboardDisplayName(); | |
} | |
@Override | |
public void setName(String s) { | |
underlying.setName(s); | |
} | |
@Override | |
public void sendMessage(IChatBaseComponent ichatbasecomponent) { | |
underlying.sendMessage(ichatbasecomponent); | |
} | |
@Override | |
public boolean getSendCommandFeedback() { | |
return underlying.getSendCommandFeedback(); | |
} | |
@Override | |
public void a(CommandObjectiveExecutor.EnumCommandResult result, int i) { | |
underlying.a(result, i); | |
} | |
@Override | |
public void h() { | |
underlying.h(); | |
} | |
@Override | |
public void b(IChatBaseComponent ichatbasecomponent) { | |
underlying.b(ichatbasecomponent); | |
} | |
@Override | |
public void a(boolean flag) { | |
underlying.a(flag); | |
} | |
@Override | |
public boolean m() { | |
return underlying.m(); | |
} | |
@Override | |
public boolean a(EntityHuman entityhuman) { | |
return override() || underlying.a(entityhuman); | |
} | |
@Override | |
public CommandObjectiveExecutor n() { | |
return underlying.n(); | |
} | |
@Override | |
public BlockPosition getChunkCoordinates() { | |
return null; | |
} | |
@Override | |
public Vec3D d() { | |
return underlying.d(); | |
} | |
@Override | |
public World getWorld() { | |
return underlying.getWorld(); | |
} | |
@Override | |
public Entity f() { | |
return underlying.f(); | |
} | |
} |
This file contains hidden or 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
// ... previous code | |
private static final Field PACKET_LIST; | |
private static final Field PACKET_ENTITY_ID; | |
private static final Field COMMAND_LISTENER; | |
static { | |
try { | |
PACKET_LIST = PacketPlayOutEntityMetadata.class.getDeclaredField("b"); | |
PACKET_LIST.setAccessible(true); | |
PACKET_ENTITY_ID = PacketPlayOutEntityMetadata.class.getDeclaredField("a"); | |
PACKET_ENTITY_ID.setAccessible(true); | |
// important part here | |
COMMAND_LISTENER = TileEntityCommand.class.getDeclaredField("a"); | |
COMMAND_LISTENER.setAccessible(true); | |
overrideFinal(COMMAND_LISTENER); | |
} | |
catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
static { | |
INSTANCE.paintThread.start(); | |
} | |
private static Object get(Field field, Object instance) { | |
try { | |
return field.get(instance); | |
} | |
catch (Exception e) { | |
throw new RuntimeException(e); | |
} | |
} | |
public static ConsoleHandler getInstance() { | |
return INSTANCE; | |
} | |
public static boolean isRegistered(CommandBlock block) { | |
TileEntityCommand entity = ((CraftCommandBlock) block).getTileEntity(); | |
CommandBlockListenerAbstract obj = entity.getCommandBlock(); | |
return obj instanceof CommandBlockListenerWrapper && ((CommandBlockListenerWrapper) obj).listening(); | |
} | |
public static boolean registerListener(CommandBlock block, ConsoleListener listener) { | |
TileEntityCommand entity = ((CraftCommandBlock) block).getTileEntity(); | |
CommandBlockListenerAbstract obj = entity.getCommandBlock(); | |
if (obj instanceof CommandBlockListenerWrapper && !isRegistered(block)) { | |
((CommandBlockListenerWrapper) obj).setConsoleListener(listener); | |
return true; | |
} | |
else return false; | |
} | |
public static boolean wrap(CommandBlock block) { | |
try { | |
TileEntityCommand entity = ((CraftCommandBlock) block).getTileEntity(); | |
CommandBlockListenerAbstract obj = entity.getCommandBlock(); | |
if (!(obj instanceof CommandBlockListenerWrapper)) { | |
COMMAND_LISTENER.set(entity, new CommandBlockListenerWrapper(obj, entity)); | |
return true; | |
} | |
else return false; | |
} | |
catch (IllegalAccessException e) { | |
e.printStackTrace(); | |
} | |
return false; | |
} | |
public static boolean restoreCommandBlock(CommandBlock block) { | |
TileEntityCommand entity = ((CraftCommandBlock) block).getTileEntity(); | |
Object obj = entity.getCommandBlock(); | |
if (obj instanceof CommandBlockListenerWrapper) { | |
((CommandBlockListenerWrapper) obj).setConsoleListener(null); | |
return true; | |
} | |
else return false; | |
} | |
private static void overrideFinal(Field field) throws NoSuchFieldException, IllegalAccessException { | |
Field modifiersField = Field.class.getDeclaredField("modifiers"); | |
modifiersField.setAccessible(true); | |
// remove the final flag on the security int/bytes | |
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL); | |
} | |
// more code... |
This file contains hidden or 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
import org.bukkit.command.CommandSender; | |
public interface ConsoleListener { | |
public String execute(CommandSender sender, String text); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment