+
* Put agents in 3D world
- Agent has body that resembles human
- Kimi K3
+
+
+* World is built around intent
+
+- you start with the world and you name intent for it
+
+- AI is monitoring what you are doing and is always ready to help
+ - rename space to better capture intent
+
+- you create new (optionally linked) spaces with (sub intents)
+ - you can inherit copy of existing apps into new space or star with empty space
+
+
+
private static final long SELFTEST_TIMEOUT_MS = 15_000;
public static void main(final String[] args) throws Exception {
- if (args.length > 0 && "--clicktest".equals(args[0]))
+ String environmentName = null;
+ for (final String arg : args)
+ if (arg.startsWith("--env="))
+ environmentName = arg.substring("--env=".length());
+
+ if (hasArg(args, "--clicktest"))
prepareClickTestPage();
- if (args.length > 0 && "--keytest".equals(args[0]))
+ if (hasArg(args, "--keytest"))
prepareKeyTestPage();
- if (args.length > 0 && "--scrolltest".equals(args[0]))
+ if (hasArg(args, "--scrolltest"))
prepareScrollTestPage();
- if (args.length > 0 && "--hovertest".equals(args[0]))
+ if (hasArg(args, "--hovertest"))
prepareHoverTestPage();
final Workspace workspace = new Workspace();
workspace.open();
- if (args.length > 0 && "--selftest".equals(args[0]))
+ if (environmentName != null)
+ openRequestedEnvironment(workspace, environmentName);
+
+ if (hasArg(args, "--selftest"))
System.exit(runSelfTest(workspace));
- if (args.length > 0 && "--guitest".equals(args[0]))
+ if (hasArg(args, "--guitest"))
System.exit(runGuiTest(workspace));
- if (args.length > 0 && "--clicktest".equals(args[0]))
+ if (hasArg(args, "--clicktest"))
System.exit(runClickTest(workspace));
- if (args.length > 0 && "--keytest".equals(args[0]))
+ if (hasArg(args, "--keytest"))
System.exit(runKeyTest(workspace));
- if (args.length > 0 && "--scrolltest".equals(args[0]))
+ if (hasArg(args, "--scrolltest"))
System.exit(runScrollTest(workspace));
- if (args.length > 0 && "--hovertest".equals(args[0]))
+ if (hasArg(args, "--hovertest"))
System.exit(runHoverTest(workspace));
- if (args.length > 0 && "--headtest".equals(args[0]))
+ if (hasArg(args, "--headtest"))
System.exit(runHeadTest(workspace));
- if (args.length > 0 && "--headdebug".equals(args[0]))
+ if (hasArg(args, "--headdebug"))
startHeadDebugLogger(workspace);
Runtime.getRuntime().addShutdownHook(
new Thread(workspace::close));
}
+ /**
+ * True when the exact flag appears anywhere on the command line;
+ * test drivers must not be position-sensitive now that --env= can
+ * occupy args[0].
+ */
+ private static boolean hasArg(final String[] args, final String flag) {
+ for (final String arg : args)
+ if (flag.equals(arg))
+ return true;
+ return false;
+ }
+
+ /**
+ * Resolves the --env=<name> provider, checks availability, and opens
+ * it into the running workspace. Exits with status 1 when the name
+ * is unknown or the provider's data files are missing.
+ */
+ private static void openRequestedEnvironment(final Workspace workspace,
+ final String name)
+ throws Exception {
+ final var provider
+ = eu.svjatoslav.sixth.env.EnvironmentRegistry.findByName(name);
+ if (provider == null) {
+ System.out.println("no environment named '" + name + "'");
+ eu.svjatoslav.sixth.env.EnvironmentRegistry
+ .printAvailableEnvironments();
+ System.exit(1);
+ }
+ if (!provider.isAvailable()) {
+ System.out.println("environment '" + name + "' ("
+ + provider.getDisplayName() + ") is not available on"
+ + " this machine — its data files were not found");
+ System.exit(1);
+ }
+ System.out.println("opening environment: "
+ + provider.getDisplayName());
+ workspace.openEnvironment(provider);
+ }
+
/**
* Drives the terminal without AWT events: injects bytes straight into
* the PTY, exactly what a focused keystroke would send.
--- /dev/null
+/*
+ * Sixth spatial computing environment. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+package eu.svjatoslav.sixth.env;
+
+import eu.svjatoslav.sixth.e3d.gui.Camera;
+import eu.svjatoslav.sixth.e3d.gui.FrameListener;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
+import eu.svjatoslav.sixth.e3d.renderer.raster.ShapeCollection;
+
+/**
+ * Host services handed to an {@link EnvironmentProvider} when it is
+ * opened. This is deliberately a narrow window into the workspace: the
+ * scene to add shapes to, the camera to place at the world's spawn
+ * point, and the per-frame tick for streaming worlds.
+ */
+public final class EnvironmentContext {
+
+ private final ViewPanel viewPanel;
+
+ public EnvironmentContext(final ViewPanel viewPanel) {
+ this.viewPanel = viewPanel;
+ }
+
+ /**
+ * The root scene graph. The environment adds its shapes here and
+ * keeps references to whatever it must later remove in close().
+ */
+ public ShapeCollection getScene() {
+ return viewPanel.getRootShapeCollection();
+ }
+
+ /**
+ * The workspace camera. An environment typically moves it to its
+ * spawn point in open(); afterwards the user owns it (fly controls,
+ * head tracking, SpaceNavigator).
+ */
+ public Camera getCamera() {
+ return viewPanel.getCamera();
+ }
+
+ /**
+ * Registers a per-frame callback — the streaming world's heartbeat:
+ * "recompute what should exist around the camera." Return true from
+ * the callback when the scene changed and needs a repaint.
+ */
+ public void addFrameListener(final FrameListener listener) {
+ viewPanel.addFrameListener(listener);
+ }
+
+ public void removeFrameListener(final FrameListener listener) {
+ viewPanel.removeFrameListener(listener);
+ }
+
+ /**
+ * Requests a repaint after scene changes made outside a frame
+ * callback (e.g. from a background loader thread).
+ */
+ public void requestRepaint() {
+ viewPanel.repaintDuringNextViewUpdate();
+ }
+
+ /**
+ * Escape hatch to the underlying view panel. Prefer the narrower
+ * methods above; this exists for things like reading viewport size.
+ */
+ public ViewPanel getViewPanel() {
+ return viewPanel;
+ }
+}
--- /dev/null
+/*
+ * Sixth spatial computing environment. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+package eu.svjatoslav.sixth.env;
+
+/**
+ * A pluggable 3D environment ("world provider") for the Sixth workspace:
+ * a game world, a map, or a procedural scene that the workspace panels
+ * live inside of. Today the wallpaper is a Fallout 4 level, tomorrow a
+ * Quake map, the day after a 3D fractal — the workspace does not care,
+ * it only knows this interface.
+ *
+ * <p>Implementations are discovered in two ways:</p>
+ * <ul>
+ * <li>built-in providers, registered directly in
+ * {@link EnvironmentRegistry};</li>
+ * <li>external providers on the classpath, discovered via
+ * {@link java.util.ServiceLoader} — a provider jar declares itself in
+ * {@code META-INF/services/eu.svjatoslav.sixth.env.EnvironmentProvider}.
+ * This is how separate environment projects (e.g.
+ * sixth-environment-fo4) plug in without Sixth depending on them.</li>
+ * </ul>
+ *
+ * <p>Selection: {@code sixth --env=<name>} picks a provider by
+ * {@link #getName()}.</p>
+ *
+ * <p>Lifecycle: {@link #open(EnvironmentContext)} is called once after the
+ * workspace window exists. The provider builds its initial scene into
+ * {@link EnvironmentContext#getScene()}, positions the camera via
+ * {@link EnvironmentContext#getCamera()}, and — for streaming worlds —
+ * registers a per-frame callback via
+ * {@link EnvironmentContext#addFrameListener} whose job is "recompute what
+ * should exist around the camera, add/remove shapes accordingly."
+ * {@link #close()} must unregister listeners and release resources.</p>
+ *
+ * <p>What an environment is NOT: it never touches the engine internals,
+ * never creates windows, and never interferes with workspace panels —
+ * it only adds shapes to the shared scene and moves nothing it does not
+ * own.</p>
+ */
+public interface EnvironmentProvider {
+
+ /**
+ * Short unique selector used on the command line, e.g. "fallout4",
+ * "quake1", "fractal". Lower case, no spaces.
+ */
+ String getName();
+
+ /**
+ * Human-readable name, e.g. "Fallout 4 — the Commonwealth".
+ */
+ String getDisplayName();
+
+ /**
+ * True when this provider can actually run on this machine — for
+ * game worlds this means the game data files were found. Providers
+ * that need no external data (procedural worlds) always return true.
+ */
+ boolean isAvailable();
+
+ /**
+ * Builds the initial scene and starts any background streaming.
+ * Called once, after the workspace window exists.
+ *
+ * @param context host services: the scene, the camera, frame ticks
+ * @throws Exception if the environment cannot be built (for game
+ * worlds: data files unreadable/corrupt)
+ */
+ void open(EnvironmentContext context) throws Exception;
+
+ /**
+ * Stops background work and removes the environment's shapes from
+ * the scene. Must tolerate being called after a failed open().
+ */
+ void close();
+}
--- /dev/null
+/*
+ * Sixth spatial computing environment. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+package eu.svjatoslav.sixth.env;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+/**
+ * Finds the environments that can run on this machine: built-in
+ * providers plus any declared on the classpath via
+ * {@code META-INF/services/eu.svjatoslav.sixth.env.EnvironmentProvider}
+ * (the plug-in mechanism used by separate environment projects such as
+ * sixth-environment-fo4).
+ */
+public final class EnvironmentRegistry {
+
+ private EnvironmentRegistry() {
+ }
+
+ /**
+ * All discovered providers, available or not. Built-ins first, then
+ * classpath plug-ins; keyed by name, later duplicates lose.
+ */
+ public static List<EnvironmentProvider> discoverProviders() {
+ final Map<String, EnvironmentProvider> providers
+ = new LinkedHashMap<>();
+ providers.put("grid", new GridEnvironmentProvider());
+ for (final EnvironmentProvider provider
+ : ServiceLoader.load(EnvironmentProvider.class))
+ providers.putIfAbsent(provider.getName(), provider);
+ return new ArrayList<>(providers.values());
+ }
+
+ /**
+ * Looks up a provider by its command-line name; null when no
+ * provider with that name is on the classpath.
+ */
+ public static EnvironmentProvider findByName(final String name) {
+ for (final EnvironmentProvider provider : discoverProviders())
+ if (provider.getName().equals(name))
+ return provider;
+ return null;
+ }
+
+ /**
+ * Prints the known providers and their availability, for CLI help
+ * and for the error message when a requested provider is missing.
+ */
+ public static void printAvailableEnvironments() {
+ System.out.println("known environments:");
+ for (final EnvironmentProvider provider : discoverProviders())
+ System.out.println(" " + provider.getName()
+ + (provider.isAvailable() ? "" : " (unavailable)")
+ + " — " + provider.getDisplayName());
+ }
+}
--- /dev/null
+/*
+ * Sixth spatial computing environment. Author: Svjatoslav Agejenko.
+ * This project is released under Creative Commons Zero (CC0) license.
+ */
+package eu.svjatoslav.sixth.env;
+
+import eu.svjatoslav.sixth.e3d.geometry.Rectangle;
+import eu.svjatoslav.sixth.e3d.math.Transform;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.basic.line.LineAppearance;
+import eu.svjatoslav.sixth.e3d.renderer.raster.shapes.composite.wireframe.Grid2D;
+
+import static eu.svjatoslav.sixth.e3d.renderer.raster.Color.hex;
+
+/**
+ * Built-in proof environment: a huge ground grid under the workspace.
+ * Exists to validate the provider contract (discovery, lifecycle, camera
+ * placement) without any external data — and as the reference
+ * implementation for how little a working provider can be.
+ */
+public class GridEnvironmentProvider implements EnvironmentProvider {
+
+ @Override
+ public String getName() {
+ return "grid";
+ }
+
+ @Override
+ public String getDisplayName() {
+ return "Ground grid (built-in test environment)";
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void open(final EnvironmentContext context) {
+ // ground plane at y=0, camera 150 units above it (negative Y is
+ // up in engine coordinates), looking slightly down
+ final Transform transform = Transform.fromAngles(0, 0, 0, 0,
+ Math.PI / 2, 0);
+ context.getScene().addShape(new Grid2D(transform,
+ new Rectangle(20000), 40, 40,
+ new LineAppearance(10, hex("5a5a3a"))));
+ context.getCamera().getTransform().set(0, -150, -300, 0, -0.4, 0);
+ context.requestRepaint();
+ }
+
+ @Override
+ public void close() {
+ // keeps no references and no background work — nothing to undo
+ }
+}
private final ViewFrame viewFrame;
private final List<TerminalPanel> terminalPanels = new ArrayList<>();
private FirefoxPanel firefoxPanel;
+ private eu.svjatoslav.sixth.env.EnvironmentProvider environment;
public Workspace() {
viewFrame = new ViewFrame("Sixth");
}
+ /**
+ * Attaches a pluggable environment (game world, procedural scene)
+ * after open(); the workspace then owns its lifecycle.
+ */
+ public void openEnvironment(
+ final eu.svjatoslav.sixth.env.EnvironmentProvider provider)
+ throws Exception {
+ environment = provider;
+ provider.open(new eu.svjatoslav.sixth.env.EnvironmentContext(
+ viewFrame.getViewPanel()));
+ }
+
/**
* Builds the scene and shows the window.
*
* Shuts down all background shell processes.
*/
public void close() {
+ if (environment != null)
+ environment.close();
for (final TerminalPanel terminalPanel : terminalPanels)
terminalPanel.getSession().stop();
if (firefoxPanel != null)
--- /dev/null
+#!/usr/bin/env bash
+# Start the Sixth workspace with the Fallout 4 environment.
+#
+# Rebuilds every module in dependency order first, so the classpath is
+# always at the latest source state (the FO4 provider resolves `sixth`
+# and `sixth-3d` from the local Maven repository — stale installs there
+# are the classic reason the world silently doesn't show up).
+#
+# Extra args are forwarded to the JVM launcher, e.g.:
+# ./start.sh -Dsixth.fo4.cell=ConcordExt
+# Actually: args go to Main. To pass -D properties, edit JAVA_OPTS below
+# or export them before calling.
+
+set -euo pipefail
+
+ROOT=/home/n0/workspace/svjatoslav
+FO4="$ROOT/sixth-environment-fo4"
+
+echo "==> building sixth-3d"
+mvn -f "$ROOT/sixth-3d/pom.xml" install -q -DskipTests -Dmaven.javadoc.skip=true
+
+echo "==> building sixth"
+mvn -f "$ROOT/sixth/pom.xml" install -q -DskipTests -Dmaven.javadoc.skip=true
+
+echo "==> building sixth-environment-fo4"
+mvn -f "$FO4/pom.xml" package -q -DskipTests -Dmaven.javadoc.skip=true
+mvn -f "$FO4/pom.xml" dependency:build-classpath -q -Dmdep.outputFile=target/cp.txt
+
+echo "==> starting Sixth with --env=fallout4"
+cd "$FO4"
+exec java -Xmx8g --enable-native-access=ALL-UNNAMED \
+ ${JAVA_OPTS:-} \
+ -cp "target/classes:$(cat target/cp.txt)" \
+ eu.svjatoslav.sixth.core.Main --env=fallout4 "$@"