Jump to content

[1.11.2]Substituting Gold_Ore doesn't work the same as Iron_ore??


olrustyeye

Recommended Posts

I wanted to change the way the in game minerals work as far as how they drop. IE: I want gold_ore to drop a piece of gold ore rather then the whole block. I also want to add a slight chance of getting a gem like Diamond. 

Heres whats super bizzaroworld. Iron works, Diamond works, but Coal and Gold don't. I haven't tried redstone yet because that has issues of its own. Also interesting it's crashing at the initialization portion of the game.  Anyone know whats wrong? 

Here my current code
https://pastebin.com/W7tTNY8C

 

And the error:
https://pastebin.com/net807Nd

 

As soon as I comment out substitute(Blocks.GOLD_ORE, new ModBlockOre2("oreGold")); everything magically works. (I've also tried commenting out everything BUT gold ore and it still doesn't work.) 

Edited by olrustyeye
Added Version
Link to comment
Share on other sites

Just now, Jay Avery said:

I don't know the exact cause of the error, but the substitution system is generally extremely buggy. It would be much easier to achieve what you're trying to do using events.

To me it looks like there something it doesn't like about the model. 
I'm a bit confused as to how I can use events to achieve that effect. I don't know much about how to use events to be honest. :/
Thanks for taking a look!

Link to comment
Share on other sites

7 minutes ago, Jay Avery said:

The docs have a basic overview of using events. To edit the drops from a block, you can use HarvestDropsEvent. In the event, you can check for your chosen block(s) and then edit the list of drops (from event#getDrops()) however you like.

Ooooo I like that!
I'll have to check it out and utilize it!
Side note: I tested somethings further and just broke my IronOre. Buggy is an understatement. I'm thinking it has something to do with Cache/memory. I'm going to try a restart and see if that clears things up a bit. That being said I'll probably use the events for a cleaner code. 

Link to comment
Share on other sites

I've got one issue right now,

This is my code:

@Mod.EventBusSubscriber
public class OverrideBlocksEvents{
 
	 
	@SubscribeEvent
	public static void overrideBlocksDrops(HarvestDropsEvent e){
		
		 if(!e.getWorld().isRemote)
	        {
	            if(e.getWorld().getBlockState(e.getPos()).getBlock() instanceof BlockOre)
	            {
	                e.getDrops().add(new ItemStack(Items.DIAMOND));
	            }
	        }

	}

		

I admittedly found this code from someone else, but from what I've read and understood. This should work. I'm checking what the block state is, and in the instance of a Ore Block it should add a diamond to the drops... right? 

 

Edit: I just used a code I personally had made and it now works because I hadn't initialized it before... jeez goes to show you someone else's code isn't always better.
here it is for those wondering:

	@SubscribeEvent
	public void overrideBlocksDrops(HarvestDropsEvent event){
		
		
				
		if (event.getState().getBlock() == Blocks.IRON_ORE){
		 Utils.getLogger().info("IronBlock Accessed. This method is Working");
			event.getDrops().add(new ItemStack(Blocks.DIAMOND_BLOCK, 1));
		}

	}


Just as a sidenote I'd still like to know why the other code doesn't work?

Edited by olrustyeye
Link to comment
Share on other sites

Hmm..
So I'm having an issue now where I can't REMOVE the block, but I can add. 

event.getDrops().remove(new ItemStack(Blocks.GOLD_ORE));

I think what I'm needing here is an addition check to check if the block dropped would be gold ore right? I'm just not sure where to go. I've told it to remove that drop but it wont. 

Looking at the other methods I'm not sure how to use remove if this isn't how one uses it? 

Link to comment
Share on other sites

You're telling it to remove a newly-created ItemStack object. That exact object won't be present in the list, because you've just made it.

 

You're right in thinking you need to check if the drop would be the ore block. You'll need to iterate through the list of drops, and for each element, check whether its item (ItemStack#getItem) is the ItemBlock for the block in question (Item.getItemFromBlock(block)).

  • Like 1
Link to comment
Share on other sites

	@SubscribeEvent
	public void overrideBlocksDrops(HarvestDropsEvent event){
		
		
		if (event.getState().getBlock() == Blocks.GOLD_ORE){
		 Utils.getLogger().info("IronBlock Accessed. This method is Working");
			
			event.getDrops().add(new ItemStack(Blocks.DIAMOND_BLOCK, 1));
			
			for(int i=0; i<= event.getDrops().size(); i++){
			if(event.getDrops().get(i) == new ItemStack(Blocks.GOLD_ORE)){
			event.getDrops().remove(i);
			
			Utils.getLogger().info("Was Gold Ore Removed?");
			}
		}
   }

I'm getting somewhere! Right now I got an error and I have some idea of why.
I think there is a parsing error perhaps, or again I'm trying to create something new where something already exsists.

 

Here my issue. Get is looking for an itemstack, so I'm trying to parse blocks into an item stack, but in order to do that I need new. Item.getblockfromitem wouldn't work because that makes it an item not a itemstack. 

I'm not sure where to go from here... :/

 

This is my error but I feel that the problem is probably obvious to those more experienced.
https://pastebin.com/Bd6KKTKK

 

 

Edited by olrustyeye
Link to comment
Share on other sites

You can't compare ItemStacks using the == operator, it checks for object identity - so a newly created stack will never be == to an existing stack. Instead you need to check the item that's within the stack (using stack#getItem) and compare it to the block's ItemBlock (which you can obtain from Item.getItemFromBlock). Items can be compared using ==, because they are singletons (so there's only ever one gold ore item, for example).

Edited by Jay Avery
  • Like 2
Link to comment
Share on other sites

17 minutes ago, Jay Avery said:

You can't compare ItemStacks using the == operator, it checks for object identity - so a newly created stack will never be == to an existing stack. Instead you need to check the item that's within the stack (using stack#getItem) and compare it to the block's ItemBlock (which you can obtain from Item.getItemFromBlock).

Ooooooooooooo

	if (event.getState().getBlock() == Blocks.GOLD_ORE){
		 Utils.getLogger().info("IronBlock Accessed. This method is Working");
			
			event.getDrops().add(new ItemStack(Blocks.DIAMOND_BLOCK, 1));
			
			for(int i=0; i<= event.getDrops().size(); i++){
			
				
			if(event.getDrops().get(i).getItem() == Item.getItemFromBlock(Blocks.GOLD_ORE)){
			event.getDrops().remove(i);
			
			Utils.getLogger().info("Was Gold Ore Removed?");
			}
			}


I'm still getting a error. I'm not sure what I am doing wrong now... The only thing I can think of is an issue in the for loop. Because removing the i means that the number that was 2 becomes 1 it has an issue when it goes to check for 2 and it's no longer there...
So I did remove "Blocks.GOLD_ORE"
and I still get an error. 

Seriously, thank you so much for helping me. It's no often a community helps a noob with out being a jerk to him. You guys are awesome, this must be cake walk for a lot of you! 
If it's any consolation I am learning a TON!

One huge key here is that it says, IndexOutofBoundsException. I think it's removing the item and then checking for it again. 

Edited by olrustyeye
Link to comment
Share on other sites

I was on the 'noob' side of these conversations for many months, so it seems only fair to pay it forward when I can! :)

 

Quote

The only thing I can think of is an issue in the for loop. Because removing the i means that the number that was 2 becomes 1 it has an issue when it goes to check for 2 and it's no longer there...

Ah yes, you have the right idea! To handle this safely, you'll need to use an Iterator for the list. Here is a little summary of using iterators. Instead of your for loop, create an iterator and then use a while loop, with the condition that the iterator hasNext. Then to get the next item from the list, instead of your get(i), use next on the iterator. That'll return an element of the list (an ItemStack) in the way you expect, and you can check its conditions in the way you currently are, and remove it from the list using remove on the iterator.

 

Edit: Checking the length in that way unfortunately won't work reliably, because of counting through the list at the same time as changing its length. Here is a stackoverflow question addressing the same problem.

Edited by Jay Avery
Link to comment
Share on other sites

4 minutes ago, Jay Avery said:

I was on the 'noob' side of these conversations for many months, so it seems only fair to pay it forward when I can! :)

 

Ah yes, you have the right idea! To handle this safely, you'll need to use an Iterator for the list. Here is a little summary of using iterators. Instead of your for loop, create an iterator and then use a while loop, with the condition that the iterator hasNext. Then to get the next item from the list, instead of your get(i), use next on the iterator. That'll return an element of the list (an ItemStack) in the way you expect, and you can check its conditions in the way you currently are, and remove it form the list using remove on the iterator.

 

Edit: Checking the length in that way unfortunately won't work reliably, because of counting through the list at the same time as changing its length. Here is a stackoverflow question addressing the same problem.

Yup, I was just thinking that. It's a band-aid not a solution. The iterator sounds much more reliable. 

Link to comment
Share on other sites

		if (event.getState().getBlock() == Blocks.IRON_ORE){
		 Utils.getLogger().info("IronBlock Accessed. This method is Working");
			event.getDrops().add(new ItemStack(Blocks.DIAMOND_BLOCK, 1));
	
			ListIterator drops = event.getDrops().listIterator();
			while(drops.hasNext()){
			Object element = drops.next();
			
			if(element == Item.getItemFromBlock(Blocks.IRON_ORE)){
			event.getDrops().remove(element);
			 Utils.getLogger().info("WE DID IT!");
			}
			}
		}

So I got the whileloop going now,

my issue is I think I'm deleting the element rather then a block in the element. I'm not sure how to tell it to remove what I want it to at this point. :/ 
Actually theres a problem with the If statement because it's not returning me...oh I think I might know what the issue might be. Element is an itemstack not an item...
Still before I go test that. It's not returning true so theres an issue there. 

Edited by olrustyeye
Link to comment
Share on other sites

You need to check the item of the element in the same way you were with your for loop: the element is an ItemStack so you need to call getItem to see if that matches the block's item.

 

Edit: You really are getting close, don't be too disheartened!

Edited by Jay Avery
Link to comment
Share on other sites

4 minutes ago, olrustyeye said:


Actually theres a problem with the If statement because it's not returning me...oh I think I might know what the issue might be. Element is an itemstack not an item...
Still before I go test that. It's not returning true so theres an issue there. 

That's the reason it's not returning true, so fixing that will solve your problem. An ItemStack will never be == to an Item, so the if statement will always be false in its current form.

Link to comment
Share on other sites

Yes!!! I got it to work. I don't love the fact I'm casting "element" into an itemstack I feel like that can be refined. But I have another issue I encountered. 
This code does NOT work with redstone. It's only removing one of the redstone. It's interesting because it should be checking it over and over until it deletes all of them right? 

Everything else works like a charm!

		if (event.getState().getBlock() == Blocks.LIT_REDSTONE_ORE){
			 Utils.getLogger().info("IronBlock Accessed. This method is Working");
				event.getDrops().add(new ItemStack(Blocks.DIAMOND_BLOCK, 1));
		
				ListIterator drops = event.getDrops().listIterator();
				while(drops.hasNext()){
				Object element = drops.next();
			
				 Utils.getLogger().info(element);
				if(((ItemStack) element).getItem() == Items.REDSTONE){
				event.getDrops().remove(element);
				 Utils.getLogger().info("WE DID IT!");
				}
				}
			}
		if (event.getState().getBlock() == Blocks.REDSTONE_ORE){
			 Utils.getLogger().info("IronBlock Accessed. This method is Working");
				event.getDrops().add(new ItemStack(Blocks.DIAMOND_BLOCK, 1));
		
				ListIterator drops = event.getDrops().listIterator();
				while(drops.hasNext()){
				Object element = drops.next();
			
				 Utils.getLogger().info(element);
				if(((ItemStack) element).getItem() == Items.REDSTONE){
				event.getDrops().remove(element);
				
				 Utils.getLogger().info("WE DID IT!");
				}
				}
			}

hehe well this isn't the ONLY issue actually. I"m also having an issue of trying to access the metadata of for dyes for lapis ore. I think I might be able to figure that one out, but if not I might be back. 

Edited by olrustyeye
Link to comment
Share on other sites

43 minutes ago, diesieben07 said:

You could get rid of the ugly cast by not using raw types. getDrops returns a List<ItemStack>, therefor listIterator also returns ListIterator<ItemStack>. Raw types are a legacy thing and should never be used in modern Java code.

Also, don't call remove on the list while you are iterating, this will crash. You need to use the remove method on the iterator to remove the current element.

Holy crap... this is powerful stuff!
It's funny how I'm not thinking in Java terms sometimes. I think I remember back in my college days (Now 4 years ago JEEZ) using lists. I totally forgot how easy they are. :P
Thank you!!!!
This is solved!

 

For those wondering reading this in the future here is the key:
 

		if (event.getState().getBlock() == Blocks.BLOCK_YOU_WANT_TO_EDIT)
		{
				event.getDrops().add(new ItemStack(YourModItemOrBlock.Item_Or_Block, Number_Of_It)); //This adds the item or block you want to 
																									// You want to add to the block.
				ListIterator<ItemStack> drops = event.getDrops().listIterator(); //This Gets the drop and puts it into a list of ItemStacks
				while(drops.hasNext()) // Using a while loop so we don't get out of the bounds of the list
					{
					ItemStack element = drops.next(); //gets the next itemstack in the list
					if(element.getItem() == Block/Item.BLOCK_OR_ITEM_YOU_WANT_TO_EDIT) // Does the list Item also match the item you want gone?
						{					
						drops.remove();	//remove it!
						}
					}
			}



Now that is some pretty beautiful code. Thanks for the help everyone I learned a TON from this little exercise!

Link to comment
Share on other sites

4 hours ago, diesieben07 said:

For the future, this feature is called generics, and they are much more powerful than what you have seen here.

Generics are fucking awesome and it's the one tool in the toolbox I don't have when working in Unity that I miss (or at least, not to the same degree: there's typed lists and such, but everything needs to be strictly defined at compile time: no contravariance or covaraiance which means that I can't generically define delegate methods).

 

Also, this method declaration is insane:

https://github.com/Draco18s/ReasonableRealism/blob/master/src/main/java/com/draco18s/flowers/OreFlowersBase.java#L204

It can technically be simplified, but not by a whole lot.

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.

Link to comment
Share on other sites

2 hours ago, Draco18s said:

Generics are fucking awesome and it's the one tool in the toolbox I don't have when working in Unity that I miss (or at least, not to the same degree: there's typed lists and such, but everything needs to be strictly defined at compile time: no contravariance or covaraiance which means that I can't generically define delegate methods).

 

Also, this method declaration is insane:

https://github.com/Draco18s/ReasonableRealism/blob/master/src/main/java/com/draco18s/flowers/OreFlowersBase.java#L204

It can technically be simplified, but not by a whole lot.

Generics expand to meet the expanding generics? Lol. 
 

Link to comment
Share on other sites

2 hours ago, olrustyeye said:

Generics expand to meet the expanding generics? Lol.

I wanted a single function that would handle the linkage between "an ore block" and "a flower block" so that the flowers could be used to indicate the presence of ore in the area. Which involves 3 different block states: the ore, the flower, and the desert flower.  And two properties and their corresponding values (for the flower and desert flower respectively).

 

It's the craziest method signature I've ever written.

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.

Link to comment
Share on other sites

1) I don't like the redundancy between lit and unlit redstone. Can't one boolean expression test for both?

 

2) If removing from a list is problematic, then maybe you could build a replacement list that skips the elements you would delete and then swaps lists at the end.

The debugger is a powerful and necessary tool in any IDE, so learn how to use it. You'll be able to tell us more and get better help here if you investigate your runtime problems in the debugger before posting.

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

    • Ok. Thanks. by the way, will this crash in any circumstances? public boolean onLeftClickEntity(ItemStack stack, Player player, Entity entity) { if (entity instanceof LivingEntity){ LivingEntity victim = (LivingEntity) entity; if(!victim.isDeadOrDying() && victim.getHealth()>0){ victim.setHealth(0); return true; } } return false; }  
    • You shouldn't be extracting the mod .jar, just place it in your mods folder.
    • so basically another rundown of my probelm. Im the admin of a 1.20.1 modded server. Were using forge 47.2.0 but tested this issue in other forge versions too on sevrer and client side. so the forge version isnt the issue. The bug happens in following instances. Were using the attacks of the jujutsucraft mod by orca normally. And for everyone that stands there nothing changes. But everyone who wasnt in the chunks before or who relogins again those chunks will appear invisible for the most part. I tried fixing this be removing and adding following mods in many combinations. Embeddium, canary, memoryleakfix, ai improvements, Krypton reforges, better chunkloading, radium reforged, embeddium plus, farsight, betterchunkloading, oculus I tested most of these mods alone and in differents combinations with each other and without the mods. What i noticed is zhat when i removed  . most invisible chunks will return or semi return. and only ine or two chunks stay invisible. I rechanged those mids mostly on the cöient side but also some in the serveside. Ir most likely isnt an issue with another non performance mod since i noticed this thing with embeddium. Ans also the problem wasnt there im the beginning of the server. Granted since then we updated some of the mods that add content and their lib mod. But i went to every big mods discord and community that we have and i didnt find someone else havinf that chunk problem. Heres the link to a video of the Problem. https://streamable.com/9v1if2     heres the link to the modlist: https://ibb.co/myF8dtX     Pleaee im foghting for months with this problem. All the performance mods kn the modlist are for sure not the issue i tested without all of them.
    • It looks like you're only setting the health if the thing you are hitting is a player.  
    • It sounds like you accidentally have two items that are both named "orange". Ensure that you give items unique names in the string when you register them. That's one of the more annoying errors to track down if you don't know what's causing it, though.
  • Topics

×
×
  • Create New...

Important Information

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