Jump to content

[1.13.2] Modifying vanilla ore generation 1.13+?


treebranch

Recommended Posts

I'm trying to handle when a vanilla ore is generated so I can cancel it under certain conditions.

So far I've tried looking into OreGenEvent.GenerateMinable and MinecraftForge.ORE_GEN_BUS, but neither of those appear to exist in 1.13.

I tried searching these forums, but nobody seems to have asked about this yet. There isn't any up-to-date online documentation either.

I tried skimming through events manually and guessing by their names, but I couldn't find anything.

Does anybody know the new way to handle when an ore block is generated?

 

Link to comment
Share on other sites

I came across this thread:

 

Here's the code I ended up coming up with as a test, replacing all coal ore with diamond ore every time a chunk loads:

 

@SubscribeEvent
public void oreGenMinable(ChunkEvent.Load event) {
	IChunk chunk = event.getChunk();
	LOGGER.info("SCANNING CHUNK at " + chunk.getPos().toString());
	IBlockState coaldefault = Blocks.COAL_ORE.getDefaultState();
	IBlockState diamonddefault = Blocks.DIAMOND_ORE.getDefaultState();
	for (int x = 0; x < 16; x++) {
		for (int z = 0; z < 16; z++) {
			for (int y = 2; y <= 256; y++) {
				BlockPos pos = new BlockPos(x, y, z);
				if (chunk.getBlockState(pos) == coaldefault) {
					chunk.setBlockState(pos, diamonddefault, false);
				}
			}
		}
	}
}

 

I noticed the chunk class no longer has .markDirty(), I'm wondering if this is still necessary. I also still need a way to avoid overwriting the same chunk twice.

Edited by treebranch
Link to comment
Share on other sites

11 minutes ago, treebranch said:

LOGGER.info(

Use debug or nothing pls (log spam & logging stuff slows down loading times)

 

11 minutes ago, treebranch said:

BlockPos pos = new BlockPos(x, y, z);

Please use a MutableBlockPos or a PooledMutableBlockPos.

protip: PooledMutableBlockPos implements AutoClosable so it can be used in try-with-resources (AKA automatic resource management) blocks

Example:

try (PooledMutableBlockPos pos = PooledMutableBlockPos.retain()) {

//loop

pos.setPos(x, y, z);

//do stuff with pos

}

Edited by Cadiboo
Slam -> spam

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

This code isn't doing what you want it to do and is horribly inefficient. First of all Chunkevent.Load fires every time the chunk is loaded, not just the first time it generates which will run this snippet of pretty expensive code every time ANY chunk is loaded. Not to say it will also replace the coal ore(in this case) regardless of how it ended up in the chunk - whether it was generated or placed by the player your code cares not.

 

Look at how vanilla's features now work, I believe the generators are registered per biome to a list and you should be able to just search that list on startup and remove the generators you don't want present.

Link to comment
Share on other sites

7 minutes ago, V0idWa1k3r said:

This code isn't doing what you want it to do and is horribly inefficient. First of all Chunkevent.Load fires every time the chunk is loaded, not just the first time it generates which will run this snippet of pretty expensive code every time ANY chunk is loaded. Not to say it will also replace the coal ore(in this case) regardless of how it ended up in the chunk - whether it was generated or placed by the player your code cares not.

 

Look at how vanilla's features now work, I believe the generators are registered per biome to a list and you should be able to just search that list on startup and remove the generators you don't want present.

 

It may be inefficient but I'm blindly trusting what @Draco18s said on the other thread:

 

On 12/15/2017 at 10:00 AM, Draco18s said:

For reference, you can scan an entire chunk and replace blocks in about 400,000 nanos (0.4 ms). You don't really need to worry about time slicing. 

 

Removing generators won't do me well because I'm going to need certain blocks to generate differently depending on how far away from world center the chunk is.

And don't worry, I know it's fired everytime a chunk loads. I'm still looking for a good way to keep track of what chunks have been modified and which ones haven't.

 

However I appreciate your help, and please continue suggesting things if you know alternative ways to do what I want, because there isn't much info out there.

Edited by treebranch
Link to comment
Share on other sites

A PooledMutableBlockPos is a BlockPos that is Mutable (can be changed/moved) and Pooled. Retain gets a PooledMutableBlockPos from the pool for you and close (called automatically by the try-with-resources block in the same way as in a try-finally block) releases the PooledMutableBlockPos you got from retain back into the pool.

 

So instead of creating 16x16x255 (65,280) new BlockPos objects you only create maximum 1 new object (the PooledMutableBlockPos is likely to have already been created and added to the pool).

Doing this avoids the cost of initialising all those objects (this cost is pretty small, but still deserves mentioning), avoids using up 786,432 bytes of ram (each block pos contains 3 integers and each integer is 4 bytes of ram) for each chunk and it avoids the cost of destroying (garbage collecting) all those objects.

 

This may not seem large, but remember that all this is being run for each chunk, and that any reduction in load time counts in big modpacks. 

Edited by Cadiboo
  • Thanks 1

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

I think IChunk is immutable, and that's why .markDirty() doesn't exist. Older versions of Forge had this method simply return a mutable Chunk. I can't figure out how to get my hands on a Chunk instead of an IChunk, and searching for IChunk on this forum brings this thread up as the only result. Does anybody here have more info?

 

Edit: So far I've had no visible problems casting my IChunk to a Chunk and calling the method anyway. Not sure if this is a bad idea or not.

Edited by treebranch
Link to comment
Share on other sites

Okay so I ended up creating a table called IgnoreChunks to keep track of what chunks have been modified and therefore should be ignored. The chunk's position is added to IgnoreChunks after it's been modified, and the position is unloaded when the chunk is unloaded. The chunk's ignore status is saved via NBT on OnChunkData.Save, and that NBT data is checked on OnChunkData.Load to populate the IgnoreChunks table again.

 

It works as expected, and there are no memory leaks, but there's a problem. The ignore state is lost when the game is entirely restarted (closed then re-opened) which causes chunks to get overwritten again. The cause seems to be that ChunkDataEvent.Load is never called (!!!) and I can't tell whether this is a Forge bug or my own mistake.

 

Here's the code:

 

@SubscribeEvent
public void onChunkLoadData(ChunkDataEvent.Load event) {
	NBTTagCompound chunkdata = event.getData();
	
	// If this chunk is marked as ignored in NBT, load its position to the ignore list so that onChunkLoad knows not to modify it
	if (chunkdata.getBoolean(ModInfo.MODID + "_ignore")) {
		IgnoreChunks.put(event.getChunk().getPos().asLong(), true);
	}
}

@SubscribeEvent
public void onChunkSaveData(ChunkDataEvent.Save event) {
	NBTTagCompound chunkdata = event.getData();
	
	// If this chunk's position is loaded in the ignore list, mark it as ignored in NBT before it's saved
	if (IgnoreChunks.containsKey(event.getChunk().getPos().asLong())) {
		chunkdata.setBoolean(ModInfo.MODID + "_ignore", true);
	}
}

@SubscribeEvent
public void onChunkLoad(ChunkEvent.Load event) {
	Chunk chunk = (Chunk) event.getChunk();
	
	// If this chunk's position is loaded in the ignore list, don't modify it (return immediately)
	if (IgnoreChunks.containsKey(chunk.getPos().asLong())) {
		return;
	}
		
	IBlockState coaldefault = Blocks.COAL_ORE.getDefaultState();
	IBlockState diamonddefault = Blocks.DIAMOND_ORE.getDefaultState();
	try (PooledMutableBlockPos pos = PooledMutableBlockPos.retain()) {
		for (int x = 0; x < 16; x++) {
			for (int z = 0; z < 16; z++) {
				for (int y = 2; y <= 256; y++) {
					pos.setPos(x, y, z);
					if (chunk.getBlockState(pos) == coaldefault) {
						chunk.setBlockState(pos, diamonddefault, false);
					}
				}
			}
		}
	}
	
	// Load the chunk's position to the ignore list
	IgnoreChunks.put(chunk.getPos().asLong(), true);
  
	chunk.markDirty();
}

@SubscribeEvent
public void onChunkUnload(ChunkEvent.Unload event) {
	// Unload this chunk's position from the ignore list if it's loaded
	Long pos = event.getChunk().getPos().asLong();
	if (IgnoreChunks.containsKey(pos)) {
		IgnoreChunks.remove(pos);
	}
}

 

Edited by treebranch
Link to comment
Share on other sites

So after a good night's sleep I've rethought my approach and come up with a solution that doesn't involve any data saving. It simply marks chunks as new on ChunkGeneratorEvent.ReplaceBiomeBlocks—this event could be anything, I'm just using it because it's called during the generation of new chunksthen the chunks are replaced later in on ChunkEvent.Load.

 

It works, almost too well. However it's causing a memory leak. Even though I remove new chunks from my NewChunks list after they've been replaced, it seems that ReplaceBiomeBlocks is being called more often than ChunkEvent.Load is, and the list steadily grows faster than it shrinks.

 

Here's the code:

 

@SubscribeEvent
public void onReplaceBiomeBlocks(ChunkGeneratorEvent.ReplaceBiomeBlocks event) {
	// This event is called whenever a new chunk is being generated, so we can prepare the chunk for replacement
	NewChunks.put(event.getChunk().getPos().asLong(), true);
}

@SubscribeEvent
public void onChunkLoad(ChunkEvent.Load event) {
	Chunk chunk = (Chunk) event.getChunk();
	
	// If this chunk isn't marked as a new chunk, don't modify it (return immediately)
	if (!NewChunks.containsKey(chunk.getPos().asLong())) {
		return;
	}
		
	IBlockState coaldefault = Blocks.COAL_ORE.getDefaultState();
	IBlockState diamonddefault = Blocks.DIAMOND_ORE.getDefaultState();
	try (PooledMutableBlockPos pos = PooledMutableBlockPos.retain()) {
		for (int x = 0; x < 16; x++) {
			for (int z = 0; z < 16; z++) {
				for (int y = 2; y <= 256; y++) {
					pos.setPos(x, y, z);
					if (chunk.getBlockState(pos) == coaldefault) {
						chunk.setBlockState(pos, diamonddefault, false);
					}
				}
			}
		}
	}
	
	// Remove this chunk from the list of new chunks to free up memory and prevent it from being replaced again 
	NewChunks.remove(chunk.getPos().asLong());
	
	chunk.markDirty();
}

 

Edited by treebranch
Link to comment
Share on other sites

Why not just use a HashSet? Also there’s probably a better event for what you want (like the chunk decorate event)

About Me

Spoiler

My Discord - Cadiboo#8887

My WebsiteCadiboo.github.io

My ModsCadiboo.github.io/projects

My TutorialsCadiboo.github.io/tutorials

Versions below 1.14.4 are no longer supported on this forum. Use the latest version to receive support.

When asking support remember to include all relevant log files (logs are found in .minecraft/logs/), code if applicable and screenshots if possible.

Only download mods from trusted sites like CurseForge (minecraft.curseforge.com). A list of bad sites can be found here, with more information available at stopmodreposts.org

Edit your own signature at www.minecraftforge.net/forum/settings/signature/ (Make sure to check its compatibility with the Dark Theme)

Link to comment
Share on other sites

8 minutes ago, Cadiboo said:

Why not just use a HashSet? Also there’s probably a better event for what you want (like the chunk decorate event)

Wasn't aware of HashSet, it looks like it just uses a HashTable internally so I'll switch anyway since it makes more sense for my code.

 

Unfortunately there's no chunk decorate event in 1.13. I've looked at all the past code examples I could, and it seems like almost every event used for purposes like this has been removed. ChunkGeneratorEvent.ReplaceBiomeBlocks is the closest I could find.

Edited by treebranch
Link to comment
Share on other sites

Well, I'm just about at the end of my wits trying to figure this out. I went as far as to turn the HashSet into a ConcurrentHashMap and iterate through it every ServerTickEvent to deal with new chunks. Theoretically this should always modify chunks the tick after they're created. But ChunkGeneratorEvent.ReplaceBiomeBlocks is called on so many not-loaded chunks that this method slowed the game down to a crawl. Distributing it over several ticks is too slow and introduces the problem of people closing the game before every chunk has been replaced. Does anybody here know of a simpler way for me to just edit a chunk after its been created?

Link to comment
Share on other sites

Okay, I need to move on with my mod. I've went back to the original method of indiscriminately overwriting chunks every time they're loaded. Mostly this will involve replacing rare ores with stone unless the chunk is a certain distance away from spawn, or unless the block's Y level is deep enough. My solution to the problem of player-placed ores getting overwritten looks something like this:

 

@SubscribeEvent
public void onBlockHarvestDrops(BlockEvent.HarvestDropsEvent event) {
	if (event.isSilkTouching() && event.getState() == Blocks.COAL_ORE.getDefaultState()) {
		event.getDrops().clear();
		event.getDrops().add(new ItemStack(Items.COAL));
	}
}

 

If anybody has a problem with this, please let me know the way you'd do it instead, and I'll happily switch. Until then...I guess I'll just warn people on the mod page that they shouldn't use this mod with creative mode.

Link to comment
Share on other sites

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

    • Selamat datang di AGEN777 salah satu situs slot gacor gampang menang hari ini di Indonesia yang sangat menjajikan. Slot gacor adalah adalah suatu istilah yang digunakan untuk menjelaskan sebuah permainan slot gampang menang di situs slot online. Situs slot gacor AGEN777 ini bisa menjadi populer walaupun terbilang baru karena RTP slot online yang disajikan begitu tinggi. Seiring dengan perkembangan zaman situs slot gacor terbaru ini juga sudah update dari segi teknologi yang menggunakan HTML5, inilah yang membuat grafis permainan terlihat begitu modern, audio lebih jernih, dan user interface yang smooth. Tidak dipungkiri grafis yang kami memiliki sudah menarik banyak sekali pendatang baru yang ingin merasakan terbawa dalam suasana tema permainan mesin slot. Kehadiran slot gacor menjadi angin segar bagi para pecinta judi online, memberikan alternatif permainan yang seru dan menguntungkan. Tak heran jika popularitas slot gacor terus meningkat, menarik minat para pemain baru untuk mencoba peruntungan mereka di situs slot gacor hari ini AGEN777.
    • Selamat datang di SLOT777 salah satu situs slot gacor gampang menang hari ini di Indonesia yang sangat menjajikan. Slot gacor adalah adalah suatu istilah yang digunakan untuk menjelaskan sebuah permainan slot gampang menang di situs slot online. Situs slot gacor SLOT777 ini bisa menjadi populer walaupun terbilang baru karena RTP slot online yang disajikan begitu tinggi. Seiring dengan perkembangan zaman situs slot gacor terbaru ini juga sudah update dari segi teknologi yang menggunakan HTML5, inilah yang membuat grafis permainan terlihat begitu modern, audio lebih jernih, dan user interface yang smooth. Tidak dipungkiri grafis yang kami memiliki sudah menarik banyak sekali pendatang baru yang ingin merasakan terbawa dalam suasana tema permainan mesin slot. Kehadiran slot gacor menjadi angin segar bagi para pecinta judi online, memberikan alternatif permainan yang seru dan menguntungkan. Tak heran jika popularitas slot gacor terus meningkat, menarik minat para pemain baru untuk mencoba peruntungan mereka di situs slot gacor hari ini SLOT777.
    • DAFTAR DEPO 50 BONUS 50 | DEPOSIT 50 BONUS 50 TO KECIL 3X 5X 7X 10X 12X 15X DI AWAL   ⚡️ KLIK DAFTAR BONUS NEW MEMBER 100 DI AWAL ⚡️ ⚡️ LINK SLOT GACOR BONUS NEW MEMBER 100 DI DEPAN ⚡   PROMO SLOT GACOR TERBARU PALING DICARI TAHUN 2024 ADALAH DEPO 50 BONUS 50 | DEPO 50 BONUS 50 TO KECIL | DEPOSIT 50 BONUS 50 TO KECIL 3X 5X 7X 10X 12X 15X DI AWAL?Apa sih yang dimaksud dengan DEPOSIT 50 BONUS 50 TO KECIL 3X 5X 7X ? DEPOSIT 50 BONUS 50 TO KECIL 3X 5X 7X adalah sebuah bonus yang telah disiapkan oleh situs khusus slot online untuk for member baru yang baru bergabung. Dan 100 sendiri adalah nilai dari bonus yang diberikan untuk member baru tersebut. Untuk Bonus yang tersedia adalah deposit 50 bonus 50 to 3x & deposit 50 bonus 50 to 5x & deposit 50 bonus 50 to 7x & depo 50 bonus 50 to 3x & depo 50 bonus 50 to 7x adalah bonus yang sangat terbaik dikelasnya dikarenakan memberikan nilai lebih dalam melakukan permainan agar bisa penarikan dengan sangat cepat yang diharapkan oleh setiap member.   DEPO 50 BONUS 50 Jadi situs judi slot online gampang berhasil deposit pulsa tanpa potongan pula membagikan keringanan dalam melaksanakan deposit duit asli lewat pulsa. Kalian dapat bermain slot deposit minimun 10 rb yg salah satu taruhan taruhan terkecil serta paling murah. jadi dengan taruhan deposit kecil pulsa tanpa potongan serta memainkan game slot Gampang jackpot ditambah promo bonus slot member baru 100, hingga profit di depan mata kalian. Selanjutnya ini ialah berkas 50 daftar julukan julukan slot online mudah berhasil yg sesuai buat kalian selaku pendatang baru dengan memakai bonus slot member baru 100 di awal.
    • DEPO 100 BONUS 100 | DEPOSIT 100 BONUS 100 TO KECIL 3X 5X 7X 10X 12X 15X DI AWAL     ⚡️ KLIK DAFTAR BONUS NEW MEMBER 100 DI AWAL ⚡️ ⚡️ LINK SLOT GACOR BONUS NEW MEMBER 100 DI DEPAN ⚡   DEPO 100 BONUS 100 | DEPO 100 BONUS 100 TO KECIL | DEPOSIT 100 BONUS 100 TO KECIL 3X 5X 7X 10X 12X 15X DI AWAL?Apa sih yang dimaksud dengan DEPOSIT 100 BONUS 100 TO KECIL 3X 5X 7X ? DEPOSIT 100 BONUS 100 TO KECIL 3X 5X 7X adalah sebuah bonus yang telah disiapkan oleh situs khusus slot online untuk for member baru yang baru bergabung. Dan 100 sendiri adalah nilai dari bonus yang diberikan untuk member baru tersebut. Untuk Bonus yang tersedia adalah deposit 100 bonus 100 to 3x & deposit 100 bonus 100 to 5x & deposit 100 bonus 100 to 7x & depo 100 bonus 100 to 3x & depo 100 bonus100 to 7x adalah bonus yang sangat terbaik dikelasnya dikarenakan memberikan nilai lebih dalam melakukan permainan agar bisa penarikan dengan sangat cepat yang diharapkan oleh setiap member. Depo 100 Bonus 100 – Depo 100 bonus 100 to 3x – Deposit 100 Bonus 100 To Kecil – Deposit 100k Bonus 100k – Deposit 100 Bonus 100 – Depo 100 Bonus 100 To 3x – Depo 100 Bonus 100 To 5x – Depo 100 Bonus 100 TO Kecil – Depo 100 Bonus 100 To 3x – Depo 100 Bonus 100 Tanpa To – Depo 100 Bonus 100 – Depo 100 Bonus 35 To 5x DEPO 100 BONUS 100 Jadi situs judi slot online gampang berhasil deposit pulsa tanpa potongan pula membagikan keringanan dalam melaksanakan deposit duit asli lewat pulsa. Kalian dapat bermain slot deposit minimun 10 rb yg salah satu taruhan taruhan terkecil serta paling murah. jadi dengan taruhan deposit kecil pulsa tanpa potongan serta memainkan game slot Gampang jackpot ditambah promo bonus slot member baru 100, hingga profit di depan mata kalian. Selanjutnya ini ialah berkas 20 daftar julukan julukan slot online mudah berhasil yg sesuai buat kalian selaku pendatang baru dengan memakai bonus slot member baru 100 di awal.
    • Slot Freebet Tanpa Syarat Bermain Slot Online tentu dapat dimainkan dengan Tanpa Syarat dengan bergabung bersama kami di freebet slot jadi kalian tinggal daftar dan langsung login ke dalam akun dan saldo akan bertambah otomatis dan dapat di klaim setiap harinya. Dengan layanan ini dapat membuat kalian menjadi pemenang setiap harinya dari mendapatkan slot Freebet Tanpa Syarat dan langsung masuk tanpa harus di klaim. Slot Freebet Tanpa Syarat dapat dimainkan di semua jenis permainan Slot Online dengan tujuan memudahkan para pemain dalam mendapatkan kemenangan dari layanan Freebet Tanpa Syarat 2024. DAFTAR KLIK DI SINI https://umpo.ac.id/assets/css/pages/-/depo-25-bonus-25/ DAFTAR KLIK DI SINI  http://seminarmajlisdekan.upsi.edu.my/depo25/ Untuk mendapatkan freebet slot tanpa Syarat kalian hanya perlu tahu informasi terlebih dahulu dalam tata cara mendapatkan hal tersebut. Bersama kami saat ini freebet 15k tanpa Syarat 2024 didapatkan dengan mudah yaitu dengan hanya melakukan pendaftaran dan mendapatkan userid maka kami dapat menjamin saldo akan masuk langsung ke dalam akun kalian. Berbagai jenis hadiah jackpot sensasional bisa didapatkan dengan mengandalkan Freebet Tanpa Syarat langsung masuk 2024 dan pastinya anti kalah. Saat ini telah banyak orang yang mengetahui layanan yang kami sediakan sehingga setiap harinya ada ratusan member yang telah bergabung dan mendapatkan layanan freebet 100k Asli secara langsung. Sistem permainan yang ditawarkan telah mendapatkan kepercayaan dari berbagai member yang sudah mendapatkan keuntungan dari hal itu yang berasal dari permainan Slot Online. Keyword Terkait : slot freebet 30k tanpa deposit slot freebet slot freebet tanpa deposit slot freebet new member situs slot freebet situs slot freebet tanpa deposit slot freebet tanpa deposit 2023 slot freebet 20k slot freebet gratis link slot freebet:
  • Topics

×
×
  • Create New...

Important Information

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