一键导入
jme-appstate
Create client-side application states using jME3 BaseAppState. Use when building UI screens, client rendering, input handling, or visual effects.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Create client-side application states using jME3 BaseAppState. Use when building UI screens, client rendering, input handling, or visual effects.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
ArenaModule interface (api/) — arena-composition contract per ADR-0008. ModuleCatalog, ModuleLoader, and ArenaModuleSystem are live. Author new ArenaModule classes under infinity-server/src/main/java/infinity/modules/<category>/ and register them in ModuleCatalog.
Work with Subspace Infinity arena settings — the per-arena `arena.groovy` files under `zone/arenas/`, the Groovy `conf/` preset fragment library (section/shipSection/shipSections DSL), the recursive `include` directive, the `SettingsSystem` typed accessors, and the `~loadArena`/`~swapMap` commands. Use when adding or reading settings, creating a new arena, or splitting settings fragments.
Explains the api ↔ server ↔ client layering of Subspace Infinity — which module new code belongs in, how data flows between layers, which packages live in which Gradle module, and the SimEthereal + RMI boundaries. Use when deciding where a new file should live, tracing data across layers, or explaining the project structure.
Overview of Subspace Infinity project structure, tech stack, and conventions. Use when understanding the codebase, finding files, or learning project patterns.
Create Zay-ES EntityComponent classes for the ECS architecture. Use when creating new components, data holders, or entity attributes.
Debug Entity-Component-System issues including EntitySet problems, memory leaks, and component queries. Use when troubleshooting ECS bugs or entity processing issues.
| name | jme-appstate |
| description | Create client-side application states using jME3 BaseAppState. Use when building UI screens, client rendering, input handling, or visual effects. |
Client-side states manage UI, rendering, and input using jME3's state system.
infinity-client/src/main/java/infinity/
com.jme3.app.state.BaseAppStatecleanup() - CRITICAL: release EntitySetsBSD-3-Clause license header// SPDX-License-Identifier: BSD-3-Clause
// Copyright (c) 2018-2026 Asser Fahrenholz
package infinity;
import com.jme3.app.Application;
import com.jme3.app.state.BaseAppState;
public class MyState extends BaseAppState {
@Override
protected void initialize(final Application app) {
// Called once when state is attached
// Setup resources, load assets
}
@Override
protected void cleanup(final Application app) {
// Called once when state is detached
// Release all resources and EntitySets!
}
@Override
protected void onEnable() {
// Called when state becomes active
// Attach to scene graph, register listeners
}
@Override
protected void onDisable() {
// Called when state becomes inactive
// Detach from scene graph, unregister listeners
}
@Override
public void update(final float tpf) {
// Per-frame updates (optional override)
}
}
This is the first design pattern in ECS - syncing entities to visual spatials:
public class VisualAppState extends BaseAppState {
private EntityData ed;
private EntitySet entities;
private final Map<EntityId, Spatial> models = new HashMap<>();
private SimpleApplication app;
@Override
protected void initialize(Application app) {
this.app = (SimpleApplication) app;
ed = getEntityData(); // Get from ConnectionState or similar
entities = ed.getEntities(Position.class, Model.class);
}
@Override
protected void cleanup(Application app) {
// CRITICAL: Release EntitySet to prevent memory leak
entities.release();
entities = null;
}
@Override
public void update(float tpf) {
// Check for changes and handle them
if (entities.applyChanges()) {
removeModels(entities.getRemovedEntities());
addModels(entities.getAddedEntities());
updateModels(entities.getChangedEntities());
}
}
private void removeModels(Set<Entity> removed) {
for (Entity e : removed) {
Spatial s = models.remove(e.getId());
s.removeFromParent();
}
}
private void addModels(Set<Entity> added) {
for (Entity e : added) {
Spatial s = createVisual(e);
models.put(e.getId(), s);
updateModelSpatial(e, s);
app.getRootNode().attachChild(s);
}
}
private void updateModels(Set<Entity> changed) {
for (Entity e : changed) {
Spatial s = models.get(e.getId());
updateModelSpatial(e, s);
}
}
private void updateModelSpatial(Entity e, Spatial s) {
Position p = e.get(Position.class);
s.setLocalTranslation(p.getLocation());
}
private Spatial createVisual(Entity e) {
Model model = e.get(Model.class);
return assetManager.loadModel("Models/" + model.getName() + ".j3o");
}
}
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.GuiGlobals;
@Override
protected void initialize(final Application app) {
Container window = new Container();
window.addChild(new Label("Title"));
Button btn = window.addChild(new Button("Click Me"));
btn.addClickCommands(source -> {
// Handle click
});
// Center on screen
window.setLocalTranslation(
(app.getCamera().getWidth() - window.getPreferredSize().x) / 2,
(app.getCamera().getHeight() + window.getPreferredSize().y) / 2,
0
);
}
@Override
protected void onEnable() {
((SimpleApplication) getApplication()).getGuiNode().attachChild(window);
}
@Override
protected void onDisable() {
window.removeFromParent();
}
OtherState other = getState(OtherState.class);
ConnectionState conn = getState(ConnectionState.class);
EntityData ed = conn.getEntityData();
MainMenuState - main menu UISettingsState - settings screenHelpState - help/controls screenTimeState - time managementPostProcessingState - visual effects