{
"$type": "site.standard.document",
"bskyPostRef": {
"cid": "bafyreiflz7fwypri2map7nfoqlkhwufjcjk2eculby65ntsroxu3oi3fuq",
"uri": "at://did:plc:dxjzgxe7cvirxkwfjr2tjspt/app.bsky.feed.post/3mnq4zirmpdf2"
},
"path": "/t/zay-es-and-hidden-states/49615#post_4",
"publishedAt": "2026-06-07T20:45:56.000Z",
"site": "https://hub.jmonkeyengine.org",
"tags": [
"@author",
"@Override"
],
"textContent": "The reason I asked is because there is already a facility for filtering out entities by a particular component. That’s how Mythruna works. If the entity has a BodyPosition outside of the client’s visible zones, that client can’t see anything about it.\n\nThis uses the ComponentVisibility feature. I guess my bpos stuff is still in the unreleased MOSS libraries so I’ll paste the example here.\n\n\n /*\n * $Id$\n *\n * Copyright (c) 2021, Simsilica, LLC\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n *\n * 1. Redistributions of source code must retain the above copyright\n * notice, this list of conditions and the following disclaimer.\n *\n * 2. Redistributions in binary form must reproduce the above copyright\n * notice, this list of conditions and the following disclaimer in\n * the documentation and/or other materials provided with the\n * distribution.\n *\n * 3. Neither the name of the copyright holder nor the names of its\n * contributors may be used to endorse or promote products derived\n * from this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n * \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS\n * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE\n * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,\n * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\n * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)\n * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,\n * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED\n * OF THE POSSIBILITY OF SUCH DAMAGE.\n */\n\n package com.simsilica.bpos.net;\n\n import java.util.*;\n\n import org.slf4j.*;\n\n import com.simsilica.es.*;\n import com.simsilica.es.server.ComponentVisibility;\n import com.simsilica.ethereal.NetworkStateListener;\n\n import com.simsilica.bpos.BodyPosition;\n\n /**\n * Used on the server for a specific client connection to limit that client's\n * visibility of any entity containing a BodyPosition to just what the\n * SimEthereal visibility says they can see. This is usually added by a\n * server-side service during client initialization.\n *\n * @author Paul Speed\n */\n public class BodyVisibility implements ComponentVisibility {\n\n static Logger log = LoggerFactory.getLogger(BodyVisibility.class);\n\n private NetworkStateListener netState;\n private EntityData ed;\n\n private Set<Long> lastActiveIds;\n\n private Map<EntityId, BodyPosition> lastValues = new HashMap<>();\n\n protected BodyVisibility( NetworkStateListener netState, Set<Long> lastActiveIds ) {\n this.netState = netState;\n this.lastActiveIds = lastActiveIds;\n }\n\n public BodyVisibility( NetworkStateListener netState ) {\n this(netState, null);\n }\n\n @Override\n public Class<? extends EntityComponent> getComponentType() {\n return BodyPosition.class;\n }\n\n @Override\n public void initialize( EntityData ed ) {\n this.ed = ed;\n }\n\n @Override\n public <T extends EntityComponent> T getComponent( EntityId entityId, Class<T> type ) {\n if( log.isTraceEnabled() ) {\n log.trace(\"getComponent(\" + entityId + \", \" + type + \")\");\n }\n //if( !netState.getActiveIds().contains(entityId) ) {\n // return null;\n //}\n if( !lastValues.containsKey(entityId) ) {\n return null;\n }\n return ed.getComponent(entityId, type);\n }\n\n @Override\n public Set<EntityId> getEntityIds( ComponentFilter filter ) {\n if( log.isTraceEnabled() ) {\n log.trace(\"getEntityIds(\" + filter + \")\");\n }\n if( filter != null ) {\n throw new UnsupportedOperationException(\"Filtering + body visibility not yet supported\");\n }\n\n /*Set<Long> active = netState.getActiveIds();\n log.info(\"active:\" + active);\n\n Set<EntityId> results = new HashSet<>();\n for( Long l : active ) {\n results.add(new EntityId(l));\n }\n\n return results;*/\n return lastValues.keySet();\n }\n\n public boolean collectChanges( Queue<EntityChange> updates ) {\n Set<Long> active = netState.getActiveIds();\n boolean changed = false;\n if( log.isTraceEnabled() ) {\n log.trace(\"active:\" + active);\n log.trace(\"updates before:\" + updates);\n }\n\n // Remove any BodyPosition updates that don't belong to the active\n // set\n for( Iterator<EntityChange> it = updates.iterator(); it.hasNext(); ) {\n EntityChange change = it.next();\n if( change.getComponentType() == BodyPosition.class\n && !active.contains(change.getEntityId().getId()) ) {\n if( log.isTraceEnabled() ) {\n log.trace(\"removing irrelevant change:\" + change);\n }\n it.remove();\n }\n }\n\n // First process the removals\n for( Iterator<EntityId> it = lastValues.keySet().iterator(); it.hasNext(); ) {\n EntityId id = it.next();\n if( active.contains(id.getId()) ) {\n continue;\n }\n if( log.isTraceEnabled() ) {\n log.trace(\"removing:\" + id);\n }\n updates.add(new EntityChange(id, BodyPosition.class));\n it.remove();\n changed = true;\n }\n\n // Now the adds\n for( Long l : active ) {\n EntityId id = new EntityId(l);\n if( lastValues.containsKey(id) ) {\n continue;\n }\n if( log.isTraceEnabled() ) {\n log.trace(\"adding:\" + id);\n }\n BodyPosition pos = ed.getComponent(id, BodyPosition.class);\n lastValues.put(id, pos);\n updates.add(new EntityChange(id, pos));\n changed = true;\n }\n\n if( changed ) {\n if( log.isTraceEnabled() ) {\n log.trace(\"done collectChanges() \" + active);\n }\n }\n\n return changed;\n }\n }\n\n\nOn the server you just register a ComponentVisibility object with the client-specific hosted entity data.\n\nEdit: rereading the classes, I guess it doesn’t prevent all queries against the entity but will filter the entity out of entity sets that have that component. I’d have to experiment to be 100% sure because my memory says one thing and the javadoc says another.",
"title": "Zay-ES and hidden states"
}