mirror of
https://github.com/Stone-Red-Code/StoneRed.LogicSimulator.git
synced 2026-09-04 09:06:29 +02:00
Create StoneRed.LogicSimulator.Api project
This commit is contained in:
@@ -0,0 +1,12 @@
|
||||
namespace StoneRed.LogicSimulator.Api.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class LogicGateDescriptionAttribute : Attribute
|
||||
{
|
||||
public string Description { get; }
|
||||
|
||||
public LogicGateDescriptionAttribute(string description)
|
||||
{
|
||||
Description = description;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace StoneRed.LogicSimulator.Api.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public class LogicGateNameAttribute : Attribute
|
||||
{
|
||||
public string Name { get; }
|
||||
|
||||
public LogicGateNameAttribute(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace StoneRed.LogicSimulator.Api.Interfaces;
|
||||
|
||||
internal interface IColorable
|
||||
{
|
||||
public Color Color { get; }
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
namespace StoneRed.LogicSimulator.Api.Interfaces;
|
||||
|
||||
internal interface IDrawable
|
||||
{
|
||||
Texture2D Texture { get; }
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
using MonoGame.Extended.Input;
|
||||
|
||||
namespace StoneRed.LogicSimulator.Api.Interfaces;
|
||||
|
||||
internal interface IInteractable
|
||||
{
|
||||
public string Info { get; }
|
||||
|
||||
public void OnInteraction(MouseStateExtended mouseState, MouseStateExtended previousMouseState, KeyboardStateExtended keyboardStateExtended);
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
|
||||
using StoneRed.LogicSimulator.Api.Utilities;
|
||||
|
||||
namespace StoneRed.LogicSimulator.Api.Interfaces;
|
||||
#pragma warning disable S112 // General exceptions should never be thrown
|
||||
|
||||
internal abstract class LogicGate
|
||||
{
|
||||
private readonly List<LogicGateConnection> logicGateConnections = new();
|
||||
private bool logicGateConnectionsChnaged = false;
|
||||
private int currentInput;
|
||||
private int newInput;
|
||||
private int output;
|
||||
private int cachedOutput;
|
||||
private LogicGateConnection[] logicGateConnectionsArray = Array.Empty<LogicGateConnection>();
|
||||
public abstract int OutputCount { get; set; }
|
||||
public abstract int InputCount { get; set; }
|
||||
internal IReadOnlyList<LogicGateConnection> LogicGateConnections => logicGateConnections.AsReadOnly();
|
||||
internal GraphicsDevice? GraphicsDevice { get; set; }
|
||||
internal LogicGateWorldData WorldData { get; init; } = new LogicGateWorldData();
|
||||
internal ulong Id { get; set; }
|
||||
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is LogicGate gate &&
|
||||
Id == gate.Id;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Id.GetHashCode();
|
||||
}
|
||||
|
||||
internal void NextTick()
|
||||
{
|
||||
currentInput = newInput;
|
||||
newInput = 0;
|
||||
output = 0;
|
||||
}
|
||||
|
||||
internal void SetInput(int value, int index)
|
||||
{
|
||||
if (index >= InputCount)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
// Inputs should act as or gates
|
||||
|
||||
if (value == 1)
|
||||
{
|
||||
newInput.SetBit(1, index);
|
||||
}
|
||||
}
|
||||
|
||||
internal void Connect(LogicGate logicGate, int inputIndex, int outputIndex)
|
||||
{
|
||||
if (inputIndex >= logicGate.InputCount)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
if (outputIndex >= OutputCount)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
lock (logicGateConnections)
|
||||
{
|
||||
logicGateConnections.Add(new LogicGateConnection(logicGate, inputIndex, outputIndex));
|
||||
logicGateConnectionsChnaged = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsConnectedTo(LogicGate logicGate, int? inputIndex = null, int? outputIndex = null)
|
||||
{
|
||||
lock (logicGateConnections)
|
||||
{
|
||||
return logicGateConnections.Exists(c =>
|
||||
c.LogicGate.Id == logicGate.Id
|
||||
&& (!inputIndex.HasValue || c.InputIndex == inputIndex)
|
||||
&& (!outputIndex.HasValue || c.OutputIndex == outputIndex));
|
||||
}
|
||||
}
|
||||
|
||||
internal void Disconnect(LogicGate logicGate, int? inputIndex = null, int? outputIndex = null)
|
||||
{
|
||||
lock (logicGateConnections)
|
||||
{
|
||||
int index = logicGateConnections.FindIndex(c =>
|
||||
c.LogicGate.Id == logicGate.Id &&
|
||||
(!inputIndex.HasValue || c.InputIndex == inputIndex) &&
|
||||
(!outputIndex.HasValue || c.OutputIndex == outputIndex));
|
||||
logicGateConnections.RemoveAt(index);
|
||||
logicGateConnectionsChnaged = true;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Update()
|
||||
{
|
||||
Execute();
|
||||
cachedOutput = output;
|
||||
PublishOutput();
|
||||
}
|
||||
|
||||
internal int GetCachedOutputBit(int index)
|
||||
{
|
||||
if (index < 0 || index >= OutputCount)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return cachedOutput.GetBit(index);
|
||||
}
|
||||
|
||||
protected internal virtual void Initialize()
|
||||
{ }
|
||||
|
||||
protected abstract void Execute();
|
||||
|
||||
protected int GetInputBit(int index)
|
||||
{
|
||||
if (index < 0 || index >= InputCount)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return currentInput.GetBit(index);
|
||||
}
|
||||
|
||||
protected void SetOutputBit(int value, int index)
|
||||
{
|
||||
if (index < 0 || index >= OutputCount)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
output.SetBit(value, index);
|
||||
}
|
||||
|
||||
protected Texture2D CreateTexture(int width, int height)
|
||||
{
|
||||
return new Texture2D(GraphicsDevice, width, height);
|
||||
}
|
||||
|
||||
private void PublishOutput()
|
||||
{
|
||||
if (logicGateConnectionsChnaged)
|
||||
{
|
||||
lock (logicGateConnections)
|
||||
{
|
||||
logicGateConnectionsArray = logicGateConnections.ToArray();
|
||||
logicGateConnectionsChnaged = false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < logicGateConnectionsArray.Length; i++)
|
||||
{
|
||||
LogicGateConnection connection = logicGateConnectionsArray[i];
|
||||
connection.LogicGate.SetInput(output.GetBit(connection.OutputIndex), connection.InputIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore S112 // General exceptions should never be thrown
|
||||
|
||||
internal class LogicGateConnection
|
||||
{
|
||||
public LogicGate LogicGate { get; }
|
||||
|
||||
public int InputIndex { get; }
|
||||
public int OutputIndex { get; }
|
||||
|
||||
public LogicGateConnection(LogicGate logicGate, int inputIndex, int outputIndex)
|
||||
{
|
||||
LogicGate = logicGate;
|
||||
InputIndex = inputIndex;
|
||||
OutputIndex = outputIndex;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="StoneRed.LogicSimulator" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="MonoGame.Extended" Version="3.8.0" />
|
||||
<PackageReference Include="MonoGame.Extended.Input" Version="3.8.0" />
|
||||
<PackageReference Include="MonoGame.Framework.DesktopGL" Version="3.8.1.303" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,34 @@
|
||||
namespace StoneRed.LogicSimulator.Api.Utilities;
|
||||
|
||||
#pragma warning disable S112 // General exceptions should never be thrown
|
||||
|
||||
internal static class BitHelper
|
||||
{
|
||||
public static void SetBit(this ref int input, int value, int index)
|
||||
{
|
||||
if (index >= 32)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
if (value == 1)
|
||||
{
|
||||
input |= 1 << index;
|
||||
}
|
||||
else
|
||||
{
|
||||
input &= ~(1 << index);
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetBit(this int input, int index)
|
||||
{
|
||||
if (index >= 32)
|
||||
{
|
||||
throw new IndexOutOfRangeException();
|
||||
}
|
||||
|
||||
return (input >> index) & 1;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore S112 // General exceptions should never be thrown
|
||||
@@ -0,0 +1,11 @@
|
||||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace StoneRed.LogicSimulator.Api.Utilities;
|
||||
|
||||
internal record LogicGateWorldData
|
||||
{
|
||||
public Vector2 Position { get; set; }
|
||||
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Description { get; set; } = string.Empty;
|
||||
}
|
||||
Reference in New Issue
Block a user