I'm having trouble getting a consistent reference to the worldserver instance. I have a packet that calls a method in a tileentity, that calls a method in it's block. The block method calls world.setblockmetadata... which fails to properly interact with my block because the block exists on a different worldserver.
when I toString() the world from the block itself, I get something like net.minecraft.world.WorldServer@14f5e86.
how can I get a reference to the same worldserver as my blocks from either the packet, tileentity or block with only a World and a EntityPlayer to play with?
I'm sorry if this is unclear, if I need to do a better job of explaining my issue, please let me know.
try adding a world.isRemote check, I'm pretty sure that returns true if it's the client instance of the world and false if it's the server instance of the world
I'm not having trouble detecting whether it's server or client...
My block overrides isProvidingStrongPower and isProvidingWeakPower. These methods take in a worldserver reference and use that to get and set the block metadata. The same thing goes for updateTick. Whther the block is providing power is sotred in the block metadata.
My block also has a custom method that can be called from it's tile to trigger the power source by setting it's meta data. This method takes a world, and coords to be able to get the blocks metadata, and can only be ran on the client thread
Now, I have a serverchatevent handler that manages my server chat messages. When one of several keywords are detected, it sends a custom packet to the client. This packet contains the keyword, and loops through the loaded telentities, and if they are an instance of my custom tile, it calls a method on the tilentity that in turn tells the block to start providing power.
This works fine in ssp, but it doesn't seem to want to work in smp. I've determined that the whole process still works as intended, all the way from the chat event on the server down through the pack, to the tile entities and into the blocks custom method. It just doesn't fire. What I've foud is that in SSP, the world beinig passed to the block from the packet is a World server that is referenced by:
This doesn't work in SMP as getIntegratedServer returns null. I need some other way to reference the current world server for a given player from the client thread while in SMP.
Hey, a quick update. More digging shows that I was using the wrong player.dimension (had to use EntityPlayerMP). Even here I got a null pointer exception. Turns out that MinecraftServer.getServer() returns null from the client thread.
I'm running out of ideas... Anyone have anything I could try?
FFS, I just got into Forge related stuff, and I have to say I find it extremely frustrating seeing legitimate questions everywhere with no real answers. It makes my life much harder trying to learn this crap.
For anyone else that comes across this thread the answer is:
If you have a server-side player, their World (Entity#world / Entity#getEntityWorld) is server-side as well; so it's already an instance of WorldServer. All you need to do is cast it.
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
if(!world.isRemote) // world.isRemote means it's the client and there is no WorldServer
{
WorldServer world = (WorldServer) world;
// etc...
}
Very good points both of you make. However, I guess the part that confuses me is that I am working with a custom Container object so it's loaded on both server and client side (client loads it behind a Gui), and I'm doing something on another thread and need to schedule something back on the main thread for thread safety b.s., and I the only thing I've found to be able to do so is use Minecraft.getMinecraft().addScheduledTask() or player.getWorldServer().addScheduledTask(). I can't use the Minecraft class because it will make the server side fail with the container loads with that import (because it doesnt exist server side), so I'm using the WorldServer method because even in single player the game is running a server instance. The method I posted earlier is backed by a sidedDelegate instance that can hold the data I need for either case safely. Or am I fundamentally missing some basic knowledge here?
Very good points both of you make. However, I guess the part that confuses me is that I am working with a custom Container object so it's loaded on both server and client side (client loads it behind a Gui), and I'm doing something on another thread and need to schedule something back on the main thread for thread safety b.s., and I the only thing I've found to be able to do so is use Minecraft.getMinecraft().addScheduledTask() or player.getWorldServer().addScheduledTask(). I can't use the Minecraft class because it will make the server side fail with the container loads with that import (because it doesnt exist server side), so I'm using the WorldServer method because even in single player the game is running a server instance. The method I posted earlier is backed by a sidedDelegate instance that can hold the data I need for either case safely. Or am I fundamentally missing some basic knowledge here?
A client-side Container shouldn't be directly interacting with the server (or scheduling a task to run on the server thread) as that would be reaching across logical sides.
On the physical client (i.e. in the client proxy), check which logical side the thread belongs to:
If it belongs to the logical client, schedule a task to run on the client thread using the Minecraft instance.
If it belongs to the logical server, schedule a task to run on the server thread using the MinecraftServer instance or a WorldServer instance (which delegates to the MinecraftServer instance anyway).
On the physical server (i.e. in the server proxy), check which logical side the thread belongs to:
If it belongs to the logical client, throw an exception as something has gone wrong (the physical server doesn't run the logical client).
If it belongs to the logical server, schedule a task to run on the server thread using the MinecraftServer instance or a WorldServer instance.
As explained in the documentation I linked, World#isRemote is the way to tell which logical side code is running on.
Are you sure you need a separate thread? Can you not run this code on the main client/server thread directly?
Rollback Post to RevisionRollBack
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
A client-side Container shouldn't be directly interacting with the server (or scheduling a task to run on the server thread) as that would be reaching across logical sides.
On the physical client (i.e. in the client proxy), check which logical side the thread belongs to:
If it belongs to the logical client, schedule a task to run on the client thread using the Minecraft instance.
If it belongs to the logical server, schedule a task to run on the server thread using the MinecraftServer instance or a WorldServer instance (which delegates to the MinecraftServer instance anyway).
On the physical server (i.e. in the server proxy), check which logical side the thread belongs to:
If it belongs to the logical client, throw an exception as something has gone wrong (the physical server doesn't run the logical client).
If it belongs to the logical server, schedule a task to run on the server thread using the MinecraftServer instance or a WorldServer instance.
As explained in the documentation I linked, World#isRemote is the way to tell which logical side code is running on.
Are you sure you need a separate thread? Can you not run this code on the main client/server thread directly?
Makes perfect sense. Thank you for that thorough explanation and links. I ended up using the @SideOnly annotation in the end. As for getting off the main thread, it is so I can sleep for 5 seconds between toggling a boolean field in the Container (the boolean is used in the Gui to draw an error)
I've been feeling the same way. I feel like it's way too hard to learn how to mod, even with a solid background in coding. I wish there was just a website for people who are beginning where they can learn everything they need starting from the super basics.
I'm having trouble getting a consistent reference to the worldserver instance. I have a packet that calls a method in a tileentity, that calls a method in it's block. The block method calls world.setblockmetadata... which fails to properly interact with my block because the block exists on a different worldserver.
when I toString() the world from the block itself, I get something like net.minecraft.world.WorldServer@14f5e86.
how can I get a reference to the same worldserver as my blocks from either the packet, tileentity or block with only a World and a EntityPlayer to play with?
I'm sorry if this is unclear, if I need to do a better job of explaining my issue, please let me know.
- SCott
I'm not having trouble detecting whether it's server or client...
My block overrides isProvidingStrongPower and isProvidingWeakPower. These methods take in a worldserver reference and use that to get and set the block metadata. The same thing goes for updateTick. Whther the block is providing power is sotred in the block metadata.
My block also has a custom method that can be called from it's tile to trigger the power source by setting it's meta data. This method takes a world, and coords to be able to get the blocks metadata, and can only be ran on the client thread
Now, I have a serverchatevent handler that manages my server chat messages. When one of several keywords are detected, it sends a custom packet to the client. This packet contains the keyword, and loops through the loaded telentities, and if they are an instance of my custom tile, it calls a method on the tilentity that in turn tells the block to start providing power.
This works fine in ssp, but it doesn't seem to want to work in smp. I've determined that the whole process still works as intended, all the way from the chat event on the server down through the pack, to the tile entities and into the blocks custom method. It just doesn't fire. What I've foud is that in SSP, the world beinig passed to the block from the packet is a World server that is referenced by:
Minecraft.getMinecraft().getIntegratedServer().worldServerForDimension(Minecraft.getMinecraft().thePlayer.dimension)
This doesn't work in SMP as getIntegratedServer returns null. I need some other way to reference the current world server for a given player from the client thread while in SMP.
Any ideas on how to go about this?
Thanks for your post. I had already tried that, but I tought it was wrong because it causes an error:
I've tried googling it, but it doesn't seem to be a common problem.
I'm running out of ideas... Anyone have anything I could try?
FFS, I just got into Forge related stuff, and I have to say I find it extremely frustrating seeing legitimate questions everywhere with no real answers. It makes my life much harder trying to learn this crap.
For anyone else that comes across this thread the answer is:
WorldServer worldServer = FMLCommonHandler.instance().getMinecraftServerInstance().getWorld(entityPlayerMP.dimension);
If you have a server-side player, their World (Entity#world / Entity#getEntityWorld) is server-side as well; so it's already an instance of WorldServer. All you need to do is cast it.
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Hello!
Very good points both of you make. However, I guess the part that confuses me is that I am working with a custom Container object so it's loaded on both server and client side (client loads it behind a Gui), and I'm doing something on another thread and need to schedule something back on the main thread for thread safety b.s., and I the only thing I've found to be able to do so is use Minecraft.getMinecraft().addScheduledTask() or player.getWorldServer().addScheduledTask(). I can't use the Minecraft class because it will make the server side fail with the container loads with that import (because it doesnt exist server side), so I'm using the WorldServer method because even in single player the game is running a server instance. The method I posted earlier is backed by a sidedDelegate instance that can hold the data I need for either case safely. Or am I fundamentally missing some basic knowledge here?
A client-side Container shouldn't be directly interacting with the server (or scheduling a task to run on the server thread) as that would be reaching across logical sides.
You need to handle this through the sided proxy system:
As explained in the documentation I linked, World#isRemote is the way to tell which logical side code is running on.
Are you sure you need a separate thread? Can you not run this code on the main client/server thread directly?
Chisel Facades: For all your decorative pipe-hiding needs.
Please don't PM me to ask for help or to join your mod development team. Asking your question in a public thread preserves it for people who are having the same problem in the future. I'm not interested in developing mods with people.
Makes perfect sense. Thank you for that thorough explanation and links. I ended up using the @SideOnly annotation in the end. As for getting off the main thread, it is so I can sleep for 5 seconds between toggling a boolean field in the Container (the boolean is used in the Gui to draw an error)
I've been feeling the same way. I feel like it's way too hard to learn how to mod, even with a solid background in coding. I wish there was just a website for people who are beginning where they can learn everything they need starting from the super basics.