Compare commits

...

2 Commits

Author SHA1 Message Date
86f6dbf302 added Pocket 2024-04-10 14:40:45 +02:00
4836cae3fa added speaker peripheral 2024-04-09 20:07:36 +02:00
4 changed files with 203 additions and 0 deletions

95
src/bin/Speaker.hx Normal file
View File

@@ -0,0 +1,95 @@
package bin;
import kernel.peripherals.Peripherals.Peripheral;
import lib.CLIAppBase;
using tink.CoreApi;
@:build(macros.Binstore.includeBin("Speaker", ["speaker", "sp"]))
class Speaker extends CLIAppBase {
public function new() {
registerSyncSubcommand("note", (args) -> {
if (args.length < 2) {
handle.writeLine("Not enough args");
return false;
}
var sp = Peripheral.getSpeaker(args[0]);
var note = args[1];
var r;
if (args.length > 3) {
var volume = Std.parseFloat(args[2]);
if (volume == null) {
handle.writeLine("Failed to parse volume");
return false;
}
if (args.length > 4) {
var pitch = Std.parseInt(args[3]);
if (pitch == null) {
handle.writeLine("Failed to parse pitch");
return false;
}
r = sp.playNote(note, volume, pitch);
} else {
r = sp.playNote(note, volume);
}
} else {
r = sp.playNote(note);
}
switch r {
case Failure(failure):
handle.writeLine(failure);
return false;
case Success(_):
return true;
}
}, "<addr> <note> [pitch] [volume]");
registerSyncSubcommand("sound", (args) -> {
if (args.length < 2) {
handle.writeLine("Not enough args");
return false;
}
var sp = Peripheral.getSpeaker(args[0]);
var sound = args[1];
var r;
if (args.length > 3) {
var volume = Std.parseFloat(args[2]);
if (volume == null) {
handle.writeLine("Failed to parse volume");
return false;
}
if (args.length > 4) {
var pitch = Std.parseFloat(args[3]);
if (pitch == null) {
handle.writeLine("Failed to parse pitch");
return false;
}
r = sp.playSound(sound, volume, pitch);
} else {
r = sp.playSound(sound, volume);
}
} else {
r = sp.playSound(sound);
}
switch r {
case Failure(failure):
handle.writeLine(failure);
return false;
case Success(_):
return true;
}
}, "<addr> <sound> [volume] [pitch]");
}
}

View File

@@ -81,6 +81,8 @@ class Peripheral {
return getModem(addr); return getModem(addr);
case Printer.TYPE_NAME: case Printer.TYPE_NAME:
return getPrinter(addr); return getPrinter(addr);
case Speaker.TYPE_NAME:
return getSpeaker(addr);
case "redstone": case "redstone":
return getRedstone(addr); return getRedstone(addr);
} }
@@ -158,4 +160,15 @@ class Peripheral {
public static function getAllComputers():Array<Computer> { public static function getAllComputers():Array<Computer> {
return [for (addr in findAddrByType(Computer.TYPE_NAME)) new Computer(addr)]; return [for (addr in findAddrByType(Computer.TYPE_NAME)) new Computer(addr)];
} }
public static function getSpeaker(addr:String):Null<Speaker> {
var addr = safeGetAddr(addr, Speaker.TYPE_NAME);
if (addr == null)
return null;
return new Speaker(addr);
}
public static function getAllSpeakers():Array<Speaker> {
return [for (addr in findAddrByType(Speaker.TYPE_NAME)) new Speaker(addr)];
}
} }

View File

@@ -0,0 +1,61 @@
package kernel.peripherals;
import cc.Peripheral;
using tink.CoreApi;
class Speaker implements IPeripheral {
public static inline final TYPE_NAME:String = "speaker";
private final addr:String;
public function new(addr:String) {
this.addr = addr;
}
public function getType():String {
return Speaker.TYPE_NAME;
}
public function getAddr():String {
return this.addr;
}
/**
Plays a note block note through the speaker.
The pitch argument uses semitones as the unit. This directly maps to the number of clicks on a note block.
For reference, 0, 12, and 24 map to F#, and 6 and 18 map to C.
A maximum of 8 notes can be played in a single tick. If this limit is hit, this function will return an error.
**/
public function playNote(instrument:String, ?volume:Float = 1.0, ?pitch:Int = 12):Outcome<Noise, String> {
if (Peripheral.call(addr, "playNote", instrument, volume, pitch)) {
return Success(null);
} else {
return Failure("maximum reached");
}
}
public function playSound(sound:String, ?volume:Float = 1.0, ?pitch:Float = 1.0):Outcome<Noise, String> {
try {
if (Peripheral.call(addr, "playSound", sound, volume, pitch)) {
return Success(null);
} else {
return Failure("Sound still playing");
}
} catch (e) {
return Failure("Sound does not exist");
}
}
public function playAudio(buffer:Array<Int>, ?volume:Float = 1.0):Outcome<Noise, String> {
try {
if (Peripheral.call(addr, "playAudio", buffer, volume)) {
return Success(null);
} else {
return Failure("Buffer full");
}
} catch (e) {
return Failure("Buffer malformed");
}
}
}

View File

@@ -0,0 +1,34 @@
package kernel.pocket;
using tink.CoreApi;
class Pocket {
public static function isPocket():Bool {
return cc.Pocket != null;
}
/**
Search the player's inventory for another upgrade, replacing the existing one with that item if found.
This inventory search starts from the player's currently selected slot, allowing you to prioritise upgrades.
**/
public static function equipBack():Outcome<Noise, String> {
var r = cc.Pocket.equipBack();
if (r.successful) {
return Success(Noise);
}
return Failure(r.error);
}
/**
Remove the pocket computer's current upgrade.
**/
public static function unequipBack():Outcome<Noise, String> {
var r = cc.Pocket.unequipBack();
if (r.successful) {
return Success(Noise);
}
return Failure(r.error);
}
}