chore: tony starkified clod
This commit is contained in:
Binary file not shown.
@@ -24,6 +24,9 @@ _last_build_time: float = 0.0
|
|||||||
_BUILD_SESSION_TIMEOUT = 3.0 # seconds of inactivity before session ends
|
_BUILD_SESSION_TIMEOUT = 3.0 # seconds of inactivity before session ends
|
||||||
_build_session_origin: tuple[float, float, float] | None = None
|
_build_session_origin: tuple[float, float, float] | None = None
|
||||||
_watcher_task: asyncio.Task | None = None
|
_watcher_task: asyncio.Task | None = None
|
||||||
|
_build_bounds: dict | None = None # {"min_x", "max_x", "min_y", "max_y", "min_z", "max_z"}
|
||||||
|
_build_flying: bool = False # whether current session uses flying mode
|
||||||
|
_build_fly_xz: tuple[float, float] | None = None # fixed XZ while flying
|
||||||
|
|
||||||
|
|
||||||
async def _request(method: str, path: str, **kwargs) -> Any:
|
async def _request(method: str, path: str, **kwargs) -> Any:
|
||||||
@@ -67,6 +70,10 @@ async def _look_at_pos(x: float, y: float, z: float) -> None:
|
|||||||
await _request("POST", "/look_at", json={"x": x, "y": y, "z": z})
|
await _request("POST", "/look_at", json={"x": x, "y": y, "z": z})
|
||||||
|
|
||||||
|
|
||||||
|
async def _set_bot_flying(flying: bool) -> None:
|
||||||
|
await _request("POST", "/set_flying", json={"flying": flying})
|
||||||
|
|
||||||
|
|
||||||
async def _get_bot_position() -> tuple[float, float, float] | None:
|
async def _get_bot_position() -> tuple[float, float, float] | None:
|
||||||
data = await _request("GET", "/status")
|
data = await _request("GET", "/status")
|
||||||
if isinstance(data, dict) and "position" in data:
|
if isinstance(data, dict) and "position" in data:
|
||||||
@@ -78,8 +85,42 @@ async def _get_bot_position() -> tuple[float, float, float] | None:
|
|||||||
def _compute_viewing_position(
|
def _compute_viewing_position(
|
||||||
build_x: float, build_y: float, build_z: float,
|
build_x: float, build_y: float, build_z: float,
|
||||||
bot_x: float, bot_y: float, bot_z: float,
|
bot_x: float, bot_y: float, bot_z: float,
|
||||||
|
bounds: dict | None = None,
|
||||||
) -> tuple[float, float, float]:
|
) -> tuple[float, float, float]:
|
||||||
"""Compute a spot 5 blocks from the build, on the side the bot is on."""
|
"""Compute a viewing spot outside the build volume.
|
||||||
|
|
||||||
|
When *bounds* is provided, position 3 blocks outside the nearest edge
|
||||||
|
of the build footprint (on the side the bot is already on).
|
||||||
|
Otherwise fall back to 5 blocks from the center point.
|
||||||
|
"""
|
||||||
|
if bounds is not None:
|
||||||
|
min_x = bounds["min_x"]
|
||||||
|
max_x = bounds["max_x"]
|
||||||
|
min_z = bounds["min_z"]
|
||||||
|
max_z = bounds["max_z"]
|
||||||
|
center_x = (min_x + max_x) / 2.0
|
||||||
|
center_z = (min_z + max_z) / 2.0
|
||||||
|
dx = bot_x - center_x
|
||||||
|
dz = bot_z - center_z
|
||||||
|
if abs(dx) < 0.01 and abs(dz) < 0.01:
|
||||||
|
dx = 1.0
|
||||||
|
# Pick the axis the bot is farthest on
|
||||||
|
if abs(dx) >= abs(dz):
|
||||||
|
# Position outside X edge
|
||||||
|
if dx >= 0:
|
||||||
|
vx = max_x + 3.5
|
||||||
|
else:
|
||||||
|
vx = min_x - 3.5
|
||||||
|
vz = center_z
|
||||||
|
else:
|
||||||
|
# Position outside Z edge
|
||||||
|
vx = center_x
|
||||||
|
if dz >= 0:
|
||||||
|
vz = max_z + 3.5
|
||||||
|
else:
|
||||||
|
vz = min_z - 3.5
|
||||||
|
return (vx, build_y, vz)
|
||||||
|
|
||||||
dx = bot_x - build_x
|
dx = bot_x - build_x
|
||||||
dz = bot_z - build_z
|
dz = bot_z - build_z
|
||||||
dist = math.hypot(dx, dz)
|
dist = math.hypot(dx, dz)
|
||||||
@@ -90,35 +131,67 @@ def _compute_viewing_position(
|
|||||||
return (build_x + dx * scale, build_y, build_z + dz * scale)
|
return (build_x + dx * scale, build_y, build_z + dz * scale)
|
||||||
|
|
||||||
|
|
||||||
async def _ensure_build_session(x: float, y: float, z: float) -> None:
|
async def _ensure_build_session(
|
||||||
|
x: float, y: float, z: float,
|
||||||
|
bounds: dict | None = None,
|
||||||
|
flying: bool = False,
|
||||||
|
) -> None:
|
||||||
"""Start or continue a build session, managing state/teleport/look."""
|
"""Start or continue a build session, managing state/teleport/look."""
|
||||||
global _build_session_active, _last_build_time, _build_session_origin
|
global _build_session_active, _last_build_time, _build_session_origin
|
||||||
global _watcher_task
|
global _watcher_task, _build_bounds, _build_flying, _build_fly_xz
|
||||||
|
|
||||||
async with _build_session_lock:
|
async with _build_session_lock:
|
||||||
_last_build_time = time.monotonic()
|
_last_build_time = time.monotonic()
|
||||||
|
|
||||||
if _build_session_active:
|
if _build_session_active:
|
||||||
# Session already running — just look at the new target
|
# Session already running
|
||||||
_build_session_origin = (x, y, z)
|
_build_session_origin = (x, y, z)
|
||||||
await _look_at_pos(x, y, z)
|
if _build_flying and _build_fly_xz is not None:
|
||||||
|
# Flying mode: keep XZ fixed, only update Y to rise with layers
|
||||||
|
fx, fz = _build_fly_xz
|
||||||
|
await _teleport_bot(fx, y, fz)
|
||||||
|
# Look at the center of the build at the current layer height
|
||||||
|
if _build_bounds:
|
||||||
|
cx = (_build_bounds["min_x"] + _build_bounds["max_x"]) / 2.0
|
||||||
|
cz = (_build_bounds["min_z"] + _build_bounds["max_z"]) / 2.0
|
||||||
|
await _look_at_pos(cx, y, cz)
|
||||||
|
else:
|
||||||
|
await _look_at_pos(x, y, z)
|
||||||
|
else:
|
||||||
|
await _look_at_pos(x, y, z)
|
||||||
return
|
return
|
||||||
|
|
||||||
# --- Start a new session ---
|
# --- Start a new session ---
|
||||||
_build_session_active = True
|
_build_session_active = True
|
||||||
_build_session_origin = (x, y, z)
|
_build_session_origin = (x, y, z)
|
||||||
|
_build_bounds = bounds
|
||||||
|
_build_flying = flying
|
||||||
|
|
||||||
await _set_bot_state("building")
|
await _set_bot_state("building")
|
||||||
|
|
||||||
pos = await _get_bot_position()
|
pos = await _get_bot_position()
|
||||||
if pos is not None:
|
if pos is not None:
|
||||||
bx, by, bz = pos
|
bx, by, bz = pos
|
||||||
dist = math.sqrt((bx - x) ** 2 + (by - y) ** 2 + (bz - z) ** 2)
|
|
||||||
if dist > 16:
|
|
||||||
vx, vy, vz = _compute_viewing_position(x, y, z, bx, by, bz)
|
|
||||||
await _teleport_bot(vx, vy, vz)
|
|
||||||
|
|
||||||
await _look_at_pos(x, y, z)
|
if bounds is not None and flying:
|
||||||
|
# Compute safe position outside build volume
|
||||||
|
vx, vy, vz = _compute_viewing_position(x, y, z, bx, by, bz, bounds=bounds)
|
||||||
|
_build_fly_xz = (vx, vz)
|
||||||
|
await _set_bot_flying(True)
|
||||||
|
await _teleport_bot(vx, y, vz)
|
||||||
|
else:
|
||||||
|
_build_fly_xz = None
|
||||||
|
dist = math.sqrt((bx - x) ** 2 + (by - y) ** 2 + (bz - z) ** 2)
|
||||||
|
if dist > 16:
|
||||||
|
vx, vy, vz = _compute_viewing_position(x, y, z, bx, by, bz)
|
||||||
|
await _teleport_bot(vx, vy, vz)
|
||||||
|
|
||||||
|
if bounds is not None:
|
||||||
|
cx = (bounds["min_x"] + bounds["max_x"]) / 2.0
|
||||||
|
cz = (bounds["min_z"] + bounds["max_z"]) / 2.0
|
||||||
|
await _look_at_pos(cx, y, cz)
|
||||||
|
else:
|
||||||
|
await _look_at_pos(x, y, z)
|
||||||
|
|
||||||
# Start the watcher if not already running
|
# Start the watcher if not already running
|
||||||
if _watcher_task is None or _watcher_task.done():
|
if _watcher_task is None or _watcher_task.done():
|
||||||
@@ -128,6 +201,7 @@ async def _ensure_build_session(x: float, y: float, z: float) -> None:
|
|||||||
async def _build_session_watcher() -> None:
|
async def _build_session_watcher() -> None:
|
||||||
"""Background task that ends the build session after inactivity."""
|
"""Background task that ends the build session after inactivity."""
|
||||||
global _build_session_active, _build_session_origin
|
global _build_session_active, _build_session_origin
|
||||||
|
global _build_bounds, _build_flying, _build_fly_xz
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
await asyncio.sleep(1.0)
|
await asyncio.sleep(1.0)
|
||||||
@@ -136,9 +210,14 @@ async def _build_session_watcher() -> None:
|
|||||||
return
|
return
|
||||||
elapsed = time.monotonic() - _last_build_time
|
elapsed = time.monotonic() - _last_build_time
|
||||||
if elapsed >= _BUILD_SESSION_TIMEOUT:
|
if elapsed >= _BUILD_SESSION_TIMEOUT:
|
||||||
|
if _build_flying:
|
||||||
|
await _set_bot_flying(False)
|
||||||
await _set_bot_state("idle")
|
await _set_bot_state("idle")
|
||||||
_build_session_active = False
|
_build_session_active = False
|
||||||
_build_session_origin = None
|
_build_session_origin = None
|
||||||
|
_build_bounds = None
|
||||||
|
_build_flying = False
|
||||||
|
_build_fly_xz = None
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
@@ -366,12 +445,13 @@ async def build_schematic(name: str, x: int, y: int, z: int) -> str:
|
|||||||
layers = info.get("layers", [])
|
layers = info.get("layers", [])
|
||||||
fmt = info.get("format", "unknown")
|
fmt = info.get("format", "unknown")
|
||||||
num_layers = len(layers)
|
num_layers = len(layers)
|
||||||
|
bounds = info.get("bounds") # may be None for empty schematics
|
||||||
|
|
||||||
if num_layers == 0:
|
if num_layers == 0:
|
||||||
return _fmt({"ok": True, "message": "Schematic is empty, nothing to build.", "placed": 0})
|
return _fmt({"ok": True, "message": "Schematic is empty, nothing to build.", "placed": 0})
|
||||||
|
|
||||||
# 2. Start build session and announce
|
# 2. Start build session with flying + bounds and announce
|
||||||
await _ensure_build_session(x, y, z)
|
await _ensure_build_session(x, y, z, bounds=bounds, flying=True)
|
||||||
await _request("POST", "/chat", json={
|
await _request("POST", "/chat", json={
|
||||||
"message": f"Starting build of {name}! {total_blocks} blocks, {num_layers} layers."
|
"message": f"Starting build of {name}! {total_blocks} blocks, {num_layers} layers."
|
||||||
})
|
})
|
||||||
@@ -384,8 +464,8 @@ async def build_schematic(name: str, x: int, y: int, z: int) -> str:
|
|||||||
layer_y = layer["y"]
|
layer_y = layer["y"]
|
||||||
block_count = layer["block_count"]
|
block_count = layer["block_count"]
|
||||||
|
|
||||||
# Keep build session alive and look at current layer
|
# Keep build session alive; flying mode rises with each layer
|
||||||
await _ensure_build_session(x, layer_y, z)
|
await _ensure_build_session(x, layer_y, z, bounds=bounds, flying=True)
|
||||||
|
|
||||||
# Check if this layer crosses a milestone threshold
|
# Check if this layer crosses a milestone threshold
|
||||||
progress = (i + 1) / num_layers
|
progress = (i + 1) / num_layers
|
||||||
@@ -408,6 +488,7 @@ async def build_schematic(name: str, x: int, y: int, z: int) -> str:
|
|||||||
}, timeout=15.0)
|
}, timeout=15.0)
|
||||||
|
|
||||||
if isinstance(result, dict) and "error" in result:
|
if isinstance(result, dict) and "error" in result:
|
||||||
|
await _set_bot_flying(False)
|
||||||
await _request("POST", "/chat", json={
|
await _request("POST", "/chat", json={
|
||||||
"message": f"Build failed at layer {i + 1}/{num_layers}! Error: {result['error']}"
|
"message": f"Build failed at layer {i + 1}/{num_layers}! Error: {result['error']}"
|
||||||
})
|
})
|
||||||
@@ -426,7 +507,8 @@ async def build_schematic(name: str, x: int, y: int, z: int) -> str:
|
|||||||
if i < num_layers - 1:
|
if i < num_layers - 1:
|
||||||
await asyncio.sleep(0.4)
|
await asyncio.sleep(0.4)
|
||||||
|
|
||||||
# 4. Announce completion
|
# 4. Land and announce completion
|
||||||
|
await _set_bot_flying(False)
|
||||||
await _request("POST", "/chat", json={
|
await _request("POST", "/chat", json={
|
||||||
"message": f"Build complete! Placed {total_placed} blocks in {num_layers} layers."
|
"message": f"Build complete! Placed {total_placed} blocks in {num_layers} layers."
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -48,6 +48,66 @@ public class ClodEntityRenderer extends MobRenderer<ClodEntity, ClodModel> {
|
|||||||
double y = entity.getY();
|
double y = entity.getY();
|
||||||
double z = entity.getZ();
|
double z = entity.getZ();
|
||||||
|
|
||||||
|
// Rocket leg particles when flying
|
||||||
|
if (entity.isClodFlying()) {
|
||||||
|
float yawRad = entity.yBodyRot * ((float) Math.PI / 180F);
|
||||||
|
double perpX = -Mth.cos(yawRad);
|
||||||
|
double perpZ = -Mth.sin(yawRad);
|
||||||
|
|
||||||
|
// Right foot: 0.16 blocks to the right
|
||||||
|
double rfX = x + perpX * 0.16;
|
||||||
|
double rfZ = z + perpZ * 0.16;
|
||||||
|
// Left foot: 0.16 blocks to the left
|
||||||
|
double lfX = x - perpX * 0.16;
|
||||||
|
double lfZ = z - perpZ * 0.16;
|
||||||
|
double footY = y + 0.05;
|
||||||
|
|
||||||
|
// Flame jets: 3 per foot
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
double velY = -0.15 - entity.getRandom().nextDouble() * 0.10;
|
||||||
|
entity.level().addParticle(ParticleTypes.FLAME,
|
||||||
|
rfX + (entity.getRandom().nextDouble() - 0.5) * 0.08,
|
||||||
|
footY,
|
||||||
|
rfZ + (entity.getRandom().nextDouble() - 0.5) * 0.08,
|
||||||
|
0.0, velY, 0.0);
|
||||||
|
entity.level().addParticle(ParticleTypes.FLAME,
|
||||||
|
lfX + (entity.getRandom().nextDouble() - 0.5) * 0.08,
|
||||||
|
footY,
|
||||||
|
lfZ + (entity.getRandom().nextDouble() - 0.5) * 0.08,
|
||||||
|
0.0, velY, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Smoke puffs: 50% chance per foot
|
||||||
|
if (entity.getRandom().nextFloat() < 0.5F) {
|
||||||
|
entity.level().addParticle(ParticleTypes.SMOKE,
|
||||||
|
rfX, footY - 0.1, rfZ,
|
||||||
|
0.0, -0.05, 0.0);
|
||||||
|
}
|
||||||
|
if (entity.getRandom().nextFloat() < 0.5F) {
|
||||||
|
entity.level().addParticle(ParticleTypes.SMOKE,
|
||||||
|
lfX, footY - 0.1, lfZ,
|
||||||
|
0.0, -0.05, 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Orange glow: 30% chance per foot
|
||||||
|
if (entity.getRandom().nextFloat() < 0.3F) {
|
||||||
|
entity.level().addParticle(
|
||||||
|
new DustParticleOptions(new Vector3f(1.0F, 0.6F, 0.2F), 0.8F),
|
||||||
|
rfX + (entity.getRandom().nextDouble() - 0.5) * 0.15,
|
||||||
|
footY - 0.05,
|
||||||
|
rfZ + (entity.getRandom().nextDouble() - 0.5) * 0.15,
|
||||||
|
0.0, -0.02, 0.0);
|
||||||
|
}
|
||||||
|
if (entity.getRandom().nextFloat() < 0.3F) {
|
||||||
|
entity.level().addParticle(
|
||||||
|
new DustParticleOptions(new Vector3f(1.0F, 0.6F, 0.2F), 0.8F),
|
||||||
|
lfX + (entity.getRandom().nextDouble() - 0.5) * 0.15,
|
||||||
|
footY - 0.05,
|
||||||
|
lfZ + (entity.getRandom().nextDouble() - 0.5) * 0.15,
|
||||||
|
0.0, -0.02, 0.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case "idle":
|
case "idle":
|
||||||
// 10% chance per frame — warm dust drifting upward
|
// 10% chance per frame — warm dust drifting upward
|
||||||
|
|||||||
@@ -127,5 +127,14 @@ public class ClodModel extends HumanoidModel<ClodEntity> {
|
|||||||
this.leftArm.zRot = -0.08F - Mth.sin(ageInTicks * 0.067F) * 0.02F;
|
this.leftArm.zRot = -0.08F - Mth.sin(ageInTicks * 0.067F) * 0.02F;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Flying hover pose — overrides leg animation from state switch
|
||||||
|
if (entity.isClodFlying()) {
|
||||||
|
float hoverBob = Mth.sin(ageInTicks * 0.1F) * 0.04F;
|
||||||
|
this.rightLeg.xRot = 0.2F + hoverBob;
|
||||||
|
this.leftLeg.xRot = 0.2F + hoverBob;
|
||||||
|
this.rightLeg.zRot = 0.1F;
|
||||||
|
this.leftLeg.zRot = -0.1F;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ public class ClodEntity extends PathfinderMob {
|
|||||||
private static final EntityDataAccessor<String> STATE =
|
private static final EntityDataAccessor<String> STATE =
|
||||||
SynchedEntityData.defineId(ClodEntity.class, EntityDataSerializers.STRING);
|
SynchedEntityData.defineId(ClodEntity.class, EntityDataSerializers.STRING);
|
||||||
|
|
||||||
|
private static final EntityDataAccessor<Boolean> FLYING =
|
||||||
|
SynchedEntityData.defineId(ClodEntity.class, EntityDataSerializers.BOOLEAN);
|
||||||
|
|
||||||
private final SimpleContainer inventory = new SimpleContainer(36);
|
private final SimpleContainer inventory = new SimpleContainer(36);
|
||||||
|
|
||||||
public ClodEntity(EntityType<? extends PathfinderMob> type, Level level) {
|
public ClodEntity(EntityType<? extends PathfinderMob> type, Level level) {
|
||||||
@@ -45,6 +48,7 @@ public class ClodEntity extends PathfinderMob {
|
|||||||
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
protected void defineSynchedData(SynchedEntityData.Builder builder) {
|
||||||
super.defineSynchedData(builder);
|
super.defineSynchedData(builder);
|
||||||
builder.define(STATE, "idle");
|
builder.define(STATE, "idle");
|
||||||
|
builder.define(FLYING, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getClodState() {
|
public String getClodState() {
|
||||||
@@ -57,6 +61,27 @@ public class ClodEntity extends PathfinderMob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isClodFlying() {
|
||||||
|
return this.entityData.get(FLYING);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setClodFlying(boolean flying) {
|
||||||
|
this.entityData.set(FLYING, flying);
|
||||||
|
this.setNoGravity(flying);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void tick() {
|
||||||
|
super.tick();
|
||||||
|
if (isClodFlying()) {
|
||||||
|
this.setDeltaMovement(0, 0, 0);
|
||||||
|
this.fallDistance = 0;
|
||||||
|
} else if (this.isNoGravity() && "idle".equals(this.getClodState())) {
|
||||||
|
// Safety reset: if gravity is off but we're idle and not flying, re-enable gravity
|
||||||
|
this.setNoGravity(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isInvulnerable() {
|
public boolean isInvulnerable() {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ public class ClodHttpServer {
|
|||||||
httpServer.createContext("/get_time", this::handleGetTime);
|
httpServer.createContext("/get_time", this::handleGetTime);
|
||||||
httpServer.createContext("/get_weather", this::handleGetWeather);
|
httpServer.createContext("/get_weather", this::handleGetWeather);
|
||||||
|
|
||||||
|
httpServer.createContext("/set_flying", this::handleSetFlying);
|
||||||
|
|
||||||
// New POST endpoints
|
// New POST endpoints
|
||||||
httpServer.createContext("/place_structure", this::handlePlaceStructure);
|
httpServer.createContext("/place_structure", this::handlePlaceStructure);
|
||||||
httpServer.createContext("/clear_area", this::handleClearArea);
|
httpServer.createContext("/clear_area", this::handleClearArea);
|
||||||
@@ -850,6 +852,31 @@ public class ClodHttpServer {
|
|||||||
|
|
||||||
runOnServerThread(() -> {
|
runOnServerThread(() -> {
|
||||||
bot.setClodState(state);
|
bot.setClodState(state);
|
||||||
|
// Safety: disable flying when going idle
|
||||||
|
if ("idle".equals(state) && bot.isClodFlying()) {
|
||||||
|
bot.setClodFlying(false);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
sendJson(exchange, 200, okJson());
|
||||||
|
} catch (TimeoutException e) {
|
||||||
|
sendJson(exchange, 504, errorJson("Server thread timeout"));
|
||||||
|
} catch (Exception e) {
|
||||||
|
sendJson(exchange, 400, errorJson(e.getMessage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void handleSetFlying(HttpExchange exchange) throws IOException {
|
||||||
|
if (!requirePost(exchange)) return;
|
||||||
|
try {
|
||||||
|
ClodEntity bot = requireBot(exchange);
|
||||||
|
if (bot == null) return;
|
||||||
|
|
||||||
|
JsonObject body = readJsonBody(exchange);
|
||||||
|
boolean flying = body.get("flying").getAsBoolean();
|
||||||
|
|
||||||
|
runOnServerThread(() -> {
|
||||||
|
bot.setClodFlying(flying);
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
sendJson(exchange, 200, okJson());
|
sendJson(exchange, 200, okJson());
|
||||||
@@ -1302,6 +1329,15 @@ public class ClodHttpServer {
|
|||||||
size.addProperty("y", maxY - minY + 1);
|
size.addProperty("y", maxY - minY + 1);
|
||||||
size.addProperty("z", maxZ - minZ + 1);
|
size.addProperty("z", maxZ - minZ + 1);
|
||||||
result.add("size", size);
|
result.add("size", size);
|
||||||
|
|
||||||
|
JsonObject bounds = new JsonObject();
|
||||||
|
bounds.addProperty("min_x", minX);
|
||||||
|
bounds.addProperty("max_x", maxX);
|
||||||
|
bounds.addProperty("min_y", minY);
|
||||||
|
bounds.addProperty("max_y", maxY);
|
||||||
|
bounds.addProperty("min_z", minZ);
|
||||||
|
bounds.addProperty("max_z", maxZ);
|
||||||
|
result.add("bounds", bounds);
|
||||||
} else {
|
} else {
|
||||||
JsonObject size = new JsonObject();
|
JsonObject size = new JsonObject();
|
||||||
size.addProperty("x", 0);
|
size.addProperty("x", 0);
|
||||||
|
|||||||
Reference in New Issue
Block a user