Jump to content

solitone

Members
  • Posts

    18
  • Joined

  • Last visited

Everything posted by solitone

  1. I found a possible solution in this old thread. Here's what I've done: @Override public boolean removedByPlayer(IBlockState state, World world, BlockPos pos, EntityPlayer player, boolean willHarvest) { if (willHarvest) { // Delay deletion of the block until after getDrops return true; } if (!player.capabilities.isCreativeMode) { harvestBlock(world, player, pos, state, null, null); } return super.removedByPlayer(state, world, pos, player, willHarvest); } The computer block is dropped when I break it, unless I'm in creative mode. So it works as expected. Yet I'm not sure that it results in the exact same effect as the original code. And I don't fully understand what's the meaning of delay deletion of the block until after getDrops. Anyhow, I no longer get errors or exceptions when in multiplayer. Plus now, when I re-enter the game, I have the same player inventory that I had when I exited. So it looks alright. Any comment, suggestion, or correction would be highly appreciated. Thanks!
  2. I've tried and moved the block of code for dropping the computer block into method harvestBlock: @Override public void harvestBlock(World worldIn, EntityPlayer player, BlockPos pos, IBlockState state, @Nullable TileEntity te, @Nullable ItemStack stack) { // Make the block drop itself ItemStack itemTemp = new ItemStack(pythontool.computerblock.StartupCommon.computerBlock, 1); EntityItem item = new EntityItem(worldIn, pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5, itemTemp); // Give it a random drop speed float multiplier = 0.1f; float motionX = worldIn.rand.nextFloat() - 0.5f; float motionY = worldIn.rand.nextFloat() - 0.5f; float motionZ = worldIn.rand.nextFloat() - 0.5f; item.motionX = motionX * multiplier; item.motionY = motionY * multiplier; item.motionZ = motionZ * multiplier; // Spawn the item in the world worldIn.spawnEntityInWorld(item); super.harvestBlock(worldIn, player, pos, state, te, stack); } It doesn't work though, the computer block is not dropped. I tried breaking the block using a pickaxe as suggested by diesieben07 but it's not dropped anyway. What am I getting wrong? Perhaps I misunderstood what you meant.
  3. Hi, as I wrote in a previous post, I'm trying to fix the PythonTool-Mod so that it can run correctly also in a multiplayer game (currently it works well only in singleplayer). At the moment it is for 1.10.2, although perhaps one day I'll try to update it to a more recent version. Basically this mod allows the player to run a python programs, saved on the client machine. It depends on raspberryjammod to launch the .py program, via a '/python script.py' command. I have the following code in a ComputerBlock class. The idea is that when a player breaks a computer block, the block should drop, but only when playing in survival mode. When playing in creative mode, the computer block should not drop: public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { // If not in creative mode: survival, etc. break and drop the block itself if (!Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) { // Make the block drop itself // [...] // Give it a random drop speed // [...] // Spawn the item in the world // [...] // Super MUST be called last because it removes the tile entity super.breakBlock(worldIn, pos, state); } else { // If in creative mode, don't drop the block super.breakBlock(worldIn, pos, state); } } It is clear though that this method works only in singleplayer mode, but not in multiplayer, since there is no Minecraft class on the dedicated server. I've moved that code in the client proxy, and at least I don't get any server side exception any longer. However I miss the server side code that I should put in the server proxy. How can I test server side that the player that breaks the block is not in creative mode?
  4. This isn’t an issue but normal behaviour, is it?
  5. Some logging that should clear things up: public class ClientOnlyProxy extends CommonProxy { private static final Logger LOGGER = LogManager.getLogger(); // [...] @Override public void runPython(World world, EntityPlayer player, String scriptPath) { LOGGER.info("In runPython() (physical client)."); if (world.isRemote) { // client side LOGGER.info("World is remote - > logical client."); if (!Minecraft.getMinecraft().isSingleplayer()) { LOGGER.info("Multiplayer game: run py script from client."); // client talks to dedicated server (multiplayer game) ClientCommandHandler.instance.executeCommand(player, "/lpython " + scriptPath); } } else { // server side LOGGER.info("World is NOT remote -> logical server (integrated)."); LOGGER.info("Singleplayer game: run py script from server."); if (player.isSneaking()) { // shift pressed. Run new parallel script Minecraft.getMinecraft().thePlayer.getServer().getCommandManager().executeCommand(player, "/apy " + scriptPath); } else { // shift not pressed. Cancel previous scripts and run new script world.getMinecraftServer().getCommandManager().executeCommand(player, "/python " + scriptPath); } } } } Here's the output when playing a singleplayer game, showing that the runPython() method is called twice--once from the logical client and once from the logical (integrated) server: [17:17:05] [Client thread/INFO] [pythontool.ClientOnlyProxy]: In runPython() (physical client). [17:17:05] [Client thread/INFO] [pythontool.ClientOnlyProxy]: World is remote - > logical client. [17:17:05] [Server thread/INFO] [pythontool.ClientOnlyProxy]: In runPython() (physical client). [17:17:05] [Server thread/INFO] [pythontool.ClientOnlyProxy]: World is NOT remote -> logical server (integrated). [17:17:05] [Server thread/INFO] [pythontool.ClientOnlyProxy]: Singleplayer game: run py script from server. [17:17:05] [Server thread/INFO] [STDOUT]: [mobi.omegacentauri.raspberryjammod.ScriptExternalCommand:execute:275]: Running mcpipy/pythontool/donut.py BTW is there a way to show logging messages with level < INFO?
  6. As far as I understand, FML instantiates one of the two proxies based on the pyhisical side [1]. So ClientOnlyProxy (that I probably should rename ClientProxy) is instantiated in the physical client, which comprises both a logical client (where world.isRemote is true) and a logical server (i.e. the integrated server, where world.isRemote is false [2]). Am I missing something?
  7. @Override public ActionResult<ItemStack> onItemRightClick(ItemStack stack, World world, EntityPlayer player, EnumHand hand) { // [...] String separator = getSeparator(); String scriptName = nbtTagCompound.getString("scriptName"); String scriptPath = "pythontool" + separator + scriptName; proxy.runPython(world, player, scriptPath); // [...] } ^^^ This is how I refactored onItemRightClick(). The runPython() method does nothing on the dedicated server, while on the client: public class ClientOnlyProxy extends CommonProxy { // [...] @Override public void runPython(World world, EntityPlayer player, String scriptPath) { super.runPython(world, player, scriptPath); if (world.isRemote) { // client side if (!Minecraft.getMinecraft().isSingleplayer()) { // client talks to dedicated server (multiplayer game) ClientCommandHandler.instance.executeCommand(player, "/lpython " + scriptPath); } } else { // server side if (player.isSneaking()) { // shift pressed. Run new parallel script Minecraft.getMinecraft().thePlayer.getServer().getCommandManager().executeCommand(player, "/apy " + scriptPath); } else { // shift not pressed. Cancel previous scripts and run new script world.getMinecraftServer().getCommandManager().executeCommand(player, "/python " + scriptPath); } } } } I still need to figure out why they used two different approaches to execute commands on the integrated server--Minecraft.getMinecraft().thePlayer.getServer().getCommandManager().executeCommand() vs. world.getMinecraftServer().getCommandManager().executeCommand(). public abstract class CommonProxy { // [...] public void runPython(World world, EntityPlayer player, String scriptPath) {} } public class PythonTool { // [...] @SidedProxy(clientSide="pythontool.ClientOnlyProxy", serverSide="pythontool.DedicatedServerProxy") public static CommonProxy proxy; // [...] } Are still there significant mistakes? Thanks again!
  8. OK, thanks, that was helpful. As for @SidedProxyvs. DistExecutor, if I understand it right the former was used till version 1.12, while the latter with version 1.13+, right?
  9. So I would have ServerScriptItem and ClientScriptItem, both inheriting from ScriptItem, and I would register a ServerScriptItem object on the dedicated server and a ClientScriptItem object on the client?
  10. From what I see in the examples I've found, proxies are basically used for preInitialization, Inizialization, and postInizialization tasks. Here I've got an Item class, with method onItemRightClick() that should perform different things based on the game mode (multiplayer vs. singleplayer). How would I take advantage of the sided proxies to refactor the following class? Should I have two classes, one for the client, the other for the dedicated server, and register the first class on the client, and the second on the dedicated server? I'm confused and basically stuck. public class ScriptItem extends Item { // [...] @Override public ActionResult<ItemStack> onItemRightClick(ItemStack stack, World world, EntityPlayer player, EnumHand hand) { // [...] String separator = getSeparator(); if (world.isRemote) { // client side if (!Minecraft.getMinecraft().isSingleplayer()) { // client talks to dedicated server (multiplayer game) String scriptName = nbtTagCompound.getString("scriptName"); ClientCommandHandler.instance.executeCommand(player, "/lpython " + "pythontool" + separator + scriptName); } } else { // server side if (!FMLCommonHandler.instance().getMinecraftServerInstance().isDedicatedServer()) { // server is integrated (singleplayer game) String scriptName = nbtTagCompound.getString("scriptName"); world.getMinecraftServer().getCommandManager().executeCommand(player, "/python " + "pythontool" + separator + scriptName); } } }
  11. I suspected it was related to grade's runServer task. However, I also tested the mod on a Forge server (running in a separate host BTW), and I do not experience any crash. My code fragment doesn't cause any exception either. I only get an exception when I break a ComputerBlock--i.e. when the breakBlock is called, not when the class is loaded. Could it depend on java version? I am on java 8.
  12. This is the code fragment I wrote and that you said would crash the server: if (world.isRemote) { // client side if (!Minecraft.getMinecraft().isSingleplayer()) { // client talks to dedicated server (multiplayer game) String scriptName = nbtTagCompound.getString("scriptName"); ClientCommandHandler.instance.executeCommand(player, "/lpython " + scriptName); } } else { // server side if (!FMLCommonHandler.instance().getMinecraftServerInstance().isDedicatedServer()) { // server is integrated (singleplayer game) String scriptName = nbtTagCompound.getString("scriptName");  world.getMinecraftServer().getCommandManager().executeCommand(player,  "/python " + scriptName); } } The point you made is that, as soon as the JVM loads the class containing this code, the JVM checks all referenced classes are available. Since Minecraft class is not available on the dedicated server, an exception should be raised and the server should crash. What I test this code, however, I don't experience any exception. The behaviour I observe is different to the expected behaviour you described. It is as if the JVM looks for the referenced classes when they need to be executed--i.e. when world.isRemote is true, which cannot happen on a dedicated server. This hypothesis is confirmed by the following code, which is delivered with the original version of the mod (i.e. I didn't change anything in it): public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { // If not in creative mode: survival, etc. break and drop the block itself if (!Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) { // Make the block drop itself // [...] // Give it a random drop speed // [...] // Spawn the item in the world // [...] // Super MUST be called last because it removes the tile entity super.breakBlock(worldIn, pos, state); } else { // If in creative mode, don't drop the block super.breakBlock(worldIn, pos, state); } } This code does not cause an exception when the containing class is loaded, but only when the method is actually called-i.e. when I break a ComputerBlock (a block provided with this mod). When the method is called, I get an exception on the dedicated server: [06:33:32] [Server thread/FATAL] [net.minecraft.server.MinecraftServer]: Error executing task java.util.concurrent.ExecutionException: java.lang.NoClassDefFoundError: net/minecraft/client/Minecraft at java.util.concurrent.FutureTask.report(FutureTask.java:122) ~[?:1.8.0_232] at java.util.concurrent.FutureTask.get(FutureTask.java:192) ~[?:1.8.0_232] at net.minecraft.util.Util.runTask(Util.java:29) [Util.class:?] at net.minecraft.server.MinecraftServer.updateTimeLightAndEntities(MinecraftServer.java:743) [MinecraftServer.class:?] at net.minecraft.server.dedicated.DedicatedServer.updateTimeLightAndEntities(DedicatedServer.java:408) [DedicatedServer.class:?] at net.minecraft.server.MinecraftServer.tick(MinecraftServer.java:688) [MinecraftServer.class:?] at net.minecraft.server.MinecraftServer.run(MinecraftServer.java:537) [MinecraftServer.class:?] at java.lang.Thread.run(Thread.java:748) [?:1.8.0_232] Caused by: java.lang.NoClassDefFoundError: net/minecraft/client/Minecraft at pythontool.computerblock.ComputerBlock.breakBlock(ComputerBlock.java:326) ~[ComputerBlock.class:?] at net.minecraft.world.chunk.Chunk.setBlockState(Chunk.java:613) ~[Chunk.class:?] at net.minecraft.world.World.setBlockState(World.java:386) ~[World.class:?] at net.minecraft.block.Block.removedByPlayer(Block.java:1317) ~[Block.class:?] at net.minecraft.server.management.PlayerInteractionManager.removeBlock(PlayerInteractionManager.java:298) ~[PlayerInteractionManager.class:?] at net.minecraft.server.management.PlayerInteractionManager.removeBlock(PlayerInteractionManager.java:292) ~[PlayerInteractionManager.class:?] at net.minecraft.server.management.PlayerInteractionManager.tryHarvestBlock(PlayerInteractionManager.java:339) ~[PlayerInteractionManager.class:?] at net.minecraft.server.management.PlayerInteractionManager.onBlockClicked(PlayerInteractionManager.java:175) ~[PlayerInteractionManager.class:?] at net.minecraft.network.NetHandlerPlayServer.processPlayerDigging(NetHandlerPlayServer.java:658) ~[NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketPlayerDigging.processPacket(CPacketPlayerDigging.java:56) ~[CPacketPlayerDigging.class:?] at net.minecraft.network.play.client.CPacketPlayerDigging.processPacket(CPacketPlayerDigging.java:12) ~[CPacketPlayerDigging.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:21) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_232] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_232] at net.minecraft.util.Util.runTask(Util.java:28) ~[Util.class:?] ... 5 more Caused by: java.lang.ClassNotFoundException: net.minecraft.client.Minecraft at net.minecraft.launchwrapper.LaunchClassLoader.findClass(LaunchClassLoader.java:101) ~[launchwrapper-1.12.jar:?] at java.lang.ClassLoader.loadClass(ClassLoader.java:418) ~[?:1.8.0_232] at java.lang.ClassLoader.loadClass(ClassLoader.java:351) ~[?:1.8.0_232] at pythontool.computerblock.ComputerBlock.breakBlock(ComputerBlock.java:326) ~[ComputerBlock.class:?] at net.minecraft.world.chunk.Chunk.setBlockState(Chunk.java:613) ~[Chunk.class:?] at net.minecraft.world.World.setBlockState(World.java:386) ~[World.class:?] at net.minecraft.block.Block.removedByPlayer(Block.java:1317) ~[Block.class:?] at net.minecraft.server.management.PlayerInteractionManager.removeBlock(PlayerInteractionManager.java:298) ~[PlayerInteractionManager.class:?] at net.minecraft.server.management.PlayerInteractionManager.removeBlock(PlayerInteractionManager.java:292) ~[PlayerInteractionManager.class:?] at net.minecraft.server.management.PlayerInteractionManager.tryHarvestBlock(PlayerInteractionManager.java:339) ~[PlayerInteractionManager.class:?] at net.minecraft.server.management.PlayerInteractionManager.onBlockClicked(PlayerInteractionManager.java:175) ~[PlayerInteractionManager.class:?] at net.minecraft.network.NetHandlerPlayServer.processPlayerDigging(NetHandlerPlayServer.java:658) ~[NetHandlerPlayServer.class:?] at net.minecraft.network.play.client.CPacketPlayerDigging.processPacket(CPacketPlayerDigging.java:56) ~[CPacketPlayerDigging.class:?] at net.minecraft.network.play.client.CPacketPlayerDigging.processPacket(CPacketPlayerDigging.java:12) ~[CPacketPlayerDigging.class:?] at net.minecraft.network.PacketThreadUtil$1.run(PacketThreadUtil.java:21) ~[PacketThreadUtil$1.class:?] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_232] at java.util.concurrent.FutureTask.run(FutureTask.java:266) ~[?:1.8.0_232] at net.minecraft.util.Util.runTask(Util.java:28) ~[Util.class:?] ... 5 more The server doesn't crash though, and I can continue playing. To sum up, I'd like to understand why in my case I don't experience the expected behaviour.
  13. I’ve repeated the test again using a remote server running on a separate machine. The code fragment in my original post does not cause any exception. By contrast, the breakBlock method (which I didn’t change) does cause a ClassNotFoundException. Such a behaviour contrasts what I would expect, based on what you said. I have no clue about what could exmplain this difference, but clearly it’s not related to the deployment scenario (both client and server on the same development machine vs. client and server in separate machines).
  14. Ok, although I can’t crash the server. I don’t even get an exception with my code. And when I get an exception (when I break a computer block and the breakBlock method is executed) the server does not crash. I’m not objecting what you’re saying. I’m just confused. I’m trying to understand why I don’t crash the server. Is it because I’m testing it running both the server and the client through IntelliJ IDEA (i.e. via runServer and runClient Gradle tasks)? Still, I have also tried with client and server running on two different machines, and the breakBlock method does not crash the server, it just throw an uncaught exception. So perhaps does it depend on the java version? Thanks
  15. So doesn’t it cause the server to crash, in contrast to what Draco18s said?
  16. So what would be the correct solution (in 1.10.2)?I thought my code was bad, but not completely broken, since in fact I don't get any NoClassDefFoundError or ClassNotFoundException, and the server doesn't crash. By contrast, I notice that the following code (originally provided with the mod, in the ComputerBlock class) does cause both those exceptions (even though the server doesn't crash either): public void breakBlock(World worldIn, BlockPos pos, IBlockState state) { // If not in creative mode: survival, etc. break and drop the block itself if (!Minecraft.getMinecraft().thePlayer.capabilities.isCreativeMode) { // Make the block drop itself // [...] // Give it a random drop speed // [...] // Spawn the item in the world // [...] // Super MUST be called last because it removes the tile entity super.breakBlock(worldIn, pos, state); } else { // If in creative mode, don't drop the block super.breakBlock(worldIn, pos, state); } }
  17. I'm trying to fix the PythonTool-Mod so that it can run correctly also in a multiplayer game (currently it works well only in singleplayer). At the moment it is for 1.10.2, although perhaps one day I'll try to update it to a more recent version. Basically this mod allows the player to run a python programs, saved on the client machine. It depends on raspberryjammod to launch the .py program, via a '/python script.py' command. In singleplayer mode this works smoothly. However, in multiplayer it doesn't, since it can't locate the python files. Sure, I could copy the .py files on the server, but I think it would be much better if PythonTool-Mod took the .py file from the client machine. Raspberryjammod allows to do this via an alternative command--i.e. 'lpython script.py' ('l' stands for local). But to do thisI need to recognize a singleplayer game from a multiplayer game, so that I can run alternative raspberryjammod commands. I've tried something like the following, and apparently works. However it seems a bit contort. Is there a better way to accomplish the same result? if (world.isRemote) { // client side if (!Minecraft.getMinecraft().isSingleplayer()) { // client talks to dedicated server (multiplayer game) String scriptName = nbtTagCompound.getString("scriptName"); ClientCommandHandler.instance.executeCommand(player, "/lpython " + scriptName); } } else { // server side if (!FMLCommonHandler.instance().getMinecraftServerInstance().isDedicatedServer()) { // server is integrated (singleplayer game) String scriptName = nbtTagCompound.getString("scriptName"); world.getMinecraftServer().getCommandManager().executeCommand(player, "/python " + scriptName); } }
  18. Yes, it does work. BTW, I need to set this parameter only for Forge 1.10.2, while for 1.14.4 I can build and run using Gradle. I'm on IntellJ IDEA 2019.
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.