SimEthereal zone issue when warping to location

@pspeed I am running an old version of SimEthereal (1.3.0) and experience strange behavior in a use case. I was wondering if I am doing something wrong or if it’s an old bug that you fixed.

Here is the use case:
Grid Size of 100.
Zone Radius of 1,1,1
Camera is within Zone 0,0,0 (all entities in the zone are visible)
Camera moves through the scene to zone 0,2,0 (all entities in zone 0,0,0 disappear as expected)
Now as I warp (explicitly set the player location) inside zone 0,0,0 the entities in 0,0,0 do not appear until I leave the zone and move back into it.

I am either doing something dumb in my code or something wonky is happening to zone management.

Maybe you have to let the NetworkStateListener know your position ?

But this is entirely down to the filter you set on the view-side right? Is the filtering set correctly after you explicitly warp ?

I do that in all cases that’s why moving through the zones without warping works.

What is this view side filter that you speak off? Ethereal takes care of removing and adding entities to the scene based on your player position.

Well, you can define your own filters on EntityContainers and one such filter could be based on the Zones you move through, applying that to the CelllId field of the BodyPosition component.

This is for example what I had in my ModelViewState in a previous build - haven’t gotten around to refactoring it yet, so not sure if it still works in my new build:

    if (playerSpatial != null) {
        Vec3d newPlayerPosition = new Vec3d(playerSpatial.getWorldTranslation());
        if (newPlayerPosition != oldPlayerPosition) {
            ZoneKey newKey = ServerGameConstants.ZONE_GRID.worldToKey(newPlayerPosition);
            long newPlayerCellId = newKey.toLongId();
            if (newPlayerCellId != oldPlayerCellId || !playerCellIdInitialized) {

                List<ZoneKey> entered = new ArrayList<>();
                List<ZoneKey> exited = new ArrayList<>();
                zones.setCenter(newKey, entered, exited);

                inZones.addAll(entered);
                inZones.removeAll(exited);

                OrFilter zoneFilter = generateZoneFilter(inZones);

                models.updateFilter(zoneFilter);

                oldPlayerCellId = newPlayerCellId;

                playerCellIdInitialized = true;

            }
            oldPlayerPosition = newPlayerPosition;
        }
    } 

But I do remember having issues with teleporting as well. Dont think I ever got around to fixing it.

It might be related to this issue which someone put in the wrong project: zay-es-net: Moving entities out of the current radius · Issue #15 · jMonkeyEngine-Contributions/zay-es · GitHub

It sounds like there is a problem with warping but I haven’t had a chance to create my own test that does warping (and my normal games don’t have warping yet).

I’ve looked at the code before and I couldn’t see any obvious reasons why skipping zones would be any different than moving through adjacent ones… but I also haven’t seen any examples of how folks are warping.

Regarding the teleport here is my workaround

        teleportationContainer.update();
        for (ToMove toMove : teleportationContainer.getArray()) {
            if (!toMove.move()) {
                toMove.remove();
            }
        }

Looks ugly but works for my use case

 private class ToMove {

        private static final float MOVE_SIZE = 25;//iteration 

        public float dist;
        public Vector3f dir;
        public EntityId entityId;

        private float iteration = MOVE_SIZE;

        public ToMove(float dist, Vector3f dir, EntityId entityId) {
            this.dist = dist;
            this.dir = dir;
            this.entityId = entityId;
        }

        public boolean move() {

            //fail safe
            if (iteration < MOVE_SIZE) {
                return false;
            }

            EntityRigidBody body = physics.getRigidBody(entityId);

            body.setPhysicsLocation(body.getPhysicsLocation().add(dir.mult(MOVE_SIZE)));

            if ((iteration + MOVE_SIZE) < dist) {
                iteration += MOVE_SIZE;
            } else {
                iteration = dist - iteration;
                body.setPhysicsLocation(body.getPhysicsLocation().add(dir.mult(iteration)));
                return false;
            }

            return true;
        }

        public void remove() {
            ed.removeComponent(entityId, Relocate.class);
        }

    }

@pspeed I just explicitly set the new location of the player. I will debug further when I get the chance.

What I find interesting is some of the responses in this thread. People are adding and removing entities manually from zone to zone … I guess some people have no idea of the power of ethereal and are reinventing the wheel lol

Well, there are so far two work arounds to the teleporting issue. One is to remove the object and readd it in the new location. The other is to rapidly move to where you want to be. I think both solutions are represented here.

Without sample code, I manually traced through the ZoneManager.updateEntity() code to see where things might go amiss if the zones change too large and I couldn’t see anything that would go amiss. Even the resetting of the local zone index seems to be correct… but that would be the most obvious thing that could go wrong.

However, 1.3.0 is quite old at this point and depending on how one is actually warping the player entity maybe they could be affecting things. A couple of major bug fixes in 1.4 and 1.5.

…and I’m working on a 1.6 with parent/child support finally implemented.

1 Like

I will be moving to the latest build this weekend. I will see if it helps. For me, the “ship” is my camera and I just “warp” the camera position to a saved shortcut in the scene … the scene is a massive galaxy so you can imagine how far the warps can be.

I mean, from SimEthereal’s perspective, warping should look like:

frame n: ZoneManager.updateEntity( somePosition )
frame n+1: ZoneManager.updateEntity( some Position far away from that)

Nothing in the code I saw seems to care whether the new zone is one zone over or 90 zones over… but I haven’t tried it.

But for example, locally I was just force setting the camera position all the time using NetworkStateListener.setSelf() with a new location… but that won’t work for zone changes because it bypasses the normal update paths. (Edit: I mean when I did this locally I saw tons of zone update problems until I moved my position setting down into the physics code.)

The only way to properly “warp” a player entity is to move the physics object/entity itself and let ZoneManager.updateEntity() move it… with setSelf() only having been called once for that entity during setup.

This sounds promising :slight_smile: