Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,6 @@ These new details will be listed under the `"sable"` key and have the following
- `transitionSpeed: number`
- `preventSelfLift: boolean`
- `scaleWithGravity: boolean`
- `scaleWithPressure: boolean`
- `scaleWithPressure: boolean`

Comment thread
Sascha-T marked this conversation as resolved.

Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import dan200.computercraft.api.detail.VanillaDetailRegistries;
import dev.ryanhcode.sable.physics.config.block_properties.PhysicsBlockPropertyHelper;
import dev.ryanhcode.sable.physics.floating_block.FloatingBlockMaterial;
import dev.ryanhcode.sable.platform.SableEventPlatform;
import io.github.techtastic.cc_sable.apis.AerodynamicsAPI;
import io.github.techtastic.cc_sable.apis.SubLevelAPI;
import io.github.techtastic.cc_sable.util.Physicker;

import java.util.Map;

Expand All @@ -16,6 +18,8 @@ public static void init() {
ComputerCraftAPI.registerAPIFactory(SubLevelAPI::new);
ComputerCraftAPI.registerAPIFactory(AerodynamicsAPI::new);

SableEventPlatform.INSTANCE.onPhysicsTick(Physicker::onPhysicsTick);

VanillaDetailRegistries.BLOCK_IN_WORLD.addProvider((data, object) -> data.put("sable", Map.of(
"mass", PhysicsBlockPropertyHelper.getMass(object.level(), object.pos(), object.state()),
"friction", PhysicsBlockPropertyHelper.getFriction(object.state()),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,11 @@
import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.lua.LuaFunction;
import dev.ryanhcode.sable.Sable;
import dev.ryanhcode.sable.api.SubLevelHelper;
import dev.ryanhcode.sable.api.sublevel.SubLevelContainer;
import dev.ryanhcode.sable.companion.SableCompanion;
import dev.ryanhcode.sable.companion.SubLevelAccess;
import dev.ryanhcode.sable.physics.config.dimension_physics.DimensionPhysicsData;
import dev.ryanhcode.sable.sublevel.ServerSubLevel;
import dev.ryanhcode.sable.sublevel.SubLevel;
import io.github.techtastic.cc_sable.util.CCSableUtils;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.Level;
import io.github.techtastic.cc_sable.util.Physicker;
import org.joml.Vector3d;
import org.joml.Vector3dc;
import org.jspecify.annotations.NonNull;
Expand All @@ -36,7 +31,7 @@ private ServerSubLevel getSublevel() throws LuaException {

@Override
public final String @NonNull [] getNames() {
return new String[] {"sublevel"};
return new String[]{"sublevel"};
}

@LuaFunction(mainThread = true)
Expand Down Expand Up @@ -111,4 +106,16 @@ public final Map<Double, Map<Double, Double>> getInertiaTensor() throws LuaExcep
public final Map<Double, Map<Double, Double>> getInverseInertiaTensor() throws LuaException {
return CCSableUtils.toLua(getSublevel().getMassTracker().getInverseInertiaTensor());
}

@LuaFunction
public final Object getForces() throws LuaException {
try {
Object o = Physicker.requestForces(system, getSublevel());
if (o == null)
throw new LuaException("timeout");
return o;
} catch (InterruptedException e) {
throw new LuaException("interrupted");
}
}
}
103 changes: 103 additions & 0 deletions common/src/main/java/io/github/techtastic/cc_sable/util/Physicker.java
Comment thread
Sascha-T marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package io.github.techtastic.cc_sable.util;

import dan200.computercraft.api.lua.IComputerSystem;
import dev.ryanhcode.sable.Sable;
import dev.ryanhcode.sable.api.physics.force.ForceGroup;
import dev.ryanhcode.sable.api.physics.force.ForceGroups;
import dev.ryanhcode.sable.api.physics.force.QueuedForceGroup;
import dev.ryanhcode.sable.companion.math.Pose3d;
import dev.ryanhcode.sable.physics.config.dimension_physics.DimensionPhysicsData;
import dev.ryanhcode.sable.sublevel.ServerSubLevel;
import dev.ryanhcode.sable.sublevel.SubLevel;
import dev.ryanhcode.sable.sublevel.system.SubLevelPhysicsSystem;
import net.minecraft.resources.ResourceLocation;
import org.joml.Vector3d;
import org.joml.Vector3dc;
import org.jspecify.annotations.Nullable;

import java.util.*;
import java.util.concurrent.*;

/**
* Track "force requests" for sublevels because Sable be like "waaah no you cant request forces mid-tick"
*/
public class Physicker {
private static ConcurrentMap<Integer, Request> REQUESTS = new ConcurrentHashMap<>();

public static void onPhysicsTick(SubLevelPhysicsSystem activeSystem, double v) {
for (Map.Entry<Integer, Request> entry : REQUESTS.entrySet()) {
if(!entry.getValue().subLevel().getLevel().equals(activeSystem.getLevel()))
continue;
REQUESTS.remove(entry.getKey());
try {
entry.getValue().receiver.put(createValueMap(entry.getValue().subLevel));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}


public static Object requestForces(IComputerSystem system, ServerSubLevel sublevel) throws InterruptedException {
int id = system.getID();
BlockingQueue<Object> receiver = new ArrayBlockingQueue<>(1);
REQUESTS.put(id, new Request(sublevel, receiver));
sublevel.enableIndividualQueuedForcesTracking(true);
Object retVal = receiver.poll(100, TimeUnit.MILLISECONDS);
sublevel.enableIndividualQueuedForcesTracking(false);
return retVal;
}

private record Request(ServerSubLevel subLevel, BlockingQueue<Object> receiver) { }

private static Map<String, Map<Integer, Map<String, Object>>> createValueMap(ServerSubLevel level) {
Map<String, Map<Integer, Map<String, Object>>> returnValue = new HashMap<>();
Map<ForceGroup, QueuedForceGroup> forceGroups = level.getQueuedForceGroups();

{
final Vector3dc centerOfMass = level.getMassTracker().getCenterOfMass();
final Pose3d pose = level.logicalPose();
final Vector3d localGravity = pose.transformNormalInverse(DimensionPhysicsData.getGravity(level.getLevel())).mul(level.getMassTracker().getMass());

Map<Integer, Map<String, Object>> force = new HashMap<>();
Map<String, Object> gravityMap = new HashMap<>();
gravityMap.put("position", CCSableUtils.toLua(centerOfMass));
gravityMap.put("force", CCSableUtils.toLua(localGravity));

force.put(1, gravityMap);
returnValue.put(Sable.sablePath("gravity").toString() /* thanks veil (?) for making life difficult @todo: hardcoded because veil is being annoying */, force);
}

if (forceGroups == null || forceGroups.isEmpty())
return returnValue;

SubLevelPhysicsSystem physicsSystem = SubLevelPhysicsSystem.get(level.getLevel());
final double timeStep = 1.0 / 20.0 / physicsSystem.getConfig().substepsPerTick; // see DiagramEntity of aeronautics

for (Map.Entry<ForceGroup, QueuedForceGroup> set : forceGroups.entrySet()) {
Map<Integer, Map<String, Object>> force = new HashMap<>();

List<QueuedForceGroup.PointForce> pointForces = set.getValue().getRecordedPointForces();
if (pointForces.isEmpty())
continue;


int index = 1; // not a big fan of for loops
for (QueuedForceGroup.PointForce pointForce : pointForces) {

Map<String, Object> pointForceLua = new HashMap<>();

pointForceLua.put("position", CCSableUtils.toLua(pointForce.point()));
pointForceLua.put("force", CCSableUtils.toLua(new Vector3d(pointForce.force()).div(timeStep)));

force.put(index, pointForceLua);
index++;
}

ResourceLocation key = ForceGroups.REGISTRY.getKey(set.getKey());
returnValue.put(key.toString(), force);
}

return returnValue;
}
}
Comment thread
TechTastic marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,12 @@
-- @treturn matrix the inverse inertia tensor of the Sub-Level
-- @raise This method errors if there is no Sub-Level associated with the computer.

--- Gets all forces acting upon the sublevel.
-- @function getForces
-- @treturn table All forces in the format { TYPE = { [1] = {position, force}, ... }, ... }
-- @raise This method errors if there is no Sub-Level associated with the computer.


if not sublevel then
error("Cannot load Sub-Level API on computer")
end
Expand Down Expand Up @@ -111,6 +117,22 @@ for k,v in pairs(native) do
end
return matrix.from2DArray(result)
end
elseif k == "getForces" then
env[k] = function()
local result, err = v()
if err then
error(err)
end

for name, force in pairs(result) do
for i, point in ipairs(force) do
point.position = vector.new(point.position.x, point.position.y, point.position.z)
point.force = vector.new(point.force.x, point.force.y, point.force.z)
end
end

return result
end
else
env[k] = v
end
Expand Down