Jump to content

Recommended Posts

Posted

Hello, I've recently been working on this cool mod, and I came across a problem.

I need to make some methods (for resetting fire to air) wait for 1/2 a second without causing immense lag, crashing the client/server or not calling the fire setting methods.

 

With my current code, here: http://gw.minecraftforge.net/MFKn , it does nothing when I right click. Well, I guess it does something. It replaces the blocks in a 5 block radius with air. It doesn't place the fire like I wanted it to.

When I used threading, like Thread.sleep(), it causes immense lag and sometimes doesn't even make the fire.

If I use the wait() method it actually makes the client wait, and onItemUse doesn't like that so it crashes.

 

So, any good wait methods?

EntityHerobrine.setDead();

 

Pwned.

Posted

If you need a precise time you can use the world.scheduleBlockUpdate (I think its called that way...) method. It is for example used by redstone repeaters to update their state after a delay. Never ever use Thread.sleep()! It will cause the whole Server to stop for as long as you make it wait (if you do it in the  main server Thread).

If you need a random, long time use setTickRandomly which is e.g. used by Leaves to decay, wheat to grow, etc, etc.

Using scheduleBlockUpdate, the fire placement is still not called. Although, I don't know exactly all the parameters, just that all 5 are ints. Any idea what each one stands for?

EntityHerobrine.setDead();

 

Pwned.

Posted

So I'm guessing since I'm making air appear I should do 0 for the blockID?

EDIT: Fire still doesn't spawn, but I know the air is because it makes other blocks go away.

EntityHerobrine.setDead();

 

Pwned.

Posted

Well, that still doesn't spawn the fire.

Earlier, before I tried any wait methods, or added the air to appear later, the fire spawned alright.

So my current method is

w.scheduleBlockUpdate(par4, par5, par6, Block.fire.blockID, 10)

I placed that between all the setBlock() methods for the fire and the air.

EntityHerobrine.setDead();

 

Pwned.

Posted

Are you editing the vanilla fire? Probably not. I guess you misunderstood what scheduleBlockUpdate does. Re-read my post:

world.scheduleBlockUpdate(x, y, z, blockId, NUMBER_OF_TICKS);

if you do that, the method updateTick will be called with that x, y, z NUMBER_OF_TICKS ticks later.

So for every .setBlock() method of fire, I have to have one of those?

Also, where is this telling the system to wait 10 ticks to replace the fire with air?

EntityHerobrine.setDead();

 

Pwned.

Posted

No. If you want something to happen to your block in lets say 10 ticks, do the following:

world.scheduleBlockUpdate(x, y, z, blockId, 10);

10 ticks later the world will automatically call

Block.blocksList[blockId].updateTick(world, x, y, z, random);

You have to do the action that should happen 10 ticks later in that method.

Okay, so something like this:

 

public boolean onItemUse(params here){

if(!w.isRemote){

w.setBlock(x, y, z, Block.fire.blockID);

w.scheduleBlockUpdate(x, y, z, block.fire.blockID, 10);

w.setBlock(x, y, z, 0);

}

}

 

 

This is just getting a bit more confusing every time  :-\

EntityHerobrine.setDead();

 

Pwned.

Posted

Bringing this back, as I am still having trouble. The class TickHandler doesn't exist, according to my Eclipse.

I really don't want to make a custom fire just for this. Also, all I need it to do is for my system to wait 10 ticks between placing fire around me to replacing that with air. After re-reading your posts, it doesn't look like you have the same idea as me :P

EntityHerobrine.setDead();

 

Pwned.

Posted

I do belive making a custom fire block will be alot easier, as in how you plan doing this in a tickHandler anyway?

In the case of custom fire you simple override the updateTick (in which case fire block has it overrided already anyway) as this is fire it has its own ticking

you could for example if want it to spread do super.updateTick(), or just override it if dont want spreading of ur own fire...

also for this to work, you simply set the block, and then schudle the update of the block...

 

~I was here~

Posted
as in how you plan doing this in a tickHandler anyway?

probably with some sort of queue, each item would have activation time (in ticks, measured maybe from a start of minecraft?) and a collection of fire blocks which would go out (to be precise it would be dimmension id and coordinates, not the actial Block). [something similar to event calendar of discrete simulation - http://en.wikipedia.org/wiki/Discrete_event_simulation#Events_List.]

 

by adding your own fire you're risking incompatibility with mods depending on fire detection.

mnn.getNativeLang() != English

If I helped you please click on the "thank you" button.

Posted

you have to implement your own tickhandler (implementing interface ITickHandler) and then register it. example of tick handler is here - http://www.minecraftforge.net/wiki/Upgrading_To_Forge_for_1.3.1#Ticking. second one is a server tick handler and that's I believe what you wanted ;).

Thanks. So now, between those two methods of setBlock, I've added something. Let's say var1 is the ClientTickHandler and var2 is the Common one. I have var1.onTickInGame(); there. What would make the system wait 10 ticks?

EntityHerobrine.setDead();

 

Pwned.

Posted

that would be some kind of basic java logic which you write, which you can learn if you go study some programming basics ;)

<3

 

What if you had some variable that tracked the number of times it has ticked and when it has ticket x times it would do Y and reset the tracker to it's default value?

If you guys dont get it.. then well ya.. try harder...

Posted

that would be some kind of basic java logic which you write, which you can learn if you go study some programming basics ;)

<3

 

What if you had some variable that tracked the number of times it has ticked and when it has ticket x times it would do Y and reset the tracker to it's default value?

Now you're the one confused. Do you understand what I want to happen? Nothing will happen until I right click with this item. When that happens, the onItemUse method is called, doing many World.setBlock() command around me to make fire in that area. 10 ticks later, in that same method of onItemUse, it will call World.setBlock() but instead fill all those areas with air. But the problem is I do not understand what method I can use for that. And if the basic java stuff you're talking about is wait() or Thread.*(), those are wrong because those crash/lag the whole system and end up not replacing the fire with air.

EntityHerobrine.setDead();

 

Pwned.

Posted
... When that happens, the onItemUse method is called, doing many World.setBlock() command around me to make fire in that area. 10 ticks later, in that same method of onItemUse, it will call World.setBlock() but instead fill all those areas with air. But the problem is I do not understand what method I can use for that.

 

You cannot (unless using some crazy hacky stuff) "go back into same method", there are no super easy magical waiting methods which automaticly fork program execution into two ways and at a same time not break the game. But (as I said above) you can use similar approach as event list has. You'll mark into a calendar that in 10 ticks from now it should do something = remove fire. In tick handler you every tick move to a next item in a calendar and look if anything is planned to happen (like extinguish those 30 fires). The upside of this solution is that you don't every tick decrease counters of all events that are planned to happen (like extinguishing all 30 fire blocks).

 

I know my English is far from perfect. I'm sorry, I don't think I can describe it more clearly...

mnn.getNativeLang() != English

If I helped you please click on the "thank you" button.

Posted

Okay, I'll tell you, I'm not very good at coding. In fact, I'm quite a noob, my first mod only having ores and tools/swords. I'm also new to ForgeModLoader and I don't understand in the slightest how any of these classes work, like my CommonTickHandler or my ClientTickHandler.

I just want a straightforward explanation of how I can use TickHandlers to make it wait for the fire to be replaced by air.

EntityHerobrine.setDead();

 

Pwned.

Posted

I don't know if 100 % this would work but it should from what i can tell so in your onItemUse() do this

 

public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
{
par3World.setBlock(par4, par5 + 1, par6, Block.fire.blockID);
didRightClick = true;
ClientTickHandler.fireTick = 0;
if(ClientTickHandler.setAir == true)
{
	par3World.setBlock(par4, par5 + 1, par6, Block.blocksList[0].blockID);
}
return false;

}

also add these in your item class

public static boolean didRightClick = false;

 

then in you ClientTickHandler use this method

 

public void onTickInGame()
{
if(YourItemClass.didRightClick == true)
{
 fireTick ++;
}
if(fireTick == 10)
{
 setAir = true;
 fireTick = 0;
}
}

 

then add these in your ClientTickHandler

public static int fireTick = 0;
public static boolean setAir = false;

 

something i noticed is you said you wanted it for 10 ticks and i think you mean seconds because 20 ticks is 1 second so if you want 10 seconds do this

public void onTickInGame()
{
if(YourItemClass.didRightClick == true)
{
 fireTick ++;
}
if(fireTick == 200)
{
 setAir = true;
 fireTick = 0;
}
}

Posted

@Jdb100: That will not work, because the onItemUse will not be called again when the tick handler has counted down.

Mm... that makes sense. But how would I make it call it again? If that is possible, of course, which it looks like it's not.

EntityHerobrine.setDead();

 

Pwned.

Posted

You need some kind of "Queue" of things to do in your TickHandler. Every tick check if the any event is ready, if so, perform it.

So would this be something appropriate for onTickInGame() ?

And, as I said before, I am not very good at this stuff. But this is the only obstacle I'm hitting with a struggle.

EntityHerobrine.setDead();

 

Pwned.

Posted

ok sorry about my stupid mistake all you have to do is edit your tick handler to add thistem

 

public void onTickInGame()
{
if(YourItemClass.didRightClick == true)
{
 fireTick ++;
}
if(fireTick == 10)
{
 fireTick = 0;
         YourItemClass.setAir();
         didRightClick = false;
}
}

 

then add this to your item

 

public void setAir(World par1World)
{
 par1World.setBlock(x, y + 1, z, Block.blocksList[0].blockID);
}

 

then change your onItemUse to this

 

public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
{
par3World.setBlock(par4, par5 + 1, par6, Block.fire.blockID);
        x = par4;
        y = par5;
        z = par6;
didRightClick = true;
ClientTickHandler.fireTick = 0;
return false;

}

 

make sure to add these to your item class

 

public int x;
public int y;
public int z;

Posted

ok sorry about my stupid mistake all you have to do is edit your tick handler to add thistem

 

public void onTickInGame()
{
if(YourItemClass.didRightClick == true)
{
 fireTick ++;
}
if(fireTick == 10)
{
 fireTick = 0;
         YourItemClass.setAir();
         didRightClick = false;
}
}

 

then add this to your item

 

public void setAir(World par1World)
{
 par1World.setBlock(x, y + 1, z, Block.blocksList[0].blockID);
}

 

then change your onItemUse to this

 

public boolean onItemUse(ItemStack par1ItemStack, EntityPlayer par2EntityPlayer, World par3World, int par4, int par5, int par6, int par7, float par8, float par9, float par10)
{
par3World.setBlock(par4, par5 + 1, par6, Block.fire.blockID);
        x = par4;
        y = par5;
        z = par6;
didRightClick = true;
ClientTickHandler.fireTick = 0;
return false;

}

 

make sure to add these to your item class

 

public int x;
public int y;
public int z;

Do I really need to define that par4 is x, par5 is y, and par6 is z? I'm pretty sure that onItemUse already knows that, as I have overridden that.

EntityHerobrine.setDead();

 

Pwned.

Posted

@Jdb100: same problem as before: only works for a single use.

Okay, you were helpful before, but now you are kind of getting in the way :(

I really just want to know what I would do, not what I can't. I understand how his wouldn't work kinda, but what do you mean only a single use? The item is a single use item.

EntityHerobrine.setDead();

 

Pwned.

Posted

The problem is that there is only one instance of your block. So if you change something on that instance, it changes for every Block of that type in the world.

You need to have a Queue in your TickHandler (probably a List or, thinking of it, actually a Set). Then store information about when which block was clicked in that Queue. Each tick look if any of the Elements in the Queue have expired (n ticks have passed) and if so, place air at their position.

So how am I supposed to list all my 30 or so fire blocks in the List<> thing?

EntityHerobrine.setDead();

 

Pwned.

Posted

You said you want to replace the blocks in a 5 block radius. So just store the x, y, z coordinate and then you can just search for fire in a 5 block radius.

Oh... that makes a lot more sense than what I was thinking of...

I thought I could store what all my 30 or so lines said. But after I've stored it, how can I replace all of them with air in 10 ticks? (Also, I do mean 10 ticks, or 1/2 a second.)

Edit: Also, how can I store all three co-ords at once? The Set.add() method only likes to have one object.

EntityHerobrine.setDead();

 

Pwned.

Posted

Attach an int lets call it tickCounter to the elements you store in the list. Every tick increment all of them, and if one of them reaches 10 then 10 ticks have passed for that element (=> process it, then remove it from the queue).

So something like this?

public boolean blockWait(Set<Object> s, Object obj){
	//s.add methods here
	return true;
	if(tickCounter == 0){
		tickCounter ++;
	}
	if(tickCounter >= 10){
		s.clear();
	}
}

This is in ItemFirePowder.

Also:

Edit: Also, how can I store all three co-ords at once? The Set.add() method only likes to have one object.

EntityHerobrine.setDead();

 

Pwned.

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



×
×
  • Create New...

Important Information

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