Terasology: Items are not being destroyed when dropped into lava

Created on 27 Apr 2015  ยท  44Comments  ยท  Source: MovingBlocks/Terasology

Content Good First Issue

Most helpful comment

@AlexDr7 no problem at all :)
If y'all have any more questions, feel free to ask here or on IRC ( people will help if they can and have the time there as well ). I'll be lurking around and answering as quickly as I can seeing as I get e-mail notifications for any update here :P

All 44 comments

@Cervator I'm one of the Porto students and at this point (speaking on behalf of my group) I would like to contribute (at least try) correcting some kind of bug, this one seems to be feasible, but I would like if posible to get some more information about the packages related to this bug in order to easily find the target area of the bug issue

Heya @sergiomieic - sure :-)

So this would be a new feature, and actually an optional one you could choose to enable by activating a module containing the functionality. It shouldn't be an engine feature at this point. It isn't actually a bug, it simply was never implemented in the first place.

A similar existing module is Breathing: https://github.com/Terasology/Breathing

Take a look at that module (use gradlew fetchModuleBreathing to add it to an existing workspace) and see how it determines how the player enters and exits water to trigger "holding your breath" or eventually suffocating. You'd likely be looking at doing something similar for players/items that enter lava.

Very similar would be something like having a player or creature take damage when you get too close to a cactus. You probably would want an ability to mark blocks as causing damage in some fashion. The breathing system was designed to eventually do that as well, but may be hard coded to water at present.

Really, a human entering water might be unable to breathe, but an amphibian would be okay. Both would be burned in lava _and_ suffocate at the same time. Imagine having a potion making you immune to fire damage - now you wouldn't burn in lava, but you'd still be unable to breathe.

A good first step: Post a suggestion thread at http://forum.terasology.org/forum/suggestions.21/ and we'll talk more design there first. Talk among yourselves on how you would enable a many-to-many system where players/creatures/items could take damage from any special blocks defined as being hurtful to them or a category in general.

Start simple, then build on it. And while you're at it maybe see if you can enhance Breathing in the same way as they're conceptually similar. Different players/creatures would potentially have to hold their breath in different kinds of situations. Water, vacuum, a tar pit, etc. Maybe a tar monster can breathe fine in a tar pit while a player (or fish) cannot :-)

I am also noticing the bubble icons in Breathing are broken. You hold your breath and the breath meter goes down but the icons are messed up. That could be the first quick bug to fix right there!

I can get you access to the Breathing module if you would like to work on it, and/or create a new one for blocks that'll hurt you, like lava. Maybe we can call it "HurtfulBlocks" :D

Thanks for the great reply @Cervator :D
It was kind of misunderstanding thinking that this issue was a bug despite not having the "bug" label. Don't be disappointed but atm our subject's stage goal is really to find a bug -> reproduce it using unit testing -> fixing it. In the next stage we'll probably try developing new features such as the ones you mentioned relatively to the Breathing mod for example

Righto :-)

I submitted https://github.com/Terasology/Breathing/issues/4 for the breathing bar icon issue. That's probably easy to fix, although probably not too unit testable since it is an icon problem

Some ideas: #1690, #1619, #1375, #1026, #715

A lot of issues these days are beyond the engine, which is fairly stable. Most remaining issues are either fairly complex and relate to multiplayer and/or the entity system, or are graphics type bugs, which can be hard to unit test for.

Non-bugs that could be interesting and maybe support unit testing: #1680, #1661, #1608,

I already have seen 2 of those issues, I'ill see the other ones you suggested and do my best. Thanks again :+1:

Just to get a bit of a status added to this issue we now have the https://github.com/Terasology/DamagingBlocks module :-)

This'll hurt a player who enters lava. I wonder if we have an item version of the event that suggests a player has entered a block.

Hello , me and a friend of mine (Alexdr7) would like to try and solve this issue as a project for a class in our university if it's still unsolved. We also contacted some of you guys through IRC and were recommended to check the Contributor - friendly issues. We both have about 4 yeas experience in java so I think we are up to the task!

Hi @theodddore ! Sorry for missing your comment for a bit. Did you catch anybody else on IRC since last?

You can definitely try to solve this issue, as you can see above there has been some related work on triggering damage for a player entering lava. Probably take a look at that for some initial ideas :-)

Hello @Cervator sorry for taking so much time to answer, me and @AlexDr7 checked the above comments on the issue and took some time to check the breathing module. However we are not quite sure, how to implement a new module, is there some repository to fork were we should contribute, or should we create one somehow?

Hey @theodddore good to hear from you again :-)

The wiki explains it pretty well: https://github.com/MovingBlocks/Terasology/wiki/Developing-Modules - there are a few related pages too.

Probably it would make sense to enhance the DamagingBlocks module further (Breathing is more of a related example). In that case you could simply run the following in an existing Terasology workspace:

  • gradlew fetchModuleDamagingBlocks
  • gradlew idea

Check out the code and how it works, play around with changing it a bit, and see how you might affect items as well as players (it should be fairly similar since both are entities)

If you have some code you want others to see you could then fork DamagingBlocks, add it as a remote to your modules/DamagingBlocks Git root, and push the changes to GitHub. Then we can either use a pull request to merge it or if you'd like to hang out and help for a longer period we just give you write access to that module repo :-)

Hello @Cervator :)
Thank you very much for the quick response , we will study the code and the wiki as soon as possible! I would also like to ask you, do you test the code with any tool like per say JUnit testing etc? I will keep in touch and inform you of our progress and of any difficulties we face!
Thank you very much for the help! :D

@theodddore yep we have a bunch of JUnit tests both in the engine and in some of the modules. Adding more is always appreciated but often gets left for last if at all, alas :-)

Hello @Cervator ,
I've been studying the code of DamagingBlocks mode and I have noticed that the DamagingBlocks component isn't added to lava on the creation of the entity.
Rather it is added when the player enters the block and then if the block is lava then the component is added, shouldn't this be better done on creation of the entity time? So I was thinking of firstly fixing that ,if it's better the way I decribed it. Here's the code as it stands right now to better illustrate the thought I had:

//code when receiving OnEnterBlockEvent.
if (blockIsDamaging(event.getNewBlock())) {
    DamagingBlockComponent damaging =
        entity.getComponent(DamagingBlockComponent.class);
    if (damaging == null) {
         damaging = new DamagingBlockComponent();
         damaging.nextDamageTime = time.getGameTimeInMs();
         entity.addComponent(damaging);
     } else {
         damaging.nextDamageTime = time.getGameTimeInMs() + damaging.timeBetweenDamage;
         entity.saveComponent(damaging);
}
//More Code

private boolean blockIsDamaging(Block block) {
     return block.isLava();
}


Regarding the items not getting destroyed, as of now the main problem I face is that I cannot find an event like the on OnEnterBlockEvent that applies to blocks or items. Moreover I'm not really sure what by the term item you mean, do you mean entities with the ItemComponent or something else?

Hey @theodddore sorry for missing this the first time around and taking a while to reply :-)

Switching the Component activation around sounds fine to me if it works (and does something better).

As for detecting items it may well be we don't have an event for that yet. May need to examine the engine when it comes to item entities moving around, and yep, I would think that means any entity with an ItemComponent (and something that places it in the world like LocationComponent). So it is possible we need the engine first throwing events for items in addition to the player. That could surely lead to other fun possibilities like throwing items at buttons or traps :-)

Hello @Cervator :)

perfect, I saw the HungerThirst module which had an activation on spawn that's why I asked about that. Now conserning the event for ItemComponents I took a look in the DropItemEvent.java and it
has the following method:

public Vector3f getPosition() {
        return position;
}

so maybe we could use something like that when an item falls. However the problem was that when I tried using the WorldProvider and the method Block getBlock(Vector3i pos); the Vectors are different and I understood that since there's a method byte getLight(Vector3f pos); that the Vector3f has something to do with lighting and not with positioning of an object. So should I try to change a bit the DropItemEvent.java and add a get method for a Vector3f? Or does this make no sense and I should better create a new Event for the items dropping?

Just to say my initial thought was that when an item is dropped I get the position it dropped and check if it's dropped in an item which is lava or a DamagingComponent, in which case we destroy it.

Thanks for the help! :)

Honestly I have to bring in the experts at this point, and maybe suggest moving to IRC or Slack as it would likely take some back and forth to figure out the details, which would take a while with just the two of us pinging this issue once or twice a day :D

@flo and @Josharias are good at this kind of stuff, @portokaliu is becoming quite proficient as well and @SkySom has had lots of fun dropping items. Maybe we can enhance the system to allow dropping items more utility, like interacting with all kinds of dropped surfaces. @portokaliu already got it working to where throwing a torch against a wall would actually attach a regular "block" torch in its stead. Could be fun to throw a train cart at some rails and have it snap onto the tracks as a full object :-)

Yes. Eventually... Throwing carts at rails. I like it.

My take on this would be that it's a bit different from what I did, seeing as I'm throwing items with special components so they can detect ground ( where items have a small lifespan ) while lava is part of the world and can be permanently in a location and shouldn't interact with anything but items ( at least for the purpose of this issue :D ). If we could have a special collision group for lava (maybe we already do), this might be easier than I'd first assume. Otherwise, a special component on "burnable" items, checking for collision to send destroyed events would be a course of action.

Also, snapping carts to rails after throwing them : totally doable.

Hello @portokaliu,
sorry for taking so long to answer, I was bit overloaded with assigments this week, conserning the burnable items , this can be implemented in the DamagingBlocks module I think. However surely it could be a lot better to be added in the main engine of the game using the collision group you mentioned. Is there anytime we can talk throught the IRC or throught messages to guide me a bit throught the code, so I can start developing the feature?

Hey @theodddore ,
No probs; I had enough work to delay my thread completion. I still have to get around to that :)

About the code, the reason items don't do this already is most likely performance issues. We don't want a lot of cluttering messages, so only the minimum necessary was implemented. In my case I use it for items with specific components. Still trying to do it in its own module, how it should be.

In your case, I don't think lava destroying items should be a default; Doing so in the DamagingBlocks module would be the end-goal.

I might be busy until way past midnight tday, but I'll be online on IRC tomorrow most of the time

Ok @portokaliu ! Thanks for the help and the fast response, I'll probalby be online too tomorrow so we'll talk throught IRC, thanks again :)

Heyo @theodddore , how's the issue going along? Encountered any interesting problems? :)

Hello @portokaliu well actually we've bumped in a problem , actually I have created this component:

@ForceBlockActive
public class BurnableItemComponent implements Component {

  @Replicate
  public CollisionGroup collisionGroup = StandardCollisionGroup.DEFAULT;

  @Replicate
  public List<CollisionGroup> collidesWith =
          Lists.<CollisionGroup>newArrayList(StandardCollisionGroup.LIQUID);

}

In hopes that this could trigger either the event CollidesEvent or CollisionEvent. However neither is triggered, I also added a TriggerComponent as well as a RigidBodyComponent in the items when they fall in addition to the BurnableItemComponent. However the events are not sent when I throw items into lava.
We also tried with @AlexDr7 to understand how events are send so that we could create on of our own, but we really struggle understanding when this happens. For example I understand that how the Systems handle events with the @ReceiveEvent method and how we can use components to filter the events and add various variables to the entities, however I cannot understand when do we sent events, I suspect this happens in the update method of the system, but still when I tried playing a bit with the PhysicsEngine and physics.getCollisionPairs(); I had various problems and crashes when starting the game. (I saw this code from PhysicsSystem.java)
What do you think about this, I feel we're in the right path but we just don't understand the sent() method part of the equation

Bellow the code that we have so far experimented with inside the DamagingBlocks module (in the DamagingSystem class for conviniance.)

    /**
     * droppedInLava is the method invoked when an item falls.
     * @param event .
     * @param entity .
     */
    @ReceiveEvent //(components = {ItemComponent.class})
    public void droppedInLava(DropItemEvent  event, EntityRef entity) {
        logger.info("dropping");

        Vector3f location = event.getPosition();


        TriggerComponent  trigger = new TriggerComponent();
        RigidBodyComponent rbc = new RigidBodyComponent();
        BurnableItemComponent brc = new BurnableItemComponent();
        entity.addComponent(rbc);
        entity.addComponent(trigger);
        entity.addComponent(brc);

        logger.info(entity.getComponent(LocationComponent.class).getLocalPosition().toString());
        logger.info(location.toString());


    }

    @ReceiveEvent
    public void onLavaEnter(CollisionEvent event, EntityRef entity) {

      logger.info("Colision!");


    }

Thanks for the interest and the help!! :)

Be sure to read the log as well. It can prove useful to know what the issue was if there was any.

Ok, I just tried it out from scratch (I lost the torch code, but the idea was there). I will leave the context of the code as well.

in the ItemPickupAuthoritySystem I added :

SpecialComponent specialComponent = new SpecialComponent();
itemEntity.addComponent(specialComponent);

and in Physics System :

if (body.isActive()) {
body.getLinearVelocity(comp.velocity);
body.getAngularVelocity(comp.angularVelocity);

            Vector3f location = Vector3f.zero();
            body.getLocation(location);
            HitResult hitResult = physics.rayTrace(location,comp.velocity.normalize(),0.2f, StandardCollisionGroup.LIQUID);
            if (hitResult.isHit() == true) {
                if (entity.hasComponent(SpecialComponent.class)) {
                    entity.send(new SpecialEvent());
                }
            }

Also in ItemPickupAuthoritySystem

@ReceiveEvent
public void onWhatever(SpecialEvent event, EntityRef entityRef, SpecialComponent specialComponent)
{
entityRef.removeComponent(SpecialComponent.class);
}

Note that SpecialComponent and SpecialEvent are completely empty. This worked for me at least. It's a crude implementation but it does the job. onWhatever triggers when hitting water with an item. Think it should work for lava as well

Collision Groups only return collision events when in contact with the player. There's more to it, but I'm not sure how to go about it (I'm relatively new to this too)

Also, @Josharias suggested this approach : https://github.com/Josharias/Terasology/commit/f4a72be5adad2f91487352939b12b59860bb57ed . I haven't tried it out yet, but I will when I can dedicate enough time for actual coding :)

@portokaliu that was extremely helpful , the SpecialEvent was exactly was we needed to understand the correct way to send events!
Thank you !!!!!

@AlexDr7 no problem at all :)
If y'all have any more questions, feel free to ask here or on IRC ( people will help if they can and have the time there as well ). I'll be lurking around and answering as quickly as I can seeing as I get e-mail notifications for any update here :P

Collisions with block entities don't work yet. I remember darkly that there was some issue with components being added one by one to the component which caused the created physics be created before all components got added to the entity

Oh and collisions between non character entities could work... @portokaliu maybe you tried it with block entities when it didn't work?

@flo The way I explained here it worked with block entities as well. Not sure how efficient/good it is, but it proves the concept. I haven't really tried item-item collision, but with the right collision group I think it should work in the way (at least for falling items; rolling or items being dragged might yield weird results).
A small improvement would be to replace the static 0.2 with the length(velocity)*delta for more accurate raycasts (pointing to the next position of the object)

I meant the CollideEvent

As far as I remember, CollideEvent only worked between items and the character. itemXitem didn't seem to do much (i remember stacking blocks on top of each other. Might've had issues with adding the triggerComponent then as well, so I'm not 100% sure)

Hey @portokaliu , we actually made it work the way we wanted (we faced some problems when destroying the items on the iterator , but we found a work around).

The only problem we still have is that the we want to put it all in a module , but because of the permissions we cant create a physicsEngine in a module. So we are looking of ways to rayTrace the items with whitelisted methods.

Do you have any idea how could we work around the physicsEngine permission?

Hey @AlexDr7

That's the point where I left off before I had to get studying for exams :) . I will be looking into the matter as well starting next saturday.

As far as I've researched, ye olde CombatBranch used the raytraces for arrows in a projectile system, so you could look into that for the moment. It's fairly old, but functional. If you need any help setting it up I'll be around here :D

I think the combat branch predates the module sandboxing system, so it might yield some physics-based inspiration but not much as far as security goes :-)

@AlexDr7: Do you have the working code available somewhere? Even if it is in engine or with security disabled, that's fine for review, I'm curious exactly which methods you're using. Physics only exposes a few methods, maybe we need to expose more. Did neither rayTrace method there cover your needs? Those do work in modules, as visible at:

https://github.com/Terasology/IRLCorp/blob/master/src/main/java/org/terasology/irlCorp/systems/MechanicalPowerToolAuthoritySystem.java#L76

Alternatively maybe we need the engine to be able to catch the sort of interaction between objects you're trying to hook into, triggering events you can handle rather than need to do physics yourself in a module. If there are other good use cases than simply destroying items going into lava that might be a nice thing to support in the engine.

Of course the working code is in this forked repo: https://github.com/theodddore/Terasology
The working code is in engine/src/main/java/org/terasology/logic/lavatest .

The problem we faced was sending the event when an item collided with a liquid. We used the physicsEngine in order to get the entities and check with rayTrace if they collide , exactly as Anthodeus showed us. Physics doesnt have any way to get the entities , nor the rigidbody. At least we didn't find any.

Please review our code first chance you get , it would be a great help for us.

Alright, I think I see what you did there, which is rare for me trying to understand something the first time :D

So you've essentially cloned PhysicsSystem.update() and tweaked it to capture liquid interactions. It does what you need, and it is great to see you got it to work!

It has me almost convinced that what we really need is to add a few key lines from your work to the existing update() in PhysicsSystem:

                    Vector3f location = Vector3f.zero();
                    body.getLocation(location);
                    HitResult hitResult = physics.rayTrace(location, comp.velocity.normalize(), 0.2f, StandardCollisionGroup.LIQUID);
                    if (hitResult.isHit() == true) {

Rather than get into the details of your functionality there, instead simply throw an OnEnterLiquidEvent, or OnItemEnterLiquidEvent, or something like that. Done. Usable by anybody who cares about liquid interactions.

Then in a module (probably DamagingBlocks) you should be able to catch that event normally, no need to access physics at all. Check for the right components and do your game logic. Done!

That avoids duplicate work in a secondary physics system (I suspect your code as-is would cause the physics system to go a little crazy doing physics.update more than once per game tick, for instance, not to mention network synchronization), opens the system up to other creative uses, and also avoids any kind of module sandbox issues.

Maybe there are other interesting physics interactions we should do more events for too. For instance I noticed the existing system merely caring about CollisionPairs doesn't seem to catch when one loose block bumps into another, which could have some fun potential. Imagine dropping a loose TNT block then dropping a loose lava block on top of it - BOOM!

Now naturally we'll run into performance issues fast if we go nuts, for instance in the previous example we probably can't check every single time two loose blocks bump into each other (imagine railgunning a mountain to create a temporary river of loose blocks rolling down it) - we need to find a good balance.

I noticed you have a unit test for the lava system (yay!) - maybe you could look into adding some minimal benchmark tests to see how different basic situations in the physics system perform, then start adding new cases and see what impact they have?

Poking @Josharias since he hasn't been in here yet. He was optimizing some physics stuff a little while back IIRC.

If we could add this functionality as default for the engine, making the combat module would be simpler than I've considered before. I need interactions for the arrows, and instead of making a separate system for them to work on (which would heavily strain the current physics I imagine), I could work off of the default.

A thing or two to add, and I'm not sure if this is a thing : if the raytrace could be just distance based, but it returns _ALL_ the items it encountered and return that with the help of an event, that would be the best possible way to do this I'd think. This way, we can interrogate the whole list whenever we're listening for the event, and pick the items that belong to whatever collision group we wish. (For example, something falling straight down into water with a longer raytrace would return all the air blocks to the water, the water and the blocks beneath the water for as far as the raytrace goes)

Another thing that would help not raytracing every item like in the case of the railgun, the items we want to do raytraces have a certain component attached to them. For example, in the default case of just throwing, add the component @ the throw and be done with it. Of course, this can be done for more types of "releasing" of items. Like, dispensers from mc or shooting arrows from a bow.

Besides the above, I would care to mention that raytracing for items that go really fast should also be in order, as it help with the tunneling issue. Maybe we can add a listener for a tunneling event and deal with that problem once and for all? Again, this comes to mind from what I remember while reading through @aherber 's forum stuff.

What you mentioned @Cervator with dropping tnt and lava blocks should work like this as well as long as we have a collision group for dropped items; even so, the issue would be the linearity of raytracing as far as I understand it. For example:

โ–“โ–“โ–“
โ–“โ–“โ–“
โ–‘โ†“
โ–‘โ–‘โ–“โ–“โ–“
โ–‘โ–‘โ–“โ–“โ–“

This wouldn't be an interaction as far as raytracing is concerned, even though their rigidbodies do touch.

Oh, one more thing, the raytrace length should be equivalent to the speed the item is moving at. Replacing the 0.2 with length(velocity)*delta should do it (I always forgot the delta, so I got mad and just considered 0.2 an ok value :D )

That's all I can think for now; I like imagining functionalities, so don't necessarily consider all of this possible without consulting the people under the hood :)

One more thing to add is that I found out raycast != raytrace != raymarch. From what sources I gathered raycasting would be the best use case for the issue at hand, while raymarching would prove inexact for several edge scenarios ( albeit most efficient! ), and raytracing sounded like the heaviest type by sending secondary rays with every hit (mostly used for rendering)

Would it be alright if we just checked for the center of the falling item/block is currently inside the lava (or whatever) blocks? This could be made relatively easily and wouldn't cost much in terms of performance (except checking for each item if the block they're in is damaging or not). Either that or the damaging block could be the one sending events every so often to items that are inside it (not sure how that would work for now, but I'll think of something :D )

Alright, I don't know how to do this properly apparently, but I added a PR on the module's side https://github.com/Terasology/DamagingBlocks/pull/1 . I'm not exactly sure how to make it seem linked to this one though.

PR in DamagingBlocks is now merged! Technically this issue is now complete :-)

I might drag this into Alpha 6 and close it, but suspect we have some loose threads to make follow-up issues or suggestion threads for.

Hi everybody!

This issue should be clear for closing.

CC: @Cervator

Closing as per Smsunarto and it being completed.

Was this page helpful?
0 / 5 - 0 ratings