Merge remote-tracking branch 'origin/main'

# Conflicts:
#	src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java
main
Astoria 3 weeks ago
commit 789d41d92f

@ -2,6 +2,7 @@ package net.brokenmoon.redcontrol.screen;
import net.brokenmoon.redcontrol.RedControl;
import net.brokenmoon.redcontrol.RedControlNetworking;
import net.brokenmoon.redcontrol.api.CpuState;
import net.brokenmoon.redcontrol.blockentities.CpuEntity;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
@ -64,12 +65,7 @@ public class CpuScreen extends Screen {
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
super.render(context, mouseX, mouseY, delta);
int buttonPos = 7;
if(cpu.isRunning){
buttonPos = 0;
} else if(cpu.isResetting || cpu.isReset){
buttonPos = 14;
}
int buttonPos = cpu.getCpuState().offset;
int x = (width - 176) / 2;
int y = (height - 166) / 2;
context.drawTexture(cpuTexture,x,y,0,0,176,166);

@ -0,0 +1,5 @@
package net.brokenmoon.redcontrol.api;
public interface CpuControl {
CpuState getCpuState();
}

@ -0,0 +1,7 @@
package net.brokenmoon.redcontrol.api;
public enum CpuState {
RUNNING(0), STOPPED(7), RESET(14);
public final int offset;
CpuState(int off){offset = off;}
}

@ -11,9 +11,20 @@ import kotlin.io.path.absolute
import kotlin.io.path.createDirectories
import kotlin.io.path.exists
/**
* A factory that takes a URI,String,String and produces a DiskDriver for the URI (or null if it cannot make one)
*/
object DriveFactory {
private val gamedir = FabricLoader.getInstance().gameDir.resolve("redbin").absolute()
/**
* a map of uri protocol -> tri funcctions to create drivers for ones not explicitly handled by the mod
*/
val extendedDrivers = HashMap<String,TriFunction<URI,String,String,DiskDriver?>>()
/**
* creates a driver from the given URI
*/
fun createDriver(uri: URI, name: String, serial: String): DiskDriver? {
if (!gamedir.exists()) {gamedir.createDirectories()}
return when (uri.scheme) {

@ -15,6 +15,10 @@ import net.minecraft.nbt.NbtCompound;
import java.io.IOException;
import java.nio.file.Paths;
/**
* A serializable emulator
*/
public class Emulator {
private RedBus bus;
@ -24,7 +28,7 @@ public class Emulator {
public Emulator(RedBus bus){
this.bus = bus;
cpu = new Cpu();
cpu.setLogCallback(new LogConsumer());
cpu.setLogCallback((i) -> RedControl.LOGGER.info("CPU emitted a byte {}",i));
cpu.setBus(new Bus(bus));
ram = new Memory(0x0000, 0x4000 - 1, ((CpuAccessor)cpu).getRedBusState());
ram.loadFromBytes(RedControl.images.get("rpcboot.bin"),0x400,0x100);
@ -34,37 +38,65 @@ public class Emulator {
ram.write(1, 1, ((CpuAccessor)cpu).getRedBusState());
}
/**
* gets the RedBus attached to this Emulator
* @return the red bus attached to this emulator
*/
public RedBus getBus() {
return bus;
}
/**
* sets the bus and sets redbus on the CPU
* @param bus the bus to set the cpu and this emu to
*/
public void setBus(RedBus bus) {
this.bus = bus;
((BusAccessor)this.cpu.getBus()).setRedBus(bus);
}
/**
* returns if the CPU is waiting on interupt
* @return if the cpu is waiting on a interupt
*/
public boolean isWaitingOnInterrupt(){
return cpu.isWaitingForInterrupt();
}
public void setWaitingOnInterrupt(){
cpu.getCpuState().intWait = false;
/**
* sets the CPU's interupt state
* @param interrupt the new interupt state
*/
public void setWaitingOnInterrupt(boolean interrupt){
cpu.getCpuState().intWait = interrupt;
}
/**
* steps the CPU by 1 instruction
* and updates all bus/redbus attached devices
*/
public void step() {
if(!isWaitingOnInterrupt()) {
CpuState state = ((CpuAccessor)this.cpu).getState();
this.cpu.step();
this.cpu.getBus().update(((CpuAccessor)cpu).getRedBusState());
}
}
/**
* resets the CPU to default values, and loads driveID and monitorID back for bootloader to use
* @param driveId the drive bootloader will read from
* @param monitorId the monitor id bootloder and initial program will write to
*/
public void reset(int driveId, int monitorId){
cpu.reset();
ram.write(0, driveId, ((CpuAccessor)cpu).getRedBusState());
ram.write(1, monitorId, ((CpuAccessor)cpu).getRedBusState());
}
/**
* save the emulator into NBT
* @param nbt the NBT to write state into
*/
public void writeNbt(NbtCompound nbt) {
//Cpu write nbt
@ -118,6 +150,10 @@ public class Emulator {
nbt.putByteArray("ramValues", ((MemoryAccessor)this.ram).getMem());
}
/**
* load emulator state from NBT
* @param nbt the NBT to load from.
*/
public void readNbt(NbtCompound nbt) {
//Cpu write nbt

@ -1,12 +0,0 @@
package net.brokenmoon.redcontrol.api;
import net.brokenmoon.redcontrol.RedControl;
import java.util.function.IntConsumer;
public class LogConsumer implements IntConsumer {
@Override
public void accept(int value) {
RedControl.LOGGER.info("Cpu MMU Logger: " + value);
}
}

@ -0,0 +1,23 @@
package net.brokenmoon.redcontrol.api;
import com.simon816.j65el02.device.RedBus;
import net.brokenmoon.redcontrol.util.FloodFill;
import net.minecraft.block.Block;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
public interface NetworkHolder {
RCWorldBus getBus(World world, BlockPos pos);
void setBus(World world, BlockPos pos, RCWorldBus bus);
default void generateBus(ServerWorld world, BlockPos pos){
Block worldBlock = world.getBlockState(pos).getBlock();
if(world.getBlockEntity(pos) instanceof Peripheral entityBlock){
RCWorldBus bus = new RCWorldBus(new RedBus(), world, pos);
entityBlock.setBus(bus);
entityBlock.getBus().setValid(true);
this.setBus(world,pos,entityBlock.getBus());
FloodFill.INSTANCE.blockFloodFiller(world, pos);
}
}
}

@ -1,12 +1,15 @@
package net.brokenmoon.redcontrol.blockentities;
package net.brokenmoon.redcontrol.api;
import com.simon816.j65el02.device.RedBus;
import net.brokenmoon.redcontrol.api.RCWorldBus;
import net.minecraft.block.BlockState;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.util.math.BlockPos;
import org.jetbrains.annotations.NotNull;
/**
* a BlockEntity peripheral
*/
public abstract class Peripheral extends BlockEntity implements RedBus.Peripheral {
protected RedBus bus;
@ -20,6 +23,10 @@ public abstract class Peripheral extends BlockEntity implements RedBus.Periphera
this.id = id;
}
/**
* get the redbus (or creates a new one if it does not exists or is invalid)
* @return the redbus for this peripheral
*/
public RCWorldBus getBus(){
if (this.worldBus == null || !this.worldBus.getValid()) {
this.worldBus = new RCWorldBus(new RedBus(),world,getPos());
@ -27,12 +34,20 @@ public abstract class Peripheral extends BlockEntity implements RedBus.Periphera
return this.worldBus;
}
public void setBus(RCWorldBus bus){
/**
* sets the bus for this peripheral and attaches it's self to the bus
* @param bus
*/
public void setBus(@NotNull RCWorldBus bus){
this.bus = bus.getRedBus();
this.bus.setPeripheral(id, this);
this.worldBus = bus;
}
/**
* gets the ID of the peripheral
* @return the id of the periperal
*/
public int getId() {
return id;
}

@ -6,6 +6,10 @@ import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
* A Bus holder including the blockpos and redbus and a cached world
* also holds if the bus is valid
*/
public class RCWorldBus {
private boolean isValid = false;
@ -22,6 +26,7 @@ public class RCWorldBus {
}
public void generateBus(ServerWorld world, BlockPos pos){
((NetworkCarrier)(world.getBlockState(pos).getBlock())).generateBus(world, pos);
}

@ -2,8 +2,7 @@ package net.brokenmoon.redcontrol.blockentities;
import com.simon816.j65el02.device.RedBus;
import net.brokenmoon.redcontrol.RedControl;
import net.brokenmoon.redcontrol.api.Emulator;
import net.brokenmoon.redcontrol.api.RCWorldBus;
import net.brokenmoon.redcontrol.api.*;
import net.brokenmoon.redcontrol.blocks.NetworkCarrier;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@ -16,7 +15,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public class CpuEntity extends Peripheral{
public class CpuEntity extends Peripheral implements CpuControl {
public int i = 0;
public boolean notTicked = true;
@ -25,10 +24,13 @@ public class CpuEntity extends Peripheral{
private int defaultMonitorId = 1;
private int defaultDriveId = 2;
public boolean isRunning = false;
public boolean isResetting = false;
public boolean isReset = false;
private int resetTimer = 20;
private CpuState state = CpuState.STOPPED;
@Override
public CpuState getCpuState() {return state;}
private int resetTimer = 40;
public CpuEntity(BlockPos pos, BlockState state) {
super(RedControl.CPU_BLOCK_ENTITY, pos, state, 0);
@ -42,18 +44,18 @@ public class CpuEntity extends Peripheral{
if (be.notTicked) {
be.notTicked = false;
}
if(be.isRunning) {
if(be.state == CpuState.RUNNING) {
for (int i = 0; i < 1000; i++)
be.step();
} else{
if (be.isResetting && !be.isReset && be.resetTimer > 0){
if (be.state == CpuState.RESET && be.resetTimer > 0){
be.resetTimer--;
} else {
be.core = new Emulator(be.getBus().getRedBus());
}
}
if (be.core.isWaitingOnInterrupt()) {
be.core.setWaitingOnInterrupt();
be.core.setWaitingOnInterrupt(false);
}
}
}
@ -78,28 +80,20 @@ public class CpuEntity extends Peripheral{
public void reset() {
this.core.reset(this.defaultDriveId, this.defaultMonitorId);
isRunning = false;
isResetting = true;
isReset = false;
resetTimer = 20;
state = CpuState.RESET;
resetTimer = 40;
markDirty();
world.updateListeners(pos, this.getCachedState(), this.getCachedState(), Block.NOTIFY_LISTENERS);
}
public void stop() {
isRunning = false;
isResetting = false;
isReset = false;
resetTimer = 20;
state = CpuState.STOPPED;
markDirty();
world.updateListeners(pos, this.getCachedState(), this.getCachedState(), Block.NOTIFY_LISTENERS);
}
public void start() {
isRunning = true;
isResetting = false;
isReset = false;
resetTimer = 20;
state = CpuState.RUNNING;
markDirty();
world.updateListeners(pos, this.getCachedState(), this.getCachedState(), Block.NOTIFY_LISTENERS);
}
@ -143,9 +137,7 @@ public class CpuEntity extends Peripheral{
@Override
protected void writeNbt(NbtCompound nbt) {
nbt.putBoolean("isRunning", this.isRunning);
nbt.putBoolean("isResetting", this.isResetting);
nbt.putBoolean("isReset", this.isReset);
nbt.putString("state", this.state.toString());
nbt.putInt("resetTimer", this.resetTimer);
nbt.putInt("defaultMonitorId", this.defaultMonitorId);
nbt.putInt("defaultDriveId", this.defaultDriveId);
@ -155,9 +147,7 @@ public class CpuEntity extends Peripheral{
@Override
public void readNbt(NbtCompound nbt) {
this.isRunning = nbt.getBoolean("isRunning");
this.isResetting = nbt.getBoolean("isResetting");
this.isReset = nbt.getBoolean("isReset");
this.state = CpuState.valueOf(nbt.getString("state"));
this.resetTimer = nbt.getInt("resetTimer");
this.defaultMonitorId = nbt.getInt("defaultMonitorId");
this.defaultDriveId = nbt.getInt("defaultDriveId");

@ -3,6 +3,7 @@ package net.brokenmoon.redcontrol.blockentities;
import com.simon816.j65el02.device.DiskDriver;
import net.brokenmoon.redcontrol.RedControl;
import net.brokenmoon.redcontrol.api.DriveFactory;
import net.brokenmoon.redcontrol.api.Peripheral;
import net.brokenmoon.redcontrol.item.FloppyDisk;
import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
@ -17,7 +18,7 @@ import java.net.URI;
import java.nio.ByteBuffer;
import java.util.UUID;
public class DriveEntity extends Peripheral{
public class DriveEntity extends Peripheral {
private static final int SECTOR_SIZE = 0x80;
@ -144,6 +145,7 @@ public class DriveEntity extends Peripheral{
disk = ItemStack.EMPTY;
this.driver = null;
this.buffer = null;
markDirty();
return ActionResult.SUCCESS;
}
@ -159,17 +161,22 @@ public class DriveEntity extends Peripheral{
}
this.driver = DriveFactory.INSTANCE.createDriver(URI.create(disk.getNbt().getString("uri")), String.valueOf(disk.getName()), disk.getNbt().getString("serial"));
this.buffer = ByteBuffer.allocateDirect(SECTOR_SIZE);
markDirty();
return ActionResult.SUCCESS;
}
@Override
protected void writeNbt(NbtCompound nbt) {
//SUPER DUPER NOT DONE TODO: FINISH THIS.
NbtCompound compound = new NbtCompound();
disk.writeNbt(compound);
nbt.put("item",compound);
super.writeNbt(nbt);
}
@Override
public void readNbt(NbtCompound nbt) {
disk = ItemStack.fromNbt(nbt.getCompound("item"));
super.readNbt(nbt);
}
}

@ -2,15 +2,11 @@ package net.brokenmoon.redcontrol.blocks;
import com.simon816.j65el02.device.RedBus;
import net.brokenmoon.redcontrol.RedControl;
import net.brokenmoon.redcontrol.api.NetworkHolder;
import net.brokenmoon.redcontrol.api.RCWorldBus;
import net.brokenmoon.redcontrol.blockentities.CpuEntity;
import net.brokenmoon.redcontrol.blockentities.Peripheral;
import net.brokenmoon.redcontrol.api.Peripheral;
import net.brokenmoon.redcontrol.mixin.RedBusAccessor;
import net.brokenmoon.redcontrol.util.FloodFill;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityTicker;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemPlacementContext;
@ -26,7 +22,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.jetbrains.annotations.Nullable;
public abstract class NetworkCarrier extends BlockWithEntity implements BlockEntityProvider {
public abstract class NetworkCarrier extends BlockWithEntity implements BlockEntityProvider, NetworkHolder {
public NetworkCarrier(Settings settings) {
super(settings);
}
@ -64,23 +60,6 @@ public abstract class NetworkCarrier extends BlockWithEntity implements BlockEnt
}
public void generateBus(ServerWorld world, BlockPos pos){
Block worldBlock = world.getBlockState(pos).getBlock();
if(world.getBlockEntity(pos) instanceof Peripheral){
Peripheral entityBlock = (Peripheral) world.getBlockEntity(pos);
RCWorldBus bus = new RCWorldBus(new RedBus(), world, pos);
entityBlock.setBus(bus);
entityBlock.getBus().setValid(true);
floodBus(entityBlock.getBus(), world, pos);
}
}
private void floodBus(RCWorldBus bus, ServerWorld world, BlockPos pos) {
this.setBus(world,pos,bus);
FloodFill.INSTANCE.blockFloodFiller(world,pos);
}
@Override
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
if (!world.isClient) {

@ -3,7 +3,7 @@ package net.brokenmoon.redcontrol.blocks
import com.mojang.serialization.MapCodec
import net.brokenmoon.redcontrol.RedControl
import net.brokenmoon.redcontrol.RedControlNetworking
import net.brokenmoon.redcontrol.blockentities.Peripheral
import net.brokenmoon.redcontrol.api.Peripheral
import net.brokenmoon.redcontrol.util.unsigned
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking
@ -16,7 +16,6 @@ import net.minecraft.network.listener.ClientPlayPacketListener
import net.minecraft.network.packet.Packet
import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket
import net.minecraft.server.network.ServerPlayerEntity
import net.minecraft.text.Text
import net.minecraft.util.ActionResult
import net.minecraft.util.ActionResult.FAIL
import net.minecraft.util.ActionResult.SUCCESS
@ -25,7 +24,6 @@ import net.minecraft.util.hit.BlockHitResult
import net.minecraft.util.math.BlockPos
import net.minecraft.world.World
import java.io.FileNotFoundException
import java.net.URI
import kotlin.experimental.xor
class TerminalBlock(settings: Settings) : NetworkCarrier(settings) {

@ -1,6 +1,7 @@
package net.brokenmoon.redcontrol.util
import net.brokenmoon.redcontrol.RedControl
import net.brokenmoon.redcontrol.api.NetworkHolder
import net.brokenmoon.redcontrol.api.RCWorldBus
import net.brokenmoon.redcontrol.blocks.NetworkCarrier
import net.minecraft.particle.ParticleTypes
@ -18,7 +19,7 @@ object FloodFill {
if (pos in seen) {continue}
val state = world.getBlockState(pos)
if (!state.isIn(RedControl.TAG_BUSABLE)){continue}
val net = state.block as? NetworkCarrier
val net = state.block as? NetworkHolder
if (net != null) {
val cpos = pos.toCenterPos()
world.spawnParticles(ParticleTypes.WAX_ON,cpos.x,cpos.y,cpos.z,20,0.6,0.6,0.6,0.2)
@ -55,7 +56,7 @@ object FloodFill {
checkable.add(pos.add(it.offsetX, it.offsetY, it.offsetZ))
}
seen.add(pos)
val nc = (state.block as? NetworkCarrier)
val nc = (state.block as? NetworkHolder)
if (nc != null) {
nc.getBus(world,pos).valid = false
val cpos = pos.toCenterPos()

Loading…
Cancel
Save