Lemur/SimTools Patch-stravaganza


#64

…ie11… thinking thinking… oh, yeah… the Firefox downloader. :slight_smile:


#65

I think I’m a bit late to the party, but would it be possible to add setters for the consumeDrags and consumeDrops booleans in the DragHandler cursor listener?
I now use a cloned version of this because I need to consume the drop event…

edit: If needed I can create an issue / PR on github for this, don’t know what you prefer.


#66

Sure. That’d be the best way.


#67

here you go:


#68

First, a big thank you for these shiny new libs, @pspeed!

Second: I’ve got a problem with the 1.3.0 version of sim-ethereal regarding the time source. The RemoteTimeSource on the client gives me very big values for getTime(), which look roughly like the nanoTime(). The frame times I get in my SharedObjectListener look like time from server startup, though.
I used etherealClient.getTimeSource().getTime(); to interpolate the positions before (in v1.2.1), but now it isn’t working, as the time is far outside the range of my buffer, that uses the ethereal frame time.

I’ve already applied the patch you posted above for the use of SiO2 and ethereal, and I didn’t found a place where I use the nanoTime directly on the server, only the time since server startup.

Is this a bug, or did I miss something?


#69

Sorry you are having trouble.

I have trouble believing this. If the patch above is applied then SimEthereal will produce times consistent with what SiO2 is producing.

Can you paste the code block where you’ve added this bit:

        ethereal.setTimeSource(new TimeSource() {
                @Override
                public long getTime() {
                    return systems.getStepTime().getUnlockedTime(System.nanoTime());
                }
            });       

I think maybe it wasn’t applied correctly.

Of course, this is presuming that you are using SiO2’s time in your physics object reporting.

What happens if you don’t apply the patch?


#70

I found the issue, and you are right, the error was on my side.
I extended the GameSystemManager to implement a fixed timestep gameloop. In the new SiO2 version the TimeStep gets initialized on the first frame, and I made a mistake migrating my code to that new design, so I basically broke the TimeStep.
Thanks for your help and sorry for wasting your time.


#71

No worries. Glad you got it working.

I always take risks when I change something fundamental like “time tracking”… but I felt it was in the end the best decision since problems related to this were actually real bugs in other code.


#72

Been playing around with this Viewport stuff and its dam awesome. I don’t think I would of figured this out on my own.

Drag and drop and mouse events all work now. Haven’t rewrote the whole thing with FilterPostProcessor and rotations yet but what’s happening with testing things so far is sweet.

Thank you.


#73

A small bump concerning the PR.
Do you have any idea when we can expect an update or new release of Lemur?

thanks for your awesome work!


#74

I hadn’t really thought about it to be honest. I guess I could do this again soon. I think there is at least one thing I want to fix in Lemur before the next push, though.


#75

Also please release a new version for LemurProps, last release was in 2015.

This is missing in latest release :


#76

btw, @pspeed it seems you forgot to add a addDoubleField() you only added addDoubleProperty().
I made a patch for it


#77

Just released SimMath 1.3.0.

I plan to start slow-rolling some new releases of the various packages over the next week or so. SimMath was the lowest tier dependency of a bunch of other things and I needed to do it before releasing a new SimEthereal.

Change log:

  • Added Quatd.fromAngles(double[])
  • Added Quatd.equals() and Quatd.hashCode()
  • Added Vec3d.isSimilar() and Quatd.isSimilar() that allow for
    comparison of values within some epsilon.
  • Converted a System.out.println() in Vec3Bits to a log.debug() call.
  • Added Vec3d.interpolateLocal().
  • Added Quatd.slerpLocal().
  • Added PositionTransition3f and PositionTransition3d.
  • Deprecated PositionTransition in favor of PositionTransition3f or
    PositionTransition3d.
  • Deprecated PositionTransition.getFrameVelocity() and did not port it
    to PositionTransition3f or PositionTransition3d.

#78

Just released SimEthereal 1.4.0

…on to Zay-ES.

Change log:

  • Fixed zone ID calculation for non-uniform grids. See PR #2.
  • Modified ZoneManager to automatically send “no-change” updates for
    objects it is managing but didn’t receive updates for. See PR #5
    (Note: this could seem like a ‘breaking change’ to any apps relying
    on objects to auto-expire in this way… just know that doing so was
    leaving extra garbage around and so not really a solution.)
  • Added a thread-safe BufferedHashSet for creating “one writer, many readers”
    fast thread safe hash sets.
  • Added a double-buffered thread safe active IDs set to the NetworkStateListener.
  • Added an error log message when updating an object with a bounds bigger than
    supported by the current grid settings.

#79

Just released Zay-ES core 1.3.1 and Zay-ES Net 1.4.0.

Core change log:

  • Fixed MemStringIndex.getStringId(string, false) to return -1 instead of throwing
    an NPE if the string has no ID.
  • Modified DefaultEntityData.addEntityComponentListener() to throw an IllegalArgumentException
    for null listeners.

Zay-ES Net changelog:

  • Fixed HostedEntityData.getStringInfo() to send back a null if the ID doesn’t exist
    for the string rather than sending back -1. A -1 would have been cached but a
    null won’t be.
  • Added EntityDataHostedServer.getHostedEntityData() for setting up connection
    specific entity stuff from other services.
  • Added support for client-specific ComponentVisibility filters that can be used to
    limit the clients’ views of certain component values, e.g.: based on permissions,
    local object visibility, etc…
  • Added lots of additional trace logging in support of the above.
  • Fixed HostedEntityData.getEntitySet() to force the next sendUpdates() to make
    at least one pass through the entity sets. Else some components won’t be
    properly tracked.

#80

Lemur 1.12.0 released.

Change log:

  • Fixed a bug in the new getPickRay() code where incorrect Rays were being
    created if the Gui Bucket didn’t have a spatial at z=0.
  • Modified how TextEntryComponent calculates its cursor width to avoid cases
    where cursors weren’t being drawn because of sub-pixel widths at certain
    screen locations.
  • Added a TextField.setPreferredCursorWidth() styleable attribute that can be
    used to change the default cursor width for text fields.
  • Modified DynamicInsetsComponent to treat the insets values as percentages
    instead of always making them sum to 1. (That behavior still happens if
    the total of min+max is more than 1.) This modification lets dynamic
    insets support dynamic stretching instead of just positioning.
    This is potentially a breaking change for code relying on the old
    normalization. (though that was kind of weird)
  • Fixed pick session bug caused by empty GUI nodes. (added a null check)
  • Added Button.EFFECT_ENABLE and Button.EFFECT_DISABLE constants and modified
    Button to call the appropriate effect chain during setEnabled(true/false).
  • Added Button.ButtonAction.Enabled and Button.ButtonAction.Disabled and
    modified Button to call the appropriate command chain during
    setEnabled(true/false).

Also, I released a new LemurProps that just adds double field/property support. (Version 1.1.0)


#81

Thanks for the new release

Can you provide an example code for using this feature, please ?


#82

SiO2 1.3.0 has been released.

Change log:

  • Upped the Zay-ES-net version to 1.4.0 to get the entity set filtering
    bug fix.
  • CompositeAppState modified to use SafeArrayList.getArray() in for loops.
  • Modified GameLoop’s default frame interval constant to be public: GameLoop.FPS_60
  • Added a GameSystemsState utility for managing a GameSystemManager in
    single player games.
  • Added a MemoryDebugState utility that displays memory stats using the DebugHudState.
  • Upped Lemur and Zay-ES/Zay-ES-Net dependencies to latest versions (1.12.0 and 1.3.1/1.4.0 respectively.)

#83

What would the fun be in that? :wink:

I use it to filter BodyPosition by what SimEthereal actually says is visible for that client. For MOSS patrons, this is available in the net-demo app… but I’ll paste it here sort of out of context:

/*
 * $Id$
 * 
 * Copyright (c) 2018, Simsilica, LLC
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions 
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright 
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Redistributions in binary form must reproduce the above copyright 
 *    notice, this list of conditions and the following disclaimer in 
 *    the documentation and/or other materials provided with the 
 *    distribution.
 * 
 * 3. Neither the name of the copyright holder nor the names of its 
 *    contributors may be used to endorse or promote products derived 
 *    from this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.simsilica.demo.server;

import java.util.*;

import org.slf4j.*;

import com.simsilica.es.*;
import com.simsilica.es.server.ComponentVisibility;
import com.simsilica.ethereal.NetworkStateListener;

import com.simsilica.demo.es.BodyPosition;

/**
 *  Limits the client's visibility of any entity containing a BodyPosition
 *  to just what the SimEthereal visibility says they can see.
 *
 *  @author    Paul Speed
 */
public class BodyVisibility implements ComponentVisibility {

    static Logger log = LoggerFactory.getLogger(BodyVisibility.class);

    private NetworkStateListener netState;
    private EntityData ed;

    private Set<Long> lastActiveIds;

    private Map<EntityId, BodyPosition> lastValues = new HashMap<>(); 

    protected BodyVisibility( NetworkStateListener netState, Set<Long> lastActiveIds ) {
        this.netState = netState;
        this.lastActiveIds = lastActiveIds;
    } 
    
    public BodyVisibility( NetworkStateListener netState ) {
        this(netState, null);
    }

    @Override
    public Class<? extends EntityComponent> getComponentType() {
        return BodyPosition.class;
    }
    
    @Override
    public void initialize( EntityData ed ) {
        this.ed = ed;
    }

    @Override
    public <T extends EntityComponent> T getComponent( EntityId entityId, Class<T> type ) {
log.info("getComponent(" + entityId + ", " + type + ")");    
        //if( !netState.getActiveIds().contains(entityId) ) {
        //    return null;
        //}
        if( !lastValues.containsKey(entityId) ) {
            return null;
        }
        return ed.getComponent(entityId, type);
    }

    @Override
    public Set<EntityId> getEntityIds( ComponentFilter filter ) {
        if( log.isTraceEnabled() ) {
            log.trace("getEntityIds(" + filter + ")");
        }    
        if( filter != null ) {
            throw new UnsupportedOperationException("Filtering + body visibility not yet supported");
        }

        /*Set<Long> active = netState.getActiveIds();
        log.info("active:" + active);
 
        Set<EntityId> results = new HashSet<>();
        for( Long l : active ) {
            results.add(new EntityId(l));
        }
    
        return results;*/
        return lastValues.keySet();    
    }

    public boolean collectChanges( Queue<EntityChange> updates ) {
        Set<Long> active = netState.getActiveIds();
        boolean changed = false;
        if( log.isTraceEnabled() ) {
            log.trace("active:" + active);
            log.info("updates before:" + updates);
        }
 
        // Remove any BodyPosition updates that don't belong to the active
        // set
        for( Iterator<EntityChange> it = updates.iterator(); it.hasNext(); ) {
            EntityChange change = it.next();
            if( change.getComponentType() == BodyPosition.class 
                && !active.contains(change.getEntityId().getId()) ) {
                if( log.isTraceEnabled() ) {
                    log.trace("removing irrelevant change:" + change);
                }                
                it.remove();
            }
        }        
        
        // First process the removals
        for( Iterator<EntityId> it = lastValues.keySet().iterator(); it.hasNext(); ) {
            EntityId id = it.next();
            if( active.contains(id.getId()) ) {
                continue;
            }
            if( log.isTraceEnabled() ) {
                log.trace("removing:" + id);
            }
            updates.add(new EntityChange(id, BodyPosition.class));
            it.remove();
            changed = true;
        }
        
        // Now the adds
        for( Long l : active ) {
            EntityId id = new EntityId(l);
            if( lastValues.containsKey(id) ) {
                continue;
            }
            if( log.isTraceEnabled() ) {
                log.trace("adding:" + id);
            }
            BodyPosition pos = ed.getComponent(id, BodyPosition.class);
            lastValues.put(id, pos);
            updates.add(new EntityChange(id, pos)); 
            changed = true;
        }

if( changed ) {
    log.info("done collectChanges() " + active);
} 
        
        return changed;
    }
}

Edit: Note that the class is a work in progress so has some things it doesn’t even use, etc.