From 4a8ea0a098c3eb7faf8e0d8e93f3dc21f10d8931 Mon Sep 17 00:00:00 2001 From: Astoria Date: Mon, 8 Apr 2024 18:24:41 -0500 Subject: [PATCH] its not working and im not sure why --- .../net/brokenmoon/redcontrol/RedControl.java | 6 + .../net/brokenmoon/redcontrol/api/RCBus.java | 9 +- .../net/brokenmoon/redcontrol/api/RCCpu.java | 19 ++- .../redcontrol/blockentities/CpuEntity.java | 28 ++-- .../redcontrol/blockentities/DriveEntity.java | 124 ++++++++++++++++++ .../blockentities/MonitorEntity.java | 17 +++ .../redcontrol/blockentities/Peripheral.java | 6 + .../redcontrol/blocks/CpuBlock.java | 6 - .../redcontrol/blocks/DriveBlock.java | 27 ++++ .../redcontrol/blocks/MonitorBlock.java | 20 +++ .../redcontrol/blocks/NetworkCarrier.java | 30 ++++- .../assets/redcontrol/image/redforth.img | Bin 0 -> 6400 bytes 12 files changed, 251 insertions(+), 41 deletions(-) create mode 100644 src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java create mode 100644 src/main/java/net/brokenmoon/redcontrol/blocks/DriveBlock.java create mode 100644 src/main/resources/assets/redcontrol/image/redforth.img diff --git a/src/main/java/net/brokenmoon/redcontrol/RedControl.java b/src/main/java/net/brokenmoon/redcontrol/RedControl.java index 5c39292..550beea 100644 --- a/src/main/java/net/brokenmoon/redcontrol/RedControl.java +++ b/src/main/java/net/brokenmoon/redcontrol/RedControl.java @@ -1,8 +1,10 @@ package net.brokenmoon.redcontrol; import net.brokenmoon.redcontrol.blockentities.CpuEntity; +import net.brokenmoon.redcontrol.blockentities.DriveEntity; import net.brokenmoon.redcontrol.blockentities.MonitorEntity; import net.brokenmoon.redcontrol.blocks.CpuBlock; +import net.brokenmoon.redcontrol.blocks.DriveBlock; import net.brokenmoon.redcontrol.blocks.MonitorBlock; import net.fabricmc.api.ModInitializer; @@ -27,11 +29,13 @@ public class RedControl implements ModInitializer { //Blocks public static final CpuBlock CPU = new CpuBlock(FabricBlockSettings.create().strength(4.0f)); public static final MonitorBlock MONITOR = new MonitorBlock(FabricBlockSettings.create().strength(4.0f)); + public static final DriveBlock DRIVE = new DriveBlock(FabricBlockSettings.create().strength(4.0f)); //Items //Block Entities public static final BlockEntityType CPU_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, new Identifier("redcontrol", "cpu_block_entity"), FabricBlockEntityTypeBuilder.create(CpuEntity::new, CPU).build()); public static final BlockEntityType MONITOR_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, new Identifier("redcontrol", "monitor_block_entity"), FabricBlockEntityTypeBuilder.create(MonitorEntity::new, MONITOR).build()); + public static final BlockEntityType DRIVE_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, new Identifier("redcontrol", "drive_block_entity"), FabricBlockEntityTypeBuilder.create(DriveEntity::new, DRIVE).build()); @Override public void onInitialize() { @@ -42,8 +46,10 @@ public class RedControl implements ModInitializer { LOGGER.info("Initializing RedControl!"); Registry.register(Registries.BLOCK, new Identifier("redcontrol", "cpu"), CPU); Registry.register(Registries.BLOCK, new Identifier("redcontrol", "monitor"), MONITOR); + Registry.register(Registries.BLOCK, new Identifier("redcontrol", "drive"), DRIVE); Registry.register(Registries.ITEM, new Identifier("redcontrol", "cpu"), new BlockItem(CPU, new FabricItemSettings())); Registry.register(Registries.ITEM, new Identifier("redcontrol", "monitor"), new BlockItem(MONITOR, new FabricItemSettings())); + Registry.register(Registries.ITEM, new Identifier("redcontrol", "drive"), new BlockItem(DRIVE, new FabricItemSettings())); } } \ No newline at end of file diff --git a/src/main/java/net/brokenmoon/redcontrol/api/RCBus.java b/src/main/java/net/brokenmoon/redcontrol/api/RCBus.java index aa29fa9..6f05e12 100644 --- a/src/main/java/net/brokenmoon/redcontrol/api/RCBus.java +++ b/src/main/java/net/brokenmoon/redcontrol/api/RCBus.java @@ -1,24 +1,28 @@ package net.brokenmoon.redcontrol.api; +import com.simon816.j65el02.Bus; import com.simon816.j65el02.device.RedBus; +import net.brokenmoon.redcontrol.RedControl; import net.brokenmoon.redcontrol.blockentities.Peripheral; import net.brokenmoon.redcontrol.blocks.NetworkCarrier; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; -public class RCBus { +public class RCBus extends Bus { private boolean isValid = false; private RedBus redBus; public RCBus(RedBus redBus) { + super(redBus); this.redBus = redBus; } public void write(int address, int data, World world, BlockPos pos) { if(isValid) { - getRedBus().write(address, data); + RedControl.LOGGER.info("Writing! " + address + " " + data); + getRedBus().write(address, data); } else { generateBusWithWrite(address, data, world, pos); } @@ -30,6 +34,7 @@ public class RCBus { public int read(int address, boolean cpuAccess, World world, BlockPos pos) { if(isValid) { + RedControl.LOGGER.info("Reading! " + address + " " + cpuAccess); return getRedBus().read(address, cpuAccess) & 0xff; } else { return generateBusWithRead(address, cpuAccess, world, pos); diff --git a/src/main/java/net/brokenmoon/redcontrol/api/RCCpu.java b/src/main/java/net/brokenmoon/redcontrol/api/RCCpu.java index 1e9bb05..2cb7080 100644 --- a/src/main/java/net/brokenmoon/redcontrol/api/RCCpu.java +++ b/src/main/java/net/brokenmoon/redcontrol/api/RCCpu.java @@ -1,20 +1,17 @@ package net.brokenmoon.redcontrol.api; import com.simon816.j65el02.Cpu; +import com.simon816.j65el02.CpuState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; public class RCCpu extends Cpu { - - private RCBus rcbus; - - public RCCpu() { - } - - public RCBus getRCBus() { - return rcbus; - } + private final World world; + private final BlockPos pos; - public void setRCBus(RCBus rcbus) { - this.rcbus = rcbus; + public RCCpu(World world, BlockPos pos) { + this.world = world; + this.pos = pos; } } diff --git a/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java b/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java index 7af514c..90f5b4c 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java +++ b/src/main/java/net/brokenmoon/redcontrol/blockentities/CpuEntity.java @@ -1,15 +1,11 @@ package net.brokenmoon.redcontrol.blockentities; import com.simon816.j65el02.Bus; -import com.simon816.j65el02.Cpu; import com.simon816.j65el02.device.*; import net.brokenmoon.redcontrol.RedControl; import net.brokenmoon.redcontrol.api.RCBus; import net.brokenmoon.redcontrol.api.RCCpu; -import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.block.entity.BlockEntity; -import net.minecraft.block.entity.BrewingStandBlockEntity; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; @@ -37,7 +33,7 @@ public class CpuEntity extends Peripheral implements Runnable{ boolean notTicked = true; private boolean running = false; private Semaphore waiInterrupt = new Semaphore(2); - private final RCCpu cpu; + private RCCpu cpu; private RCBus rcbus; private Path bootloader; @@ -50,22 +46,22 @@ public class CpuEntity extends Peripheral implements Runnable{ public CpuEntity(BlockPos pos, BlockState state) { super(RedControl.CPU_BLOCK_ENTITY, pos, state, 0); RedControl.LOGGER.info("Making CpuEntity"); - this.cpu = new RCCpu(); - this.setRCBus(new RCBus(new RedBus())); - this.cpu.setRCBus(this.getRCBus()); - this.cpu.setBus(new Bus(this.getRCBus().getRedBus())); - Memory ram = new Memory(0x0000, 0x2000); - try { - ram.loadFromFile(bootloader, 0x400, 0x100); - } catch (IOException e) { - throw new RuntimeException(e); - } - cpu.getBus().addDevice(ram); } public static void tick(World world, BlockPos pos, BlockState state, CpuEntity be) { if(be.notTicked) { + be.cpu = new RCCpu(world, pos); + be.setRCBus(new RCBus(new RedBus())); + be.cpu.setBus(be.getRCBus()); + be.cpu.setBus(new Bus(be.getRCBus().getRedBus())); + Memory ram = new Memory(0x0000, 0x2000); + try { + ram.loadFromFile(be.bootloader, 0x400, 0x100); + } catch (IOException e) { + throw new RuntimeException(e); + } + be.cpu.getBus().addDevice(ram); be.reset(); be.notTicked = false; be.start(); diff --git a/src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java b/src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java new file mode 100644 index 0000000..b5dbff1 --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/blockentities/DriveEntity.java @@ -0,0 +1,124 @@ +package net.brokenmoon.redcontrol.blockentities; + +import com.simon816.j65el02.device.DiskDriver; +import com.simon816.j65el02.device.FileDiskDriver; +import net.brokenmoon.redcontrol.RedControl; +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.util.math.BlockPos; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.Paths; + +public class DriveEntity extends Peripheral{ + + private static final int SECTOR_SIZE = 0x80; + + private final DiskDriver driver; + private final byte[] diskName = new byte[SECTOR_SIZE]; + private final byte[] diskSerial = new byte[SECTOR_SIZE]; + private final ByteBuffer buffer; + + private int sector; + private int command; + + public DriveEntity(BlockPos pos, BlockState state) { + super(RedControl.DRIVE_BLOCK_ENTITY, pos, state, 2); + + try { + this.driver = new FileDiskDriver(Paths.get("/home/astoria/code/java/mods/RedControl/src/main/resources/assets/redcontrol/image/redforth.img"), "Forth", "FORTH", false); + } catch (IOException e) { + throw new RuntimeException(e); + } + this.buffer = ByteBuffer.allocateDirect(SECTOR_SIZE); + byte[] name = driver.getDriveName(); + byte[] serial = driver.getDriveSerial(); + System.arraycopy(name, 0, this.diskName, 0, name.length); + System.arraycopy(serial, 0, this.diskSerial, 0, serial.length); + } + + @Override + public void write(int address, int data) { + switch (address) { + case 0x80: // Sector number (lo) + this.sector = (this.sector & 0xff00) | data; + break; + case 0x81: // Sector number (hi) + this.sector = (data << 8) | (this.sector & 0xff); + break; + case 0x82: // Disk command + this.command = data; + break; + default: // Disk sector buffer + if (address >= 0 && address <= 0x7f) { + this.buffer.put(address, (byte) data); + } + } + } + + + @Override + public int read(int address) { + RedControl.LOGGER.info("Drive Reading"); + switch (address) { + case 0x80: // Sector number (lo) + return this.sector & 0xff; + case 0x81: // Sector number (hi) + return (this.sector >> 8) & 0xff; + case 0x82: // Disk command + return this.command; + default: // Disk sector buffer + if (address >= 0 && address <= 0x7f) { + return this.buffer.get(address); + } + return 0; + } + } + + @Override + public void update() { + try { + switch (this.command) { + case 0x01: // Read Disk Name + this.buffer.clear(); + this.buffer.put(this.diskName); + this.command = 0; + break; + case 0x02: // Write Disk Name + this.buffer.position(0); + this.buffer.get(this.diskName); + this.driver.writeDiskName(this.diskName); + this.command = 0; + break; + case 0x03: // Read Disk Serial + this.buffer.clear(); + this.buffer.put(this.diskSerial); + this.command = 0; + break; + case 0x04: // Read Disk Sector + if (this.sector >= 0x800) { + this.command = 0xff; + break; + } + this.driver.seek(this.sector << 7); + this.buffer.position(0); + this.driver.read(this.buffer); + this.command = 0; + break; + case 0x05: // Write Disk Sector + if (this.sector >= 0x800) { + this.command = 0xff; + break; + } + this.driver.seek(this.sector << 7); + this.buffer.position(0); + this.driver.write(this.buffer); + this.command = 0; + break; + } + } catch (Exception e) { + this.command = 0xff; + } + } +} diff --git a/src/main/java/net/brokenmoon/redcontrol/blockentities/MonitorEntity.java b/src/main/java/net/brokenmoon/redcontrol/blockentities/MonitorEntity.java index 5e3b4e1..0c6d554 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blockentities/MonitorEntity.java +++ b/src/main/java/net/brokenmoon/redcontrol/blockentities/MonitorEntity.java @@ -26,6 +26,18 @@ public class MonitorEntity extends Peripheral { private byte[] keyBuffer = new byte[0x10]; private byte[][] windowData = new byte[HEIGHT][WIDTH]; + public String[] getText(){ + String[] l = new String[HEIGHT]; + for(int y = 0; y < HEIGHT; y++) { + String temp = ""; + for (int x = 0; x < WIDTH; x++) { + temp += (char) windowData[y][x]; + } + l[y] = temp; + } + return l; + } + private boolean isDisplayDirty; private boolean isCursorDirty; @@ -35,6 +47,7 @@ public class MonitorEntity extends Peripheral { @Override public void write(int address, int data) { + RedControl.LOGGER.info("Monitor Writing"); switch (address) { case 0x00: this.accessRow = data; @@ -85,6 +98,10 @@ public class MonitorEntity extends Peripheral { this.isDisplayDirty = true; this.windowData[this.accessRow][address - 0x10] = (byte) data; } + if (this.isDisplayDirty) { + this.isDisplayDirty = false; + this.update(); + } } } diff --git a/src/main/java/net/brokenmoon/redcontrol/blockentities/Peripheral.java b/src/main/java/net/brokenmoon/redcontrol/blockentities/Peripheral.java index 0ca4909..e6ef6d6 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blockentities/Peripheral.java +++ b/src/main/java/net/brokenmoon/redcontrol/blockentities/Peripheral.java @@ -6,7 +6,13 @@ import net.brokenmoon.redcontrol.api.RCBus; import net.minecraft.block.BlockState; import net.minecraft.block.entity.BlockEntity; import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; public abstract class Peripheral extends BlockEntity implements RedBus.Peripheral { diff --git a/src/main/java/net/brokenmoon/redcontrol/blocks/CpuBlock.java b/src/main/java/net/brokenmoon/redcontrol/blocks/CpuBlock.java index c1a1b58..9b54b55 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blocks/CpuBlock.java +++ b/src/main/java/net/brokenmoon/redcontrol/blocks/CpuBlock.java @@ -28,12 +28,6 @@ public class CpuBlock extends NetworkCarrier { return new CpuEntity(pos, state); } - @Override - public BlockRenderType getRenderType(BlockState state) { - // With inheriting from BlockWithEntity this defaults to INVISIBLE, so we need to change that! - return BlockRenderType.MODEL; - } - @Override public BlockEntityTicker getTicker(World world, BlockState state, BlockEntityType type) { return validateTicker(type, RedControl.CPU_BLOCK_ENTITY, (world1, pos, state1, be) -> CpuEntity.tick(world1, pos, state1, be)); diff --git a/src/main/java/net/brokenmoon/redcontrol/blocks/DriveBlock.java b/src/main/java/net/brokenmoon/redcontrol/blocks/DriveBlock.java new file mode 100644 index 0000000..8521c7c --- /dev/null +++ b/src/main/java/net/brokenmoon/redcontrol/blocks/DriveBlock.java @@ -0,0 +1,27 @@ +package net.brokenmoon.redcontrol.blocks; + +import com.mojang.serialization.MapCodec; +import net.brokenmoon.redcontrol.blockentities.DriveEntity; +import net.brokenmoon.redcontrol.blockentities.MonitorEntity; +import net.minecraft.block.BlockState; +import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.util.math.BlockPos; +import org.jetbrains.annotations.Nullable; + +public class DriveBlock extends NetworkCarrier{ + public DriveBlock(Settings settings) { + super(settings); + } + + @Override + protected MapCodec getCodec() { + return null; + } + + @Nullable + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new DriveEntity(pos, state); + } +} diff --git a/src/main/java/net/brokenmoon/redcontrol/blocks/MonitorBlock.java b/src/main/java/net/brokenmoon/redcontrol/blocks/MonitorBlock.java index ef16d4f..197df5c 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blocks/MonitorBlock.java +++ b/src/main/java/net/brokenmoon/redcontrol/blocks/MonitorBlock.java @@ -7,7 +7,13 @@ import net.minecraft.block.BlockEntityProvider; import net.minecraft.block.BlockState; import net.minecraft.block.BlockWithEntity; import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; public class MonitorBlock extends NetworkCarrier { @@ -25,4 +31,18 @@ public class MonitorBlock extends NetworkCarrier { public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { return new MonitorEntity(pos, state); } + + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (!world.isClient) { + MonitorEntity monitor = (MonitorEntity) world.getBlockEntity(pos); + player.sendMessage(Text.literal(String.valueOf(monitor.getBus().hashCode())), false); + String[] text = monitor.getText(); + for(int i = 0; i < text.length; i++){ + player.sendMessage(Text.literal(text[i]), false); + } + } + + return ActionResult.SUCCESS; + } } diff --git a/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java b/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java index 1597c77..ee99809 100644 --- a/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java +++ b/src/main/java/net/brokenmoon/redcontrol/blocks/NetworkCarrier.java @@ -3,12 +3,14 @@ package net.brokenmoon.redcontrol.blocks; import com.simon816.j65el02.device.RedBus; import net.brokenmoon.redcontrol.api.RCBus; import net.brokenmoon.redcontrol.blockentities.Peripheral; -import net.minecraft.block.Block; -import net.minecraft.block.BlockEntityProvider; -import net.minecraft.block.BlockState; -import net.minecraft.block.BlockWithEntity; +import net.minecraft.block.*; import net.minecraft.entity.LivingEntity; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.jetbrains.annotations.Nullable; @@ -33,15 +35,21 @@ public abstract class NetworkCarrier extends BlockWithEntity implements BlockEnt @Override public void onStateReplaced(BlockState state, World world, BlockPos pos, BlockState newState, boolean moved) { + if(world.getBlockEntity(pos) instanceof Peripheral){ + ((Peripheral) world.getBlockEntity(pos)).getBus().setValid(false); + } if (state.hasBlockEntity() && !state.isOf(newState.getBlock())) { world.removeBlockEntity(pos); } } - public void invalidateBus(World world, BlockPos pos){ - + @Override + public BlockRenderType getRenderType(BlockState state) { + // With inheriting from BlockWithEntity this defaults to INVISIBLE, so we need to change that! + return BlockRenderType.MODEL; } + public void generateBus(World world, BlockPos pos){ Block worldBlock = world.getBlockState(pos).getBlock(); if(world.getBlockEntity(pos) instanceof Peripheral){ @@ -90,4 +98,14 @@ public abstract class NetworkCarrier extends BlockWithEntity implements BlockEnt } return 0; } + + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (!world.isClient) { + Peripheral peripheral = (Peripheral) world.getBlockEntity(pos); + player.sendMessage(Text.literal(String.valueOf(peripheral.getBus().hashCode())), false); + } + + return ActionResult.SUCCESS; + } } diff --git a/src/main/resources/assets/redcontrol/image/redforth.img b/src/main/resources/assets/redcontrol/image/redforth.img new file mode 100644 index 0000000000000000000000000000000000000000..a0536b55fa7a2121cb888cf63aecaa970b9e62a9 GIT binary patch literal 6400 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 E|1{jgdjJ3c literal 0 HcmV?d00001