Jump to content

PopulateChunkEvent.Post Never Fires Every Chunk In Nether


Recommended Posts

Posted (edited)

Doesn't print in ever chunk not even if the tile entity map is null. Is this the case with the overworld as well What event should I be using? I need it after everything occurs every chunk

 

@SubscribeEvent
public void dungeonDetectNether(PopulateChunkEvent.Post e)
{
	World w = e.getWorld();
	if(w.isRemote || !w.provider.isNether())
		return;
	Chunk chunk = w.getChunkFromChunkCoords(e.getChunkX(), e.getChunkZ() );
	Map<BlockPos, TileEntity> map = chunk.getTileEntityMap();
	IChunkGenerator gen = e.getGenerator();
  	if(map == null)
		System.out.println(e.getChunkX() + ", " + e.getChunkZ());
	Iterator<Map.Entry<BlockPos, TileEntity>> it = map.entrySet().iterator();
	while(it.hasNext() )
	{
		Map.Entry<BlockPos, TileEntity> pair = it.next();
		BlockPos pos = pair.getKey();
		TileEntity tile = pair.getValue();
		if(tile instanceof TileEntityMobSpawner)
        {
			System.out.println("Spawner:" + pos);
			EventDungeon d = new EventDungeon.Post(tile,pos, Type.NETHERFORTRESS);
			MinecraftForge.EVENT_BUS.post(d);
        }
	}
}

 

Console:
 

[02:42:33] [Server thread/INFO]: Player622 has made the advancement [We Need to Go Deeper]
[02:42:33] [main/INFO]: [CHAT] Player622 has made the advancement [We Need to Go Deeper]
[02:42:33] [Server thread/WARN]: Can't keep up! Did the system time change, or is the server overloaded? Running 11636ms behind, skipping 232 tick(s)
[02:42:34] [main/INFO]: Loaded 17 advancements
[02:42:46] [Server thread/INFO]: [Player622: Teleported Player622 to -141.5, 70.0, 41.5]
[02:42:46] [main/INFO]: [CHAT] Teleported Player622 to -141.5, 70.0, 41.5
[02:42:50] [Server thread/INFO]: Player622 has made the advancement [A Terrible Fortress]
[02:42:50] [main/INFO]: [CHAT] Player622 has made the advancement [A Terrible Fortress]
[02:42:50] [main/INFO]: Loaded 19 advancements


Steps to reproduce

create world seed: "2"

go to nether
/tp -142 70 41

observer no printlines from code yet then fly for about 30 chunks around then it will call populate post event

 

Issue caused by this:

because it's not firing when it needs to the blaze room in the nether fortress isn't wither skeleton if it was firing every chunk it would become a wither skeleton

Edited by jredfox
Posted (edited)
33 minutes ago, diesieben07 said:

Cannot reproduce this. Followed your steps and the event fired before and after the teleport.

Don't know how went to nether after firing the event teleported nothing no printlines I will post video. I said it doesn't fire every chunk never said it never fired

Edited by jredfox
Posted (edited)
8 minutes ago, diesieben07 said:

If you want me to actually test your code and not just verify that the event works in general, post a working Git repo. I don't care about a video.

Ok tell me why everything isn't wither skeletons in the new event the top one I hard coded regardless if tile entity is mob spanwer fire event with type fortress meaning it will set to wither skele and it's not printing there or anywhere for me. Both the hard coded test and printlines have failed It's not firing for me I registered both on terrain bus and regular

I am on the forge recommended build should I be higher?

https://github.com/jredfox/dungeontweeks

Edited by jredfox
Posted
2 minutes ago, diesieben07 said:

Your repository is missing the build.gradle so I cannot run your code.

why do you need build.gradle that's simply going to have to be re-run anyways once you setup it to your path

Posted (edited)
14 minutes ago, loordgek said:

you need it to setup the dev environment

Edit: ok misread this 

18 minutes ago, diesieben07 said:

Your repository is missing the build.gradle so I cannot run your code.

can't upload full files past 100 but, did give you the build.gradle

 

Edit: look at bottom comment

Edited by jredfox
Posted (edited)
5 minutes ago, diesieben07 said:

So that I can just clone your repository and it works. Instead of me having to fiddle around with 20 files and downloads.

 

Your issue is that structures can reach across chunks when generating (terrible, but that's how it is). The spawner your teleport command goes to is in chunk -9/2, but the structure it is part of is generated in chunk -10/2. You have to check neighboring chunks in your populate event handler, too, to catch all spawners. How many? I don't know.

Sounds cool but, I thought this populate chunk event was suppose to be firing ever chunk load what event fires every chunk load after everything has been populated? Or I need a method boolean to detect if a chunk hasn't existed before but, never fired upon

 

Note: it has to be a chunk event only when generating new chunks

 

because, if I scan a radius then I might override existing spawners and it's no guarantee  that it will always only be one chunk away

Edited by jredfox
Posted
2 hours ago, diesieben07 said:

It does. But the spawner in chunk -9/2 is not generated as part of chunk -9/2's population. It is generated as part of chunk -10/2's generation (because structure generation spans multiple chunks).

Here is what happens:

  1. Chunk -9/2 is populated, no structure.
  2. Post populate event for -9/2 fires, you scan -9/2 for spawners and don't find any (because there are no structures).
  3. Chunk -10/2 is populated and a nether fortress decides to spawn, including a blaze spawner. This blaze spawner happens to be in chunk -9/2.
  4. Post populate event for -10/2 fires, you scan -10/2 for spawners and don't find any (because the spawner is in -9/2).

I know. It sucks. But that is how structure generation is implemented in Minecraft.

So how do I have a boolean of whether or not I modified the spawner? A hashmap of <points(xzchunk),tileentity> and then lets say I scan chunks that have already been loaded how do I know whether or not that chunk has already been written to the disk and re-loaded or something I could be overwriting spawners that have already existed with other entities?

Does this happen in any of the other structures again what is a proper solution that involves checks for this? So confused don't want to replace every structure that just happens to be out of a chunk for initial spawn

Posted

Honestly, the best way in terms of performance and in terms of logical simplicity and correctness is to replace the structure generators with your own. It really isn't that hard, as you really just copy or extend the existing ones and replace the one line of code for the spawner. Many of the vanilla structure generators have public fields you can assign directly, and dungeons have the event where you can intercept and replace it. I know it sounds heavy-handed but I'm not sure that it is that bad.

 

Secondly, if you continue with your scanning approach you seem really worried about remembering what has been changed and such. It isn't that hard to add a collection (list of spawners) that you have modified and add that to the world save data.

 

Thirdly, another possibility is to predict where the structures will add the parts that go into the next chunks. Basically you would create a copy of the structure generator that takes the same seed and instead of actually generating the structure (remove that part)  just note which additional chunks are affected and scan those.

 

Lastly, while it would take a bit longer you can simply make a PR to add the hooks you need in Forge. For example, I think the current DungeonHooks implementation sort of sucks because it doesn't allow outright replacement of the spawner. So why don't you make a PR for a PlaceSpawnerEvent that gets information on location and which generator type produced it. If you're lucky (and for a simple and useful PR it is quite possible) it will take about a month to get your PR accepted and then you can return to this aspect of your mod.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted

I just thought of another thing. It may be possible to generate the dungeon twice. I think with the same seed it should generate the same way. So why not just have your dungeon generator also run after the vanilla stuff? Of course your version doesn't have to place all the blocks, but should be able to find where the spawner would be. Even if it wasn't perfect due to randomness beyond the seed value, I think it could greatly narrow down the scanning you need to do as you'd know specific area that spawner should/could be.

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted (edited)
8 minutes ago, jabelar said:

I just thought of another thing. It may be possible to generate the dungeon twice. I think with the same seed it should generate the same way. So why not just have your dungeon generator also run after the vanilla stuff? Of course your version doesn't have to place all the blocks, but should be able to find where the spawner would be. Even if it wasn't perfect due to randomness beyond the seed value, I think it could greatly narrow down the scanning you need to do as you'd know specific area that spawner should/could be.

Well I thought of adding a hashmap of spawners and positions the issue with that is exit the world go back hash map is cleared get's overriden all over again on chunk populate for loading a new chunk right next to that. I would need booleans if the chunk is on the disk and if it's already scanned. I could simply hard code pig in for everything but, that might run stuff. I would have to write a list of spawners to the disk and that would get really big real fast and laggy if you go exploring for 3000 chunks. The solution has to be in memory only

 

I could try adding a tag to the tile entity under the entity part but, that's kind of cheating. {SpawnData:{isScanned:true} } so I don't like that idea because, in the future I plan on supporting other tile entities once silk spanwer and the core get a major update or two

 

replacing the structures I am trying not to do this if there is any other way


predicting where the chunks are going to layed out sounds like to much math for something that fires for every new chunk I would rather replace the structures.

I replaced the dungeon because there was no hook properly into this and I also wanted to alter the floor based on what type of entity it is.

My dungeon detector for mob spawners runs in post after everything else the issue is structure placed spawner into a chunk that was already scanned.

Edited by jredfox
Posted

 I don't think it could generate the same dungeon twice always because the random variable .getnexRandom() wouldn't be the same it would have to get modified the same ways before I could call it for my structure replacing the structure would be better idea as it would do the same thing non laggy I am more or less liking scanning chunks via radius ever chunk load

Posted (edited)
4 hours ago, diesieben07 said:

It does. But the spawner in chunk -9/2 is not generated as part of chunk -9/2's population. It is generated as part of chunk -10/2's generation (because structure generation spans multiple chunks).

Here is what happens:

  1. Chunk -9/2 is populated, no structure.
  2. Post populate event for -9/2 fires, you scan -9/2 for spawners and don't find any (because there are no structures).
  3. Chunk -10/2 is populated and a nether fortress decides to spawn, including a blaze spawner. This blaze spawner happens to be in chunk -9/2.
  4. Post populate event for -10/2 fires, you scan -10/2 for spawners and don't find any (because the spawner is in -9/2).

I know. It sucks. But that is how structure generation is implemented in Minecraft.

Well and array list of scanned poses would work but, I need a second check a check for if player exits game goes back how do they know if it's been checked or not because, new scan radius of one then the chunk that had already been there on the edge just got overriden because, the chunk next to it has a spawner in say a mineshaft and previous was dungon.

So what would I check for if the chunk is on the disk? But, you said it already was a loaded chunk that got modified? what would be a good solution can the dynamic and just hard code replace vanilla? Then how am I suppose to support mods same manual replacing of structures?

Edited by jredfox
Posted (edited)

Ok I think I know how I am going to do things now there is no current way without bugs to create such dynamic support without a forge update forcing people with tile entities to have tag called scanned boolean true/false 0 1 on the disk.


Edit:

I could asm the tile entity class to have such a variable for read and write would this be a better solution "dungeontweeksScanned:0" either way it will have a detection system for mods.

Edit Edit: I need to use detection nbt for has detected true/false write and readfromNBT() for mod support I will be updating the core mod for asm utils to implement this because if mod user defines squirrel spawner as nbt and in their list has squirrel for chance to be default then it will get overridden via the next chunk has tile entity so yeah going to need that scanning boolean. My other options are writing and loading every single pos and never deleting them which is a terrible idea of doing it

 

So I am going to replace vanilla worldgen but, in order to remain dynamic my thing is going to scan on the event for x entity id if entity id is minecraft:blank_dugenonName or any other defined dungeon override it by scanning radius of 1 that way stuff like battle towers could add support for my mod by simply if my mod exists set entity id basically to blank_battletowers and then client defines name as dungoen then it's compatible. That's how I am going to add support for stuff. doing what choonster originally said just a bit more advanced. Yes vanilla world gen and any world gen that adds comparability would have to add the blank thing to be fully supported. Of course name defiinitions would only work per dimension thus making further compatibility.

Edited by jredfox
Posted (edited)
3 hours ago, diesieben07 said:

You do not need ASM to store additional data on tile entities. Either you can add a capability to every tile entity you need using AttachCapabilityEvent or you can use TileEntity::getTileData, which is an NBTTagCompound which you can store custom data into (prefix with your mod ID).

ok is this also in 1.7 since I backport all mods once done in newest to 1.7 eventually till I revert the combat system

 

Ok I did the chunk radius thing but, the issue described on the chunk radius form is manually loading chunks during a forge event that's loading chunks what method should I be using to get the chunks that haven't been populated yet? So yeah no blaze issue but, the issue now is it's recursively calling load chunk help?

 

Seriously one thing after the other hopefully this is the last fix for a fix then I can actually verify overrides and start coding in the config system

Edited by jredfox
Posted
1 hour ago, jredfox said:

ok is this also in 1.7

1.7.10 is no longer supported here

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted (edited)

Hey @jredfox, I know you've been working hard with all this scanning stuff, but I was able to get it all working with only 20 lines of new code and about five minutes.  All I had to do was:

 

1) Copied the WorldGenDungeons code into a new class and changed the line for the spawner to make a wither spawner and to add a simple boolean tag to the spawner. See example code: https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/worldgen/WorldGenDungeonsModded.java

 

2) Handle the Populate event and check for dungeon type, then copied the code from the overworld chunk generator's populate() method that calls my dungeon generator. I also set result of the event to Result.DENY to prevent the vanilla dungeon. See example code: https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/TerrainGenEventHandler.java 

 

I could then access the world.getLoadedTileEntities at any time and filter for those with my tag to see what spawners I had modded. To test this I also handled the EntityJoinedWorldEvent, checked for the player, and then printed to console all the tile entities that had my tag.  https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/EventHandler.java#L1096 

 

Here is what the console printed out when I created the new world:

[23:42:40] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=22, y=58, z=384}
[23:42:40] [Server thread/INFO]: Preparing spawn area: 15%
[23:42:40] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=45, y=26, z=150}
[23:42:41] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=61, y=26, z=70}
[23:42:41] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=61, y=26, z=150}
[23:42:41] [Server thread/INFO]: Preparing spawn area: 28%
[23:42:42] [Server thread/INFO]: Preparing spawn area: 41%
[23:42:43] [Server thread/INFO]: Preparing spawn area: 56%
[23:42:44] [Server thread/INFO]: Preparing spawn area: 73%
[23:42:45] [Server thread/INFO]: Preparing spawn area: 89%
[23:42:46] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.MainMod:serverStarting:175]: Server starting
[23:42:46] [Server thread/INFO]: Changing view distance to 12, from 10
[23:42:46] [Netty Local Client IO #1/INFO] [FML]: Server protocol version 2
[23:42:46] [Netty Server IO #3/INFO] [FML]: Client protocol version 2
[23:42:46] [Netty Server IO #3/INFO] [FML]: Client attempting to join with 5 mods : [email protected],[email protected],[email protected],[email protected],[email protected]
[23:42:46] [Netty Local Client IO #1/INFO] [FML]: [Netty Local Client IO #1] Client side modded connection established
[23:42:47] [Server thread/INFO] [FML]: [Server thread] Server side modded connection established
[23:42:47] [Server thread/INFO]: Player738[local:E:0277a632] logged in with entity id 6503 at (177.5, 75.0, 246.5)
[23:42:47] [Server thread/INFO]: Player738 joined the game
[23:42:47] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.EventHandler:onEvent:1104]: World has modded dungeon spawners [net.minecraft.tileentity.TileEntityMobSpawner@53d837e5, net.minecraft.tileentity.TileEntityMobSpawner@46e1b33f, net.minecraft.tileentity.TileEntityMobSpawner@5a946ae9, net.minecraft.tileentity.TileEntityMobSpawner@78f0523e]

 

You can see that it modded four spawners and that when I joined the world the server could find all four modded tile entities. In game I teleported to the spawner locations and confirmed they were spawning withers.

 

Then I quit and saved and then loaded the same world and the console showed:

[23:42:59] [Server thread/INFO]: Saving and pausing game...
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/overworld
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_nether
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_end
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/cloud
[23:43:59] [Server thread/INFO]: Stopping server
[23:43:59] [Server thread/INFO]: Saving players
[23:43:59] [Server thread/INFO]: Player738 lost connection: Disconnected
[23:43:59] [Server thread/INFO]: Player738 left the game
[23:43:59] [Server thread/INFO]: Stopping singleplayer server as player logged out
[23:43:59] [Server thread/INFO]: Saving worlds
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/overworld
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_nether
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_end
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/cloud
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension 0
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension -1
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension 1
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension 2
[23:43:59] [Server thread/INFO] [FML]: Applying holder lookups
[23:43:59] [Server thread/INFO] [FML]: Holder lookups applied
[23:44:06] [Server thread/INFO]: Starting integrated minecraft server version 1.12.2
[23:44:06] [Server thread/INFO]: Generating keypair
[23:44:06] [Server thread/INFO] [FML]: Injecting existing registry data into this server instance
[23:44:06] [Server thread/INFO] [FML]: Applying holder lookups
[23:44:06] [Server thread/INFO] [FML]: Holder lookups applied
[23:44:06] [Server thread/INFO] [FML]: Loading dimension 0 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO]: Loaded 488 advancements
[23:44:06] [Server thread/INFO] [FML]: Loading dimension 2 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO] [FML]: Loading dimension 1 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO] [FML]: Loading dimension -1 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO]: Preparing start region for level 0
[23:44:07] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.MainMod:serverStarting:175]: Server starting
[23:44:07] [Server thread/INFO]: Changing view distance to 12, from 10
[23:44:07] [Netty Local Client IO #2/INFO] [FML]: Server protocol version 2
[23:44:07] [Netty Server IO #5/INFO] [FML]: Client protocol version 2
[23:44:07] [Netty Server IO #5/INFO] [FML]: Client attempting to join with 5 mods : [email protected],[email protected],[email protected],[email protected],[email protected]
[23:44:07] [Netty Local Client IO #2/INFO] [FML]: [Netty Local Client IO #2] Client side modded connection established
[23:44:07] [Server thread/INFO] [FML]: [Server thread] Server side modded connection established
[23:44:07] [Server thread/INFO]: Player738[local:E:d39a95e0] logged in with entity id 11287 at (177.5, 75.0, 246.5)
[23:44:07] [Server thread/INFO]: Player738 joined the game
[23:44:07] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.EventHandler:onEvent:1104]: World has modded dungeon spawners [net.minecraft.tileentity.TileEntityMobSpawner@4011b568, net.minecraft.tileentity.TileEntityMobSpawner@453cb458, net.minecraft.tileentity.TileEntityMobSpawner@2ce4226f, net.minecraft.tileentity.TileEntityMobSpawner@56ec5e53]

 

You can see that when I loaded the world it remembered that there were four modded spawners.

 

It is really that simple. It has no perf impact at all and it will perfectly only modify spawners in the dungeon and will perfectly remember all the ones you've modified.

Edited by jabelar

Check out my tutorials here: http://jabelarminecraft.blogspot.com/

Posted
4 hours ago, jabelar said:

Hey @jredfox, I know you've been working hard with all this scanning stuff, but I was able to get it all working with only 20 lines of new code and about five minutes.  All I had to do was:

 

1) Copied the WorldGenDungeons code into a new class and changed the line for the spawner to make a wither spawner and to add a simple boolean tag to the spawner. See example code: https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/worldgen/WorldGenDungeonsModded.java

 

2) Handle the Populate event and check for dungeon type, then copied the code from the overworld chunk generator's populate() method that calls my dungeon generator. I also set result of the event to Result.DENY to prevent the vanilla dungeon. See example code: https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/TerrainGenEventHandler.java 

 

I could then access the world.getLoadedTileEntities at any time and filter for those with my tag to see what spawners I had modded. To test this I also handled the EntityJoinedWorldEvent, checked for the player, and then printed to console all the tile entities that had my tag.  https://github.com/jabelar/ExampleMod-1.12/blob/master/src/main/java/com/blogspot/jabelarminecraft/examplemod/EventHandler.java#L1096 

 

Here is what the console printed out when I created the new world:


[23:42:40] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=22, y=58, z=384}
[23:42:40] [Server thread/INFO]: Preparing spawn area: 15%
[23:42:40] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=45, y=26, z=150}
[23:42:41] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=61, y=26, z=70}
[23:42:41] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.worldgen.WorldGenDungeonsModded:generate:144]: Replacing dungeon mob spawner at BlockPos{x=61, y=26, z=150}
[23:42:41] [Server thread/INFO]: Preparing spawn area: 28%
[23:42:42] [Server thread/INFO]: Preparing spawn area: 41%
[23:42:43] [Server thread/INFO]: Preparing spawn area: 56%
[23:42:44] [Server thread/INFO]: Preparing spawn area: 73%
[23:42:45] [Server thread/INFO]: Preparing spawn area: 89%
[23:42:46] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.MainMod:serverStarting:175]: Server starting
[23:42:46] [Server thread/INFO]: Changing view distance to 12, from 10
[23:42:46] [Netty Local Client IO #1/INFO] [FML]: Server protocol version 2
[23:42:46] [Netty Server IO #3/INFO] [FML]: Client protocol version 2
[23:42:46] [Netty Server IO #3/INFO] [FML]: Client attempting to join with 5 mods : [email protected],[email protected],[email protected],[email protected],[email protected]
[23:42:46] [Netty Local Client IO #1/INFO] [FML]: [Netty Local Client IO #1] Client side modded connection established
[23:42:47] [Server thread/INFO] [FML]: [Server thread] Server side modded connection established
[23:42:47] [Server thread/INFO]: Player738[local:E:0277a632] logged in with entity id 6503 at (177.5, 75.0, 246.5)
[23:42:47] [Server thread/INFO]: Player738 joined the game
[23:42:47] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.EventHandler:onEvent:1104]: World has modded dungeon spawners [net.minecraft.tileentity.TileEntityMobSpawner@53d837e5, net.minecraft.tileentity.TileEntityMobSpawner@46e1b33f, net.minecraft.tileentity.TileEntityMobSpawner@5a946ae9, net.minecraft.tileentity.TileEntityMobSpawner@78f0523e]

 

You can see that it modded four spawners and that when I joined the world the server could find all four modded tile entities. In game I teleported to the spawner locations and confirmed they were spawning withers.

 

Then I quit and saved and then loaded the same world and the console showed:


[23:42:59] [Server thread/INFO]: Saving and pausing game...
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/overworld
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_nether
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_end
[23:42:59] [Server thread/INFO]: Saving chunks for level 'New World'/cloud
[23:43:59] [Server thread/INFO]: Stopping server
[23:43:59] [Server thread/INFO]: Saving players
[23:43:59] [Server thread/INFO]: Player738 lost connection: Disconnected
[23:43:59] [Server thread/INFO]: Player738 left the game
[23:43:59] [Server thread/INFO]: Stopping singleplayer server as player logged out
[23:43:59] [Server thread/INFO]: Saving worlds
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/overworld
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_nether
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/the_end
[23:43:59] [Server thread/INFO]: Saving chunks for level 'New World'/cloud
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension 0
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension -1
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension 1
[23:43:59] [Server thread/INFO] [FML]: Unloading dimension 2
[23:43:59] [Server thread/INFO] [FML]: Applying holder lookups
[23:43:59] [Server thread/INFO] [FML]: Holder lookups applied
[23:44:06] [Server thread/INFO]: Starting integrated minecraft server version 1.12.2
[23:44:06] [Server thread/INFO]: Generating keypair
[23:44:06] [Server thread/INFO] [FML]: Injecting existing registry data into this server instance
[23:44:06] [Server thread/INFO] [FML]: Applying holder lookups
[23:44:06] [Server thread/INFO] [FML]: Holder lookups applied
[23:44:06] [Server thread/INFO] [FML]: Loading dimension 0 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO]: Loaded 488 advancements
[23:44:06] [Server thread/INFO] [FML]: Loading dimension 2 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO] [FML]: Loading dimension 1 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO] [FML]: Loading dimension -1 (New World) (net.minecraft.server.integrated.IntegratedServer@73338cd5)
[23:44:06] [Server thread/INFO]: Preparing start region for level 0
[23:44:07] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.MainMod:serverStarting:175]: Server starting
[23:44:07] [Server thread/INFO]: Changing view distance to 12, from 10
[23:44:07] [Netty Local Client IO #2/INFO] [FML]: Server protocol version 2
[23:44:07] [Netty Server IO #5/INFO] [FML]: Client protocol version 2
[23:44:07] [Netty Server IO #5/INFO] [FML]: Client attempting to join with 5 mods : [email protected],[email protected],[email protected],[email protected],[email protected]
[23:44:07] [Netty Local Client IO #2/INFO] [FML]: [Netty Local Client IO #2] Client side modded connection established
[23:44:07] [Server thread/INFO] [FML]: [Server thread] Server side modded connection established
[23:44:07] [Server thread/INFO]: Player738[local:E:d39a95e0] logged in with entity id 11287 at (177.5, 75.0, 246.5)
[23:44:07] [Server thread/INFO]: Player738 joined the game
[23:44:07] [Server thread/INFO] [STDOUT]: [com.blogspot.jabelarminecraft.examplemod.EventHandler:onEvent:1104]: World has modded dungeon spawners [net.minecraft.tileentity.TileEntityMobSpawner@4011b568, net.minecraft.tileentity.TileEntityMobSpawner@453cb458, net.minecraft.tileentity.TileEntityMobSpawner@2ce4226f, net.minecraft.tileentity.TileEntityMobSpawner@56ec5e53]

 

You can see that when I loaded the world it remembered that there were four modded spawners.

 

It is really that simple. It has no perf impact at all and it will perfectly only modify spawners in the dungeon and will perfectly remember all the ones you've modified.

Thanks for your work but, I had already replaced the vanilla dungeon I am working on supporting modded dungeons which in my definition is any dungeon that isn't the dungeon including the nether fortress. The scanning chunks I am still working on because, I want it working with essence of the gods AoA battle towers etc...

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.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



  • Recently Browsing

    • No registered users viewing this page.
  • Posts

    • Version 1.19 - Forge 41.0.63 I want to create a wolf entity that I can ride, so far it seems to be working, but the problem is that when I get on the wolf, I can’t control it. I then discovered that the issue is that the server doesn’t detect that I’m riding the wolf, so I’m struggling with synchronization. However, it seems to not be working properly. As I understand it, the server receives the packet but doesn’t register it correctly. I’m a bit new to Java, and I’ll try to provide all the relevant code and prints *The comments and prints are translated by chatgpt since they were originally in Spanish* Thank you very much in advance No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. No player is mounted, or the passenger is not a player. MountableWolfEntity package com.vals.valscraft.entity; import com.vals.valscraft.network.MountSyncPacket; import com.vals.valscraft.network.NetworkHandler; import net.minecraft.client.Minecraft; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.Mob; import net.minecraft.world.entity.ai.attributes.AttributeSupplier; import net.minecraft.world.entity.ai.attributes.Attributes; import net.minecraft.world.entity.animal.Wolf; import net.minecraft.world.entity.player.Player; import net.minecraft.world.entity.Entity; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Items; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraftforge.event.TickEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; import net.minecraftforge.network.PacketDistributor; public class MountableWolfEntity extends Wolf { private boolean hasSaddle; private static final EntityDataAccessor<Byte> DATA_ID_FLAGS = SynchedEntityData.defineId(MountableWolfEntity.class, EntityDataSerializers.BYTE); public MountableWolfEntity(EntityType<? extends Wolf> type, Level level) { super(type, level); this.hasSaddle = false; } @Override protected void defineSynchedData() { super.defineSynchedData(); this.entityData.define(DATA_ID_FLAGS, (byte)0); } public static AttributeSupplier.Builder createAttributes() { return Wolf.createAttributes() .add(Attributes.MAX_HEALTH, 20.0) .add(Attributes.MOVEMENT_SPEED, 0.3); } @Override public InteractionResult mobInteract(Player player, InteractionHand hand) { ItemStack itemstack = player.getItemInHand(hand); if (itemstack.getItem() == Items.SADDLE && !this.hasSaddle()) { if (!player.isCreative()) { itemstack.shrink(1); } this.setSaddle(true); return InteractionResult.SUCCESS; } else if (!level.isClientSide && this.hasSaddle()) { player.startRiding(this); MountSyncPacket packet = new MountSyncPacket(true); // 'true' means the player is mounted NetworkHandler.CHANNEL.sendToServer(packet); // Ensure the server handles the packet return InteractionResult.SUCCESS; } return InteractionResult.PASS; } @Override public void travel(Vec3 travelVector) { if (this.isVehicle() && this.getControllingPassenger() instanceof Player) { System.out.println("The wolf has a passenger."); System.out.println("The passenger is a player."); Player player = (Player) this.getControllingPassenger(); // Ensure the player is the controller this.setYRot(player.getYRot()); this.yRotO = this.getYRot(); this.setXRot(player.getXRot() * 0.5F); this.setRot(this.getYRot(), this.getXRot()); this.yBodyRot = this.getYRot(); this.yHeadRot = this.yBodyRot; float forward = player.zza; float strafe = player.xxa; if (forward <= 0.0F) { forward *= 0.25F; } this.flyingSpeed = this.getSpeed() * 0.1F; this.setSpeed((float) this.getAttributeValue(Attributes.MOVEMENT_SPEED) * 1.5F); this.setDeltaMovement(new Vec3(strafe, travelVector.y, forward).scale(this.getSpeed())); this.calculateEntityAnimation(this, false); } else { // The wolf does not have a passenger or the passenger is not a player System.out.println("No player is mounted, or the passenger is not a player."); super.travel(travelVector); } } public boolean hasSaddle() { return this.hasSaddle; } public void setSaddle(boolean hasSaddle) { this.hasSaddle = hasSaddle; } @Override protected void dropEquipment() { super.dropEquipment(); if (this.hasSaddle()) { this.spawnAtLocation(Items.SADDLE); this.setSaddle(false); } } @SubscribeEvent public static void onServerTick(TickEvent.ServerTickEvent event) { if (event.phase == TickEvent.Phase.START) { MinecraftServer server = net.minecraftforge.server.ServerLifecycleHooks.getCurrentServer(); if (server != null) { for (ServerPlayer player : server.getPlayerList().getPlayers()) { if (player.isPassenger() && player.getVehicle() instanceof MountableWolfEntity) { MountableWolfEntity wolf = (MountableWolfEntity) player.getVehicle(); System.out.println("Tick: " + player.getName().getString() + " is correctly mounted on " + wolf); } } } } } private boolean lastMountedState = false; @Override public void tick() { super.tick(); if (!this.level.isClientSide) { // Only on the server boolean isMounted = this.isVehicle() && this.getControllingPassenger() instanceof Player; // Only print if the state changed if (isMounted != lastMountedState) { if (isMounted) { Player player = (Player) this.getControllingPassenger(); // Verify the passenger is a player System.out.println("Server: Player " + player.getName().getString() + " is now mounted."); } else { System.out.println("Server: The wolf no longer has a passenger."); } lastMountedState = isMounted; } } } @Override public void addPassenger(Entity passenger) { super.addPassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(true)); } } } @Override public void removePassenger(Entity passenger) { super.removePassenger(passenger); if (passenger instanceof Player) { Player player = (Player) passenger; if (!this.level.isClientSide && player instanceof ServerPlayer) { // Send the packet to the server to indicate the player is no longer mounted NetworkHandler.CHANNEL.send(PacketDistributor.PLAYER.with(() -> (ServerPlayer) player), new MountSyncPacket(false)); } } } @Override public boolean isControlledByLocalInstance() { Entity entity = this.getControllingPassenger(); return entity instanceof Player; } @Override public void positionRider(Entity passenger) { if (this.hasPassenger(passenger)) { double xOffset = Math.cos(Math.toRadians(this.getYRot() + 90)) * 0.4; double zOffset = Math.sin(Math.toRadians(this.getYRot() + 90)) * 0.4; passenger.setPos(this.getX() + xOffset, this.getY() + this.getPassengersRidingOffset() + passenger.getMyRidingOffset(), this.getZ() + zOffset); } } } MountSyncPacket package com.vals.valscraft.network; import com.vals.valscraft.entity.MountableWolfEntity; import net.minecraft.network.FriendlyByteBuf; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.player.Player; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class MountSyncPacket { private final boolean isMounted; public MountSyncPacket(boolean isMounted) { this.isMounted = isMounted; } public void encode(FriendlyByteBuf buffer) { buffer.writeBoolean(isMounted); } public static MountSyncPacket decode(FriendlyByteBuf buffer) { return new MountSyncPacket(buffer.readBoolean()); } public void handle(NetworkEvent.Context context) { context.enqueueWork(() -> { ServerPlayer player = context.getSender(); // Get the player from the context if (player != null) { // Verifies if the player has dismounted if (!isMounted) { Entity vehicle = player.getVehicle(); if (vehicle instanceof MountableWolfEntity wolf) { // Logic to remove the player as a passenger wolf.removePassenger(player); System.out.println("Server: Player " + player.getName().getString() + " is no longer mounted."); } } } }); context.setPacketHandled(true); // Marks the packet as handled } } networkHandler package com.vals.valscraft.network; import com.vals.valscraft.valscraft; import net.minecraft.resources.ResourceLocation; import net.minecraftforge.network.NetworkRegistry; import net.minecraftforge.network.simple.SimpleChannel; import net.minecraftforge.network.NetworkEvent; import java.util.function.Supplier; public class NetworkHandler { private static final String PROTOCOL_VERSION = "1"; public static final SimpleChannel CHANNEL = NetworkRegistry.newSimpleChannel( new ResourceLocation(valscraft.MODID, "main"), () -> PROTOCOL_VERSION, PROTOCOL_VERSION::equals, PROTOCOL_VERSION::equals ); public static void init() { int packetId = 0; // Register the mount synchronization packet CHANNEL.registerMessage( packetId++, MountSyncPacket.class, MountSyncPacket::encode, MountSyncPacket::decode, (msg, context) -> msg.handle(context.get()) // Get the context with context.get() ); } }  
    • Do you use features of inventory profiles next (ipnext) or is there a change without it?
    • Remove rubidium - you are already using embeddium, which is a fork of rubidium
  • Topics

×
×
  • Create New...

Important Information

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