Track LocalMods as part of monolith
This commit is contained in:
5
LocalMods/MicroLua/CSharp/RunConfig.xml
Executable file
5
LocalMods/MicroLua/CSharp/RunConfig.xml
Executable file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RunConfig>
|
||||
<Server>Standard</Server>
|
||||
<Client>Standard</Client>
|
||||
</RunConfig>
|
||||
167
LocalMods/MicroLua/CSharp/Shared/MicroLua.cs
Executable file
167
LocalMods/MicroLua/CSharp/Shared/MicroLua.cs
Executable file
@@ -0,0 +1,167 @@
|
||||
// SPDX-FileCopyrightText: 2023 Matheus Izvekov <mizvekov@gmail.com>
|
||||
// SPDX-License-Identifier: ISC
|
||||
|
||||
using Barotrauma;
|
||||
using Barotrauma.Items.Components;
|
||||
using Barotrauma.Networking;
|
||||
using MoonSharp.Interpreter.Interop;
|
||||
using MoonSharp.Interpreter;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace miz {
|
||||
partial class MicroLua : ItemComponent, IServerSerializable {
|
||||
private readonly static Regex inpRegex = new Regex(@"^signal_in(\d+)$");
|
||||
private readonly static Regex outRegex = new Regex(@"^signal_out(\d+)$");
|
||||
private List<Connection> outConns = new();
|
||||
|
||||
private Script script;
|
||||
|
||||
private readonly struct EventData : IEventData {
|
||||
public readonly string data;
|
||||
public EventData(string data) { this.data = data; }
|
||||
}
|
||||
|
||||
private void handleException(string source, InterpreterException e) {
|
||||
LuaCsLogger.LogError($"[{Item}] [{source}] {e.DecoratedMessage}", LuaCsMessageOrigin.LuaMod);
|
||||
}
|
||||
|
||||
private bool toNumber(string s, out double value) {
|
||||
return double.TryParse(s, NumberStyles.AllowLeadingSign | NumberStyles.AllowDecimalPoint,
|
||||
CultureInfo.InvariantCulture, out value);
|
||||
}
|
||||
|
||||
private string source;
|
||||
[InGameEditable, Serialize("", IsPropertySaveable.Yes, description: "The Lua source code.", alwaysUseInstanceValues: true)]
|
||||
public string Source {
|
||||
get => source;
|
||||
set {
|
||||
if (value == null) { return; }
|
||||
source = value;
|
||||
script = null;
|
||||
IsActive = false;
|
||||
|
||||
if (source.IsNullOrWhiteSpace()) { return; }
|
||||
Script newscript = new(CoreModules.Preset_HardSandbox | CoreModules.Metatables |
|
||||
CoreModules.ErrorHandling | CoreModules.Coroutine);
|
||||
newscript.Options.DebugPrint = (string o) => LuaCsLogger.LogMessage($"[{Item}] {o}");
|
||||
newscript.Options.CheckThreadAccess = false;
|
||||
|
||||
newscript.Globals.Get("table").Table["clear"] = (Table t) => t.Clear();
|
||||
|
||||
// MoonSharp's tonumber is too permissive. However, ours does not support base.
|
||||
newscript.Globals["tonumber"] = double? (string s) => toNumber(s, out double value) ? value : null;
|
||||
|
||||
newscript.Globals["mode"] = GameMain.NetworkMember?.IsClient switch {
|
||||
null => "single", false => "server", true => "client"
|
||||
};
|
||||
newscript.Globals["out"] = UserData.Create(this, new OutDesc());
|
||||
newscript.Globals["time"] = () => GameMain.GameScreen.GameTime;
|
||||
|
||||
if (GameMain.NetworkMember is not null) {
|
||||
#if SERVER
|
||||
newscript.Globals["send"] = (string data) => item.CreateServerEvent(this, new EventData(data));
|
||||
#endif
|
||||
}
|
||||
|
||||
try { newscript.DoString(source, codeFriendlyName: "source"); }
|
||||
catch (SyntaxErrorException e) {
|
||||
handleException("syntax", e);
|
||||
return;
|
||||
}
|
||||
catch (ScriptRuntimeException e) {
|
||||
handleException("runtime", e);
|
||||
return;
|
||||
}
|
||||
|
||||
IsActive = true;
|
||||
script = newscript;
|
||||
}
|
||||
}
|
||||
|
||||
public MicroLua(Item item, ContentXElement element) : base(item, element) {}
|
||||
|
||||
class OutDesc : IUserDataDescriptor {
|
||||
public string Name {
|
||||
get { return "out"; }
|
||||
}
|
||||
public Type Type {
|
||||
get { return typeof(OutDesc); }
|
||||
}
|
||||
|
||||
public DynValue Index(Script script, object obj, DynValue index, bool isDirectIndexing) {
|
||||
throw new ScriptRuntimeException("__index metamethod not implemented");
|
||||
}
|
||||
public bool SetIndex(Script script, object obj, DynValue index, DynValue value, bool isDirectIndexing) {
|
||||
var parent = (MicroLua)obj;
|
||||
if (index.Type != DataType.Number) { throw new ScriptRuntimeException("pin must be an integer"); }
|
||||
var indexNumber = index.Number;
|
||||
var pin = (int)indexNumber;
|
||||
if ((double)pin != indexNumber) { throw new ScriptRuntimeException("pin must be an integer"); }
|
||||
|
||||
if (pin < 0 || pin > parent.outConns.Count) { throw new ScriptRuntimeException($"invalid pin {pin}"); }
|
||||
var connection = parent.outConns[pin - 1] ?? throw new ScriptRuntimeException($"invalid pin {pin}");
|
||||
parent.item.SendSignal(new Signal(value.Type switch {
|
||||
DataType.Number => value.Number.ToString(CultureInfo.InvariantCulture),
|
||||
DataType.String => value.String,
|
||||
_ => throw new ScriptRuntimeException($"invalid value type {value.Type}")
|
||||
}), connection);
|
||||
|
||||
return true;
|
||||
}
|
||||
public string AsString(object obj) { throw new ScriptRuntimeException("__tostring metamethod not implemented"); }
|
||||
public DynValue MetaIndex(Script script, object obj, string metaname) { throw new ScriptRuntimeException($"{metaname} metamethod not implemented"); }
|
||||
public bool IsTypeCompatible(Type type, object obj) { return type.IsInstanceOfType(obj); }
|
||||
};
|
||||
|
||||
public override void OnItemLoaded() {
|
||||
base.OnItemLoaded();
|
||||
foreach(var connection in item.Connections) {
|
||||
var match = outRegex.Match(connection.Name);
|
||||
if (!match.Success) { continue; }
|
||||
var index = int.Parse(match.Groups[1].Value);
|
||||
outConns.Insert(index - 1, connection);
|
||||
}
|
||||
}
|
||||
|
||||
private void Call(string field, params object[] objs) {
|
||||
DynValue cb = script.Globals.Get(field);
|
||||
if (cb.Type == DataType.Nil) { return; }
|
||||
try { script.Call(cb, objs); }
|
||||
catch (ScriptRuntimeException e) { handleException(field, e); }
|
||||
}
|
||||
|
||||
public override void Update(float deltaTime, Camera cam) { Call("upd", deltaTime); }
|
||||
|
||||
public override void ReceiveSignal(Signal signal, Connection connection) {
|
||||
if (script == null) { return; }
|
||||
|
||||
var match = inpRegex.Match(connection.Name);
|
||||
if (!match.Success) { return; }
|
||||
|
||||
var index = int.Parse(match.Groups[1].Value);
|
||||
var value = toNumber(signal.value, out double dynvalue) ? DynValue.NewNumber(dynvalue) :
|
||||
DynValue.NewString(signal.value);
|
||||
DynValue inp = script.Globals.Get("inp");
|
||||
switch(inp.Type) {
|
||||
case DataType.Nil: break;
|
||||
case DataType.Table: inp.Table.Set(index, value); break;
|
||||
default:
|
||||
try { script.Call(inp, index, value); }
|
||||
catch (ScriptRuntimeException e) { handleException("inp", e); }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if CLIENT
|
||||
public void ClientEventRead(IReadMessage msg, float sendingTime) { Call("recv", msg.ReadString()); }
|
||||
#endif
|
||||
#if SERVER
|
||||
public void ServerEventWrite(IWriteMessage msg, Client c, NetEntityEvent.IData extraData) {
|
||||
msg.WriteString(ExtractEventData<EventData>(extraData).data);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
6
LocalMods/MicroLua/MicroLua.Eng.Txt.xml
Executable file
6
LocalMods/MicroLua/MicroLua.Eng.Txt.xml
Executable file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<infotexts language="English" nowhitespace="false" translatedname="English">
|
||||
<entityname.miz.microlua>MicroLua Component</entityname.miz.microlua>
|
||||
<entitydescription.miz.microlua>Sends signals as programmed by the user, configured in the source box.</entitydescription.miz.microlua>
|
||||
<circuitboxnode.miz.microlua>MicroLua</circuitboxnode.miz.microlua>
|
||||
</infotexts>
|
||||
BIN
LocalMods/MicroLua/MicroLua.Inv.png
Executable file
BIN
LocalMods/MicroLua/MicroLua.Inv.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 3.3 KiB |
6
LocalMods/MicroLua/MicroLua.Por.Txt.xml
Executable file
6
LocalMods/MicroLua/MicroLua.Por.Txt.xml
Executable file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<infotexts language="Brazilian Portuguese" nowhitespace="false" translatedname="Português brasileiro">
|
||||
<entityname.miz.microlua>Componente MicroLua</entityname.miz.microlua>
|
||||
<entitydescription.miz.microlua>Envia os sinais programados pelo usuário, configurado na caixa 'source'.</entitydescription.miz.microlua>
|
||||
<circuitboxnode.miz.microlua>MicroLua</circuitboxnode.miz.microlua>
|
||||
</infotexts>
|
||||
BIN
LocalMods/MicroLua/MicroLua.Spr.png
Executable file
BIN
LocalMods/MicroLua/MicroLua.Spr.png
Executable file
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
100
LocalMods/MicroLua/MicroLua.xml
Executable file
100
LocalMods/MicroLua/MicroLua.xml
Executable file
@@ -0,0 +1,100 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Items>
|
||||
<Item name="" identifier="miz.microlua" category="Electrical" Tags="smallitem,logic,circuitboxcomponent" maxstacksize="8" cargocontaineridentifier="metalcrate" description="" scale="0.5" impactsoundtag="impact_metal_light" isshootable="true">
|
||||
<Price baseprice="100" minleveldifficulty="15">
|
||||
<Price storeidentifier="merchantoutpost" />
|
||||
<Price storeidentifier="merchantcity" sold="false" />
|
||||
<Price storeidentifier="merchantresearch" multiplier="1.25" />
|
||||
<Price storeidentifier="merchantmilitary" />
|
||||
<Price storeidentifier="merchantmine" />
|
||||
<Price storeidentifier="merchantengineering" multiplier="0.9" />
|
||||
</Price>
|
||||
<PreferredContainer primary="engcab" />
|
||||
<PreferredContainer secondary="wreckengcab,abandonedengcab,outpostengcab,beaconengcab" amount="1" spawnprobability="0.05" />
|
||||
<Deconstruct time="10">
|
||||
<Item identifier="plastic" />
|
||||
<Item identifier="copper" />
|
||||
<Item identifier="tin" />
|
||||
</Deconstruct>
|
||||
<Fabricate suitablefabricators="fabricator" requiredtime="10">
|
||||
<RequiredSkill identifier="electrical" level="20" />
|
||||
<RequiredItem identifier="fpgacircuit" />
|
||||
<RequiredItem identifier="tin" />
|
||||
</Fabricate>
|
||||
<InventoryIcon texture="MicroLua.Inv.png" sourcerect="0,0,63,57" origin="0.5,0.5" />
|
||||
<Sprite texture="MicroLua.Spr.png" depth="0.8" sourcerect="0,0,32,32" origin="0.5,0.5" canflipx="false" />
|
||||
<MicroLua canbeselected="true" />
|
||||
<Body width="31" height="25" density="15" />
|
||||
<Holdable selectkey="Select" pickkey="Use" slots="Any,RightHand,LeftHand" msg="ItemMsgDetachWrench" PickingTime="5.0" aimpos="85,-10" handle1="0,0" attachable="true" aimable="true">
|
||||
<RequiredItem items="wrench" type="Equipped" />
|
||||
</Holdable>
|
||||
<ConnectionPanel selectkey="Action" canbeselected="true" msg="ItemMsgRewireScrewdriver" hudpriority="10">
|
||||
<GuiFrame relativesize="0.2,0.8" minsize="480,1200" maxsize="520,1300" anchor="Center" style="ConnectionPanel" />
|
||||
<RequiredItem items="screwdriver" type="Equipped" />
|
||||
<input name="signal_in1" displayname="connection.signalinx~[num]=1" />
|
||||
<input name="signal_in2" displayname="connection.signalinx~[num]=2" />
|
||||
<input name="signal_in3" displayname="connection.signalinx~[num]=3" />
|
||||
<input name="signal_in4" displayname="connection.signalinx~[num]=4" />
|
||||
<input name="signal_in5" displayname="connection.signalinx~[num]=5" />
|
||||
<input name="signal_in6" displayname="connection.signalinx~[num]=6" />
|
||||
<input name="signal_in7" displayname="connection.signalinx~[num]=7" />
|
||||
<input name="signal_in8" displayname="connection.signalinx~[num]=8" />
|
||||
<input name="signal_in9" displayname="connection.signalinx~[num]=9" />
|
||||
<input name="signal_in10" displayname="connection.signalinx~[num]=10" />
|
||||
<input name="signal_in11" displayname="connection.signalinx~[num]=11" />
|
||||
<input name="signal_in12" displayname="connection.signalinx~[num]=12" />
|
||||
<input name="signal_in13" displayname="connection.signalinx~[num]=13" />
|
||||
<input name="signal_in14" displayname="connection.signalinx~[num]=14" />
|
||||
<input name="signal_in15" displayname="connection.signalinx~[num]=15" />
|
||||
<input name="signal_in16" displayname="connection.signalinx~[num]=16" />
|
||||
<input name="signal_in17" displayname="connection.signalinx~[num]=17" />
|
||||
<input name="signal_in18" displayname="connection.signalinx~[num]=18" />
|
||||
<input name="signal_in19" displayname="connection.signalinx~[num]=19" />
|
||||
<input name="signal_in20" displayname="connection.signalinx~[num]=20" />
|
||||
<input name="signal_in21" displayname="connection.signalinx~[num]=21" />
|
||||
<input name="signal_in22" displayname="connection.signalinx~[num]=22" />
|
||||
<input name="signal_in23" displayname="connection.signalinx~[num]=23" />
|
||||
<input name="signal_in24" displayname="connection.signalinx~[num]=24" />
|
||||
<input name="signal_in25" displayname="connection.signalinx~[num]=25" />
|
||||
<input name="signal_in26" displayname="connection.signalinx~[num]=26" />
|
||||
<input name="signal_in27" displayname="connection.signalinx~[num]=27" />
|
||||
<input name="signal_in28" displayname="connection.signalinx~[num]=28" />
|
||||
<input name="signal_in29" displayname="connection.signalinx~[num]=29" />
|
||||
<input name="signal_in30" displayname="connection.signalinx~[num]=30" />
|
||||
<input name="signal_in31" displayname="connection.signalinx~[num]=31" />
|
||||
<input name="signal_in32" displayname="connection.signalinx~[num]=32" />
|
||||
<output name="signal_out1" displayname="connection.signaloutx~[num]=1" />
|
||||
<output name="signal_out2" displayname="connection.signaloutx~[num]=2" />
|
||||
<output name="signal_out3" displayname="connection.signaloutx~[num]=3" />
|
||||
<output name="signal_out4" displayname="connection.signaloutx~[num]=4" />
|
||||
<output name="signal_out5" displayname="connection.signaloutx~[num]=5" />
|
||||
<output name="signal_out6" displayname="connection.signaloutx~[num]=6" />
|
||||
<output name="signal_out7" displayname="connection.signaloutx~[num]=7" />
|
||||
<output name="signal_out8" displayname="connection.signaloutx~[num]=8" />
|
||||
<output name="signal_out9" displayname="connection.signaloutx~[num]=9" />
|
||||
<output name="signal_out10" displayname="connection.signaloutx~[num]=10" />
|
||||
<output name="signal_out11" displayname="connection.signaloutx~[num]=11" />
|
||||
<output name="signal_out12" displayname="connection.signaloutx~[num]=12" />
|
||||
<output name="signal_out13" displayname="connection.signaloutx~[num]=13" />
|
||||
<output name="signal_out14" displayname="connection.signaloutx~[num]=14" />
|
||||
<output name="signal_out15" displayname="connection.signaloutx~[num]=15" />
|
||||
<output name="signal_out16" displayname="connection.signaloutx~[num]=16" />
|
||||
<output name="signal_out17" displayname="connection.signaloutx~[num]=17" />
|
||||
<output name="signal_out18" displayname="connection.signaloutx~[num]=18" />
|
||||
<output name="signal_out19" displayname="connection.signaloutx~[num]=19" />
|
||||
<output name="signal_out20" displayname="connection.signaloutx~[num]=20" />
|
||||
<output name="signal_out21" displayname="connection.signaloutx~[num]=21" />
|
||||
<output name="signal_out22" displayname="connection.signaloutx~[num]=22" />
|
||||
<output name="signal_out23" displayname="connection.signaloutx~[num]=23" />
|
||||
<output name="signal_out24" displayname="connection.signaloutx~[num]=24" />
|
||||
<output name="signal_out25" displayname="connection.signaloutx~[num]=25" />
|
||||
<output name="signal_out26" displayname="connection.signaloutx~[num]=26" />
|
||||
<output name="signal_out27" displayname="connection.signaloutx~[num]=27" />
|
||||
<output name="signal_out28" displayname="connection.signaloutx~[num]=28" />
|
||||
<output name="signal_out29" displayname="connection.signaloutx~[num]=29" />
|
||||
<output name="signal_out30" displayname="connection.signaloutx~[num]=30" />
|
||||
<output name="signal_out31" displayname="connection.signaloutx~[num]=31" />
|
||||
<output name="signal_out32" displayname="connection.signaloutx~[num]=32" />
|
||||
</ConnectionPanel>
|
||||
</Item>
|
||||
</Items>
|
||||
6
LocalMods/MicroLua/filelist.xml
Executable file
6
LocalMods/MicroLua/filelist.xml
Executable file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<contentpackage name="MicroLua" modversion="0.0.4" corepackage="False" steamworkshopid="3018125421" gameversion="1.1.19.3" expectedhash="B754DCA6FD2D3F4803BA9B5BCBDA4DC7">
|
||||
<Item file="%ModDir%/MicroLua.xml" />
|
||||
<Text file="%ModDir%/MicroLua.Eng.Txt.xml" />
|
||||
<Text file="%ModDir%/MicroLua.Por.Txt.xml" />
|
||||
</contentpackage>
|
||||
Reference in New Issue
Block a user