Posted February 20, 20178 yr Hey, so I was trying to send a packet to the server and get the output and that works the problem is that since I send an addScheduledTask the output from that comes later that the return statement. So basically I have to delay the return statement until my runnable executes on the main thread. Here is some of my code. HandlerRunCommand.java package com.radar.commandblockmod.packages; import net.minecraft.client.Minecraft; import net.minecraft.command.CommandResultStats.Type; import net.minecraft.command.ICommandManager; import net.minecraft.command.ICommandSender; import net.minecraft.entity.Entity; import net.minecraft.server.MinecraftServer; import net.minecraft.util.IThreadListener; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.world.World; import net.minecraft.world.WorldServer; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.common.network.simpleimpl.IMessage; import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler; import net.minecraftforge.fml.common.network.simpleimpl.MessageContext; public class HandlerRunCommand implements IMessageHandler <RunCommandMessage, IMessage>{ private MessageContext ctx; private int out; @Override public IMessage onMessage(RunCommandMessage message, final MessageContext ctx) { final String command = message.getCommand(); final int x = message.getxPos(); final int y = message.getyPos(); final int z = message.getzPos(); final String name = message.getName(); IThreadListener mainThread = (WorldServer) ctx.getServerHandler().playerEntity.worldObj; mainThread.addScheduledTask(new Runnable() { @Override public void run() { RunCommands onServer = new RunCommands(command,x,y,z,name); out = onServer.run(); System.out.println("Sent "+out); } class RunCommands implements ICommandSender{ public ICommandSender instance; private int x,y,z; private String nameBlock, command; public RunCommands(String command, int x, int y, int z, String name){ this.x = x; this.y = y; this.z = z; this.command = command; this.nameBlock = name; } public int run (){ ICommandManager icommandmanager = ctx.getServerHandler().playerEntity.worldObj.getMinecraftServer().commandManager; return icommandmanager.executeCommand(this, this.command); } @Override public String getName() { return ctx.getServerHandler().playerEntity.getName(); } @Override public ITextComponent getDisplayName() { ITextComponent name = new TextComponentString(this.nameBlock); return name; } @Override public void addChatMessage(ITextComponent component) { } @Override public boolean canCommandSenderUseCommand(int permLevel, String commandName) { return true; } @Override public BlockPos getPosition() { return new BlockPos(x,y,z); } @Override public Vec3d getPositionVector() { return ctx.getServerHandler().playerEntity.getPositionVector(); } @Override public World getEntityWorld() { return ctx.getServerHandler().playerEntity.worldObj; } @Override public Entity getCommandSenderEntity() { return ctx.getServerHandler().playerEntity; } @Override public boolean sendCommandFeedback() { return true; } @Override public void setCommandStat(Type type, int amount) { } @Override public MinecraftServer getServer() { return ctx.getServerHandler().playerEntity.worldObj.getMinecraftServer(); } } }); return new ReturnCommandOut(x,y,z,out); } } I hope this helps thanks!
February 20, 20178 yr You can't delay the return statement, but you can just send the response packet from the SimpleNetworkWrapper as you would a regular packet. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
February 20, 20178 yr Author From what you said I should put it after all my other code in the run() class, correct? Where do I send the packet to because I need to specify a player on the client. Would Minecraft.getMinecraft.thePlayer work? Figured it out had to use ctx.getServerHandler().playerEntity Edited February 20, 20178 yr by Radar6255 Solved
February 20, 20178 yr Author Okay now for another problem that I was having related to this which is when I get the packet that I just received I need to wait until it is sent to my block before further action. Basically I have to wait until the packet has set the data then have my block use that data after it is done to set the comparator output. I need to wait for the packet in this code. @Override public void neighborChanged(IBlockState state, World worldIn, BlockPos pos, Block blockIn, BlockPos p_189540_5_) { if (worldIn.isBlockPowered(pos) & previousState != worldIn.isBlockPowered(pos)){ TileEntityDiamondCommand tile = (TileEntityDiamondCommand) Minecraft.getMinecraft().theWorld.getTileEntity(pos); commandblockmod.network.sendToServer(new RunCommandMessage(tile.getCommand(),pos.getX(),pos.getY(),pos.getZ(),"Diamond Command Block")); try { Thread.sleep(50); } catch (InterruptedException e) { e.printStackTrace(); } out = tile.getOut(); System.out.println("Update "+out); if (out > 0){ out = 15; }else{ out = 0; } worldIn.updateComparatorOutputLevel(pos, this); } previousState = worldIn.isBlockPowered(pos); } public boolean hasComparatorInputOverride(IBlockState state) { return true; } public int getComparatorInputOverride(IBlockState blockState, World worldIn, BlockPos pos) { return out; } Thanks for all the help and hope that you can help me figure this out also!
February 21, 20178 yr You cannot use Thread.sleep, that will pause the client or server thread completely and stop the game from running for the duration of the sleep. If you want to delay an action by a certain amount of time, you need to schedule a block update or count ticks in a ticking TileEntity or tick event handler. Why is the client telling the server to run a command? The server should be in charge of the game state (e.g. running commands) and send any data necessary for display purposes to the appropriate clients. The client doesn't need to know the comparator output level, it can simply return 0 while the server returns the actual value. You can't store mutable data in fields of your Block class, it's a singleton shared between all occurrences of the block. Mutable data must be stored in the block state or TileEntity. Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
February 21, 20178 yr Author Okay I understand what you are saying, so set the comparator output on the server. How would I do this the closest method I can find to do this is ctx.getServerHandler().playerEntity.worldObj.updateComparatorOutputLevel(pos, blockIn); Which doesn't set the comparator output it just calls the getComparatorInputOverride method in my block that I overrided. I hope this makes sense.
February 22, 20178 yr Override Block#getComparatorInputOverride to return the comparator output level stored in your TileEntity. When this level changes, call TileEntity#markDirty to notify Minecraft that the TileEntity's data has changed (so the chunk containing it won't be skipped when saving the world) and update the output level of adjacent comparators. The client shouldn't be involved in this, it will simply return 0 (the default value of an int) from Block#getComparatorInputOverride if the TileEntity's output level isn't synced (which is fine, since the server's level will be the one used by the comparator). Please don't PM me to ask for help. Asking your question in a public thread preserves it for people who are having the same problem in the future.
February 23, 20178 yr Author Thanks you very much for all the help it works perfectly now. Edited February 23, 20178 yr by Radar6255
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.