Compare commits
8 Commits
4a7b57c47f
...
0c5775560c
| Author | SHA1 | Date | |
|---|---|---|---|
| 0c5775560c | |||
| a1fdca689f | |||
| b9fcbd9040 | |||
| ba05ff7645 | |||
| 14f7b6c6df | |||
| f8f5f5e5c7 | |||
| bf378deea2 | |||
| df39865c3d |
20
Makefile
20
Makefile
@@ -5,6 +5,7 @@ BUILD_DIR = build
|
|||||||
HAXE_FLAGS =
|
HAXE_FLAGS =
|
||||||
POLYFILLED_NAME = bundle.polyfill.lua
|
POLYFILLED_NAME = bundle.polyfill.lua
|
||||||
POLYFILL_SRC = src/polyfill.lua
|
POLYFILL_SRC = src/polyfill.lua
|
||||||
|
CREAFTOS_PATH = craftos
|
||||||
|
|
||||||
HAXE_PATH := $(BUILD_DIR)/$(HAXE_NAME)
|
HAXE_PATH := $(BUILD_DIR)/$(HAXE_NAME)
|
||||||
MIN_PATH := $(BUILD_DIR)/$(MINIFYD_NAME)
|
MIN_PATH := $(BUILD_DIR)/$(MINIFYD_NAME)
|
||||||
@@ -12,31 +13,38 @@ POLYFILL_PATH := $(BUILD_DIR)/$(POLYFILLED_NAME)
|
|||||||
|
|
||||||
all: clean build
|
all: clean build
|
||||||
|
|
||||||
|
build: HAXE_FLAGS += --main kernel.Entrypoint -D analyzer-optimize
|
||||||
build: $(MIN_PATH)
|
build: $(MIN_PATH)
|
||||||
|
|
||||||
debug: HAXE_FLAGS += -D webconsole -D error_stack --debug
|
debug: HAXE_FLAGS += -D webconsole -D error_stack --debug
|
||||||
debug: build
|
debug: build
|
||||||
|
|
||||||
$(HAXE_PATH): $(shell find src -name '*.hx')
|
$(HAXE_PATH): $(shell find src -name '*.hx')
|
||||||
haxe build.hxml $(HAXE_FLAGS) --cmd "mv build/_haxe.lua $(HAXE_PATH)"
|
haxe build.hxml $(HAXE_FLAGS)
|
||||||
|
|
||||||
$(MIN_PATH): $(POLYFILL_PATH)
|
|
||||||
node minify.js $(POLYFILL_PATH) $@
|
|
||||||
|
|
||||||
$(POLYFILL_PATH): $(POLYFILL_SRC) $(HAXE_PATH)
|
$(POLYFILL_PATH): $(POLYFILL_SRC) $(HAXE_PATH)
|
||||||
cat $(POLYFILL_SRC) $(HAXE_PATH) > $@
|
cat $(POLYFILL_SRC) $(HAXE_PATH) > $@
|
||||||
|
|
||||||
deps: package.json build.hxml
|
$(MIN_PATH): $(POLYFILL_PATH)
|
||||||
|
node minify.js $(POLYFILL_PATH) $@
|
||||||
|
|
||||||
|
.PHONY: deps
|
||||||
|
deps:
|
||||||
haxelib install all --always && yarn install
|
haxelib install all --always && yarn install
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(BUILD_DIR)
|
rm -rf $(BUILD_DIR)
|
||||||
|
mkdir $(BUILD_DIR)
|
||||||
|
|
||||||
|
.PHONY: watch
|
||||||
watch:
|
watch:
|
||||||
find src -name "*.hx" | entr make debug
|
find src -name "*.hx" | entr make debug
|
||||||
|
|
||||||
|
.PHONY: emulator
|
||||||
emulator:
|
emulator:
|
||||||
craftos --mount-ro /=build
|
$(CREAFTOS_PATH) --mount-ro /=$(shell pwd)/$(BUILD_DIR)
|
||||||
|
|
||||||
|
.PHONY: webconsole
|
||||||
webconsole:
|
webconsole:
|
||||||
node console.js
|
node console.js
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ run `make deps && make`. The `bundle.min.lua` inside the `build` dir is the fina
|
|||||||
|
|
||||||
# Useful links
|
# Useful links
|
||||||
|
|
||||||
[CC lua code](https://github.com/cc-tweaked/CC-Tweaked/tree/mc-1.16.x/src/main/resources/data/computercraft/lua)
|
[CC lua code](https://github.com/cc-tweaked/CC-Tweaked/tree/mc-1.19.x/projects/core/src/main/resources/data/computercraft/lua)
|
||||||
|
|
||||||
[CC wiki](https://tweaked.cc/)
|
[CC wiki](https://tweaked.cc/)
|
||||||
|
|
||||||
@@ -38,6 +38,7 @@ Run `make watch` to recompile when a file changed.
|
|||||||
## Emulator
|
## Emulator
|
||||||
|
|
||||||
You could use Minecraft to run the program or you could use [craftos pc](https://www.craftos-pc.cc/) as an emulator. Just install it and run `make emulator`.
|
You could use Minecraft to run the program or you could use [craftos pc](https://www.craftos-pc.cc/) as an emulator. Just install it and run `make emulator`.
|
||||||
|
There is an AppImage available [here](https://github.com/MCJack123/craftos2/releases).
|
||||||
|
|
||||||
## Websconsole
|
## Websconsole
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
-p src
|
-p src
|
||||||
--main kernel.Entrypoint
|
|
||||||
|
|
||||||
--library cctweaked:git:https://git.kapelle.org/niklas/cctweaked-haxelib.git
|
--library cctweaked:git:https://git.kapelle.org/niklas/cctweaked-haxelib.git
|
||||||
--library tink_core
|
--library tink_core
|
||||||
@@ -9,4 +8,4 @@
|
|||||||
-D lua-vanilla
|
-D lua-vanilla
|
||||||
-D lua-ver 5.1
|
-D lua-ver 5.1
|
||||||
|
|
||||||
--lua build/_haxe.lua
|
--lua build/haxe.lua
|
||||||
|
|||||||
@@ -4,7 +4,13 @@ import kernel.log.Log;
|
|||||||
|
|
||||||
class Entrypoint {
|
class Entrypoint {
|
||||||
public static function main() {
|
public static function main() {
|
||||||
|
try {
|
||||||
Init.initKernel();
|
Init.initKernel();
|
||||||
|
}catch(e){
|
||||||
|
Log.error('Error in init: ${e.toString()}');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Startup.main();
|
Startup.main();
|
||||||
}catch(e){
|
}catch(e){
|
||||||
|
|||||||
@@ -13,6 +13,10 @@ import kernel.peripherals.Peripherals.Peripheral;
|
|||||||
import kernel.net.Net;
|
import kernel.net.Net;
|
||||||
|
|
||||||
class Init {
|
class Init {
|
||||||
|
|
||||||
|
@:allow(kernel.KernelEvents)
|
||||||
|
private static var mainEvent:MainEvent;
|
||||||
|
|
||||||
public static function initKernel() {
|
public static function initKernel() {
|
||||||
// Init singeltons here because haxe is confused about the order to create them.
|
// Init singeltons here because haxe is confused about the order to create them.
|
||||||
Log.instance = new Log();
|
Log.instance = new Log();
|
||||||
@@ -44,9 +48,8 @@ class Init {
|
|||||||
FS.makeDir("/var/ns");
|
FS.makeDir("/var/ns");
|
||||||
}
|
}
|
||||||
|
|
||||||
MainLoop.add(()->{
|
Init.mainEvent = MainLoop.add(()->{
|
||||||
KernelEvents.instance.startEventLoop();
|
KernelEvents.instance.startEventLoop();
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
package kernel;
|
package kernel;
|
||||||
|
|
||||||
|
import haxe.MainLoop;
|
||||||
|
import cc.OS;
|
||||||
import kernel.log.Log;
|
import kernel.log.Log;
|
||||||
import lib.Pos;
|
import lib.Pos;
|
||||||
import cc.HTTP.HTTPResponse;
|
import cc.HTTP.HTTPResponse;
|
||||||
import lua.TableTools;
|
import lua.TableTools;
|
||||||
import lua.Coroutine;
|
import lua.Coroutine;
|
||||||
import lib.Vec.Vec2;
|
|
||||||
import haxe.Exception;
|
import haxe.Exception;
|
||||||
|
|
||||||
using tink.CoreApi;
|
using tink.CoreApi;
|
||||||
@@ -95,6 +96,8 @@ class KernelEvents {
|
|||||||
private final onWebsocketMessageTrigger:SignalTrigger<{url:String, message:String, isBinary:Bool}> = Signal.trigger();
|
private final onWebsocketMessageTrigger:SignalTrigger<{url:String, message:String, isBinary:Bool}> = Signal.trigger();
|
||||||
private final onWebsocketSuccessTrigger:SignalTrigger<{url:String, handle:Any}> = Signal.trigger();
|
private final onWebsocketSuccessTrigger:SignalTrigger<{url:String, handle:Any}> = Signal.trigger();
|
||||||
|
|
||||||
|
private var stopLoop:Bool = false;
|
||||||
|
|
||||||
@:allow(kernel.Init)
|
@:allow(kernel.Init)
|
||||||
private function new() {
|
private function new() {
|
||||||
this.onAlarm = onAlarmTrigger.asSignal();
|
this.onAlarm = onAlarmTrigger.asSignal();
|
||||||
@@ -132,15 +135,26 @@ class KernelEvents {
|
|||||||
/**
|
/**
|
||||||
Start pulling events. Blocking.
|
Start pulling events. Blocking.
|
||||||
**/
|
**/
|
||||||
public function startEventLoop() {
|
@:allow(kernel.Init)
|
||||||
while (true) {
|
private function startEventLoop() {
|
||||||
|
while (!stopLoop) {
|
||||||
var event:Table<Int, Dynamic> = pullEvents();
|
var event:Table<Int, Dynamic> = pullEvents();
|
||||||
|
|
||||||
var eventName:String = event[1];
|
var eventName:String = event[1];
|
||||||
|
try {
|
||||||
fireSignal(eventName,event);
|
fireSignal(eventName,event);
|
||||||
|
}catch(e:Dynamic) {
|
||||||
|
Log.error('Error while handling event: $eventName: ${e}');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function shutdown() {
|
||||||
|
Log.info('Shutting down event loop');
|
||||||
|
this.stopLoop = true;
|
||||||
|
MainTerm.instance.reset();
|
||||||
|
Init.mainEvent.stop();
|
||||||
|
}
|
||||||
|
|
||||||
private function pullEvents():Table<Int, Dynamic> {
|
private function pullEvents():Table<Int, Dynamic> {
|
||||||
return cast TableTools.pack(Coroutine.yield(null));
|
return cast TableTools.pack(Coroutine.yield(null));
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package kernel.gps;
|
package kernel.gps;
|
||||||
|
|
||||||
|
import kernel.log.Log;
|
||||||
import lib.KVStore;
|
import lib.KVStore;
|
||||||
import kernel.net.Net;
|
import kernel.net.Net;
|
||||||
import kernel.net.INetworkInterface;
|
import kernel.net.INetworkInterface;
|
||||||
import kernel.net.Package;
|
import kernel.net.Package;
|
||||||
import lib.Pos3;
|
import lib.Pos3;
|
||||||
|
|
||||||
|
using tink.CoreApi;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Determines the position of the computer based on the distance to other computers.
|
Determines the position of the computer based on the distance to other computers.
|
||||||
When receiving a message from another computer via wireless, the distance is also received.
|
When receiving a message from another computer via wireless, the distance is also received.
|
||||||
@@ -15,6 +18,7 @@ class GPS {
|
|||||||
public static var instance:GPS;
|
public static var instance:GPS;
|
||||||
|
|
||||||
private var shouldRespond = true;
|
private var shouldRespond = true;
|
||||||
|
private var shouldDoWholeNumberCheck = true;
|
||||||
private var posAccuracy = 0; // 0 = unkown, 1 = (ins,best guess), 2 = (stored/manual,should be right), 3 = (gps,confirmed)
|
private var posAccuracy = 0; // 0 = unkown, 1 = (ins,best guess), 2 = (stored/manual,should be right), 3 = (gps,confirmed)
|
||||||
private var cachedPosition:Pos3;
|
private var cachedPosition:Pos3;
|
||||||
private var lastPositionResponse: Array<{pos:Pos3,dist:Float}> = [];
|
private var lastPositionResponse: Array<{pos:Pos3,dist:Float}> = [];
|
||||||
@@ -112,12 +116,18 @@ class GPS {
|
|||||||
var response = new Package(Net.instance.networkID,pack.fromID, pack.msgID, GPSResponse(cachedPosition),null,0);
|
var response = new Package(Net.instance.networkID,pack.fromID, pack.msgID, GPSResponse(cachedPosition),null,0);
|
||||||
iface.send(pack.fromID,Net.instance.networkID,response);
|
iface.send(pack.fromID,Net.instance.networkID,response);
|
||||||
case GPSResponse(pos):
|
case GPSResponse(pos):
|
||||||
if (lastPositionResponse.contains({pos:pos,dist:dist})) return;
|
if (lastPositionResponse.contains({pos:pos,dist:dist})) return; // Ignore duplicate responses
|
||||||
lastPositionResponse.push({pos:pos,dist:dist});
|
|
||||||
if (lastPositionResponse.length > 5) lastPositionResponse.shift();
|
lastPositionResponse.push({pos:pos,dist:dist});
|
||||||
if (lastPositionResponse.length < 3) return;
|
|
||||||
|
// TODO: wait for a few seconds before calculating the position, so we can get more responses
|
||||||
|
|
||||||
|
if (lastPositionResponse.length < 4) return; // We need at least 3 responses to calculate the position
|
||||||
|
|
||||||
|
var calculatedPosition = calculatePosition().round();
|
||||||
|
|
||||||
|
lastPositionResponse = []; // Reset the response array
|
||||||
|
|
||||||
var calculatedPosition = calculatePosition();
|
|
||||||
if (calculatedPosition == null) return;
|
if (calculatedPosition == null) return;
|
||||||
cachedPosition = calculatedPosition;
|
cachedPosition = calculatedPosition;
|
||||||
posAccuracy = 3;
|
posAccuracy = 3;
|
||||||
@@ -137,62 +147,46 @@ class GPS {
|
|||||||
var r2 = lastPositionResponse[1].dist;
|
var r2 = lastPositionResponse[1].dist;
|
||||||
var r3 = lastPositionResponse[2].dist;
|
var r3 = lastPositionResponse[2].dist;
|
||||||
|
|
||||||
return trilateration(p1,p2,p3,r1,r2,r3);
|
var result = trilateration(p1,p2,p3,r1,r2,r3);
|
||||||
|
|
||||||
// var calculatedPositions: Array<Pos3> = [];
|
if (result.a.close(result.b)) return result.a;
|
||||||
|
|
||||||
// // Loop through all possible permutations of the last 3 responses
|
// If we have more than 3 responses, we can use the 4th response to determine which of the two positions is correct
|
||||||
// for (i in 0...lastPositionResponse.length) {
|
// TODO: if this is a pocket computer we cant use this since it can move freely
|
||||||
// for (j in 0...lastPositionResponse.length) {
|
if (lastPositionResponse.length > 3){
|
||||||
// if (i == j) continue;
|
var err1 = Math.abs(result.a.distance(lastPositionResponse[3].pos) - lastPositionResponse[3].dist);
|
||||||
// for (k in 0...lastPositionResponse.length) {
|
var err2 = Math.abs(result.b.distance(lastPositionResponse[3].pos) - lastPositionResponse[3].dist);
|
||||||
// if (i == k || j == k) continue;
|
|
||||||
|
|
||||||
// var p1 = lastPositionResponse[i].pos;
|
if (Math.abs(err1 - err2) < 0.0001) {
|
||||||
// var p2 = lastPositionResponse[j].pos;
|
Log.warn("Failed to determine GPS position via 4th fix");
|
||||||
// var p3 = lastPositionResponse[k].pos;
|
return null; // The two positions are essentially the same, so we cant determine which one is correct
|
||||||
|
|
||||||
// var r1 = lastPositionResponse[i].dist;
|
|
||||||
// var r2 = lastPositionResponse[j].dist;
|
|
||||||
// var r3 = lastPositionResponse[k].dist;
|
|
||||||
|
|
||||||
// calculatedPositions.push(trilateration(p1,p2,p3,r1,r2,r3));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var tainted = false;
|
|
||||||
// // Check if all calculated positions are the same
|
|
||||||
// for (i in 0...calculatedPositions.length) {
|
|
||||||
// for (j in 0...calculatedPositions.length) {
|
|
||||||
// if (i == j) continue;
|
|
||||||
// if (calculatedPositions[i] != calculatedPositions[j]){
|
|
||||||
// Log.warn("GPS not all calculated positions are the same");
|
|
||||||
// tainted = true;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!tainted) return calculatedPositions[0];
|
|
||||||
|
|
||||||
// // Get the most common position
|
|
||||||
// var mostCommon:Pos3 = null;
|
|
||||||
// var mostCommonCount = 0;
|
|
||||||
// for (i in 0...calculatedPositions.length) {
|
|
||||||
// var count = 0;
|
|
||||||
// for (j in 0...calculatedPositions.length) {
|
|
||||||
// if (calculatedPositions[i] == calculatedPositions[j]) count++;
|
|
||||||
// }
|
|
||||||
// if (count > mostCommonCount) {
|
|
||||||
// mostCommon = calculatedPositions[i];
|
|
||||||
// mostCommonCount = count;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return mostCommon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function trilateration(p1:Pos3,p2:Pos3,p3: Pos3,r1:Float,r2:Float,r3:Float):Pos3 {
|
if (err1 < err2) return result.a;
|
||||||
|
if (err2 < err1) return result.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
// last resort, just use the position that is closest to a whole number (whithin a resonable margin of error)
|
||||||
|
if (!shouldDoWholeNumberCheck) return null;
|
||||||
|
|
||||||
|
// TODO: mark the position as not so accurate if we use this method
|
||||||
|
|
||||||
|
var err1 = (result.a - result.a.round()).length();
|
||||||
|
var err2 = (result.b - result.b.round()).length();
|
||||||
|
|
||||||
|
if (err1 < err2 && err1 < 0.0001) {
|
||||||
|
return result.a;
|
||||||
|
} else if (err2 < 0.0001) {
|
||||||
|
return result.b;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Determines the position(s) of a point given 3 other points and the distance to each of them.
|
||||||
|
**/
|
||||||
|
private function trilateration(p1:Pos3,p2:Pos3,p3: Pos3,r1:Float,r2:Float,r3:Float):Pair<Pos3,Pos3> {
|
||||||
var a2b = p2 - p1;
|
var a2b = p2 - p1;
|
||||||
var a2c = p3 - p1;
|
var a2c = p3 - p1;
|
||||||
|
|
||||||
@@ -211,9 +205,9 @@ class GPS {
|
|||||||
var zSquared = r1 * r1 - x * x - y * y;
|
var zSquared = r1 * r1 - x * x - y * y;
|
||||||
if (zSquared > 0) {
|
if (zSquared > 0) {
|
||||||
var z = Math.sqrt(zSquared);
|
var z = Math.sqrt(zSquared);
|
||||||
result += ez * z;
|
return new Pair(result + (ez * z),result - (ez * z));
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return new Pair(result,result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,12 +53,11 @@ class Log {
|
|||||||
if (logLines.length > MAX_LINES) {
|
if (logLines.length > MAX_LINES) {
|
||||||
logLines.shift();
|
logLines.shift();
|
||||||
}
|
}
|
||||||
|
onLogTrigger.trigger(line);
|
||||||
|
|
||||||
#if webconsole
|
#if webconsole
|
||||||
Debug.printWeb('[${Std.string(line.level)}][${line.origin}] ${line.message}');
|
Debug.printWeb('[${Std.string(line.level)}][${line.origin}] ${line.message}');
|
||||||
#end
|
#end
|
||||||
|
|
||||||
onLogTrigger.trigger(line);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getLines():ReadOnlyArray<LogLine> {
|
public function getLines():ReadOnlyArray<LogLine> {
|
||||||
|
|||||||
@@ -130,6 +130,7 @@ class HomeContext {
|
|||||||
|
|
||||||
children.push(new TextElement('Add Terminal', {onClick: this.addTerminal}));
|
children.push(new TextElement('Add Terminal', {onClick: this.addTerminal}));
|
||||||
children.push(new TextElement('Add Log', {onClick: this.addLog}));
|
children.push(new TextElement('Add Log', {onClick: this.addLog}));
|
||||||
|
children.push(new TextElement('Exit', {onClick: KernelEvents.instance.shutdown}));
|
||||||
|
|
||||||
renderer.setChildren(children);
|
renderer.setChildren(children);
|
||||||
|
|
||||||
|
|||||||
@@ -96,4 +96,16 @@ abstract Pos3(Vec3<Float>) from Vec3<Float> to Vec3<Float>{
|
|||||||
public function toString():String {
|
public function toString():String {
|
||||||
return 'Pos3(${this.x}, ${this.y}, ${this.z})';
|
return 'Pos3(${this.x}, ${this.y}, ${this.z})';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function round():Pos3 {
|
||||||
|
return new Pos3({
|
||||||
|
x: Math.fround(this.x),
|
||||||
|
y: Math.fround(this.y),
|
||||||
|
z: Math.fround(this.z)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function distance(rhs:Pos3):Float {
|
||||||
|
return Math.sqrt(Math.pow(this.x - rhs.x, 2) + Math.pow(this.y - rhs.y, 2) + Math.pow(this.z - rhs.z, 2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user