You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
9.0 KiB
Java

package net.brokenmoon.redcontrol;
import net.brokenmoon.redcontrol.api.events.BlockModificationEvents;
import net.brokenmoon.redcontrol.blockentities.CpuEntity;
import net.brokenmoon.redcontrol.blockentities.DriveEntity;
import net.brokenmoon.redcontrol.blocks.CpuBlock;
import net.brokenmoon.redcontrol.blocks.DriveBlock;
import net.brokenmoon.redcontrol.blocks.TerminalBlock;
import net.brokenmoon.redcontrol.blocks.TerminalEntity;
import net.brokenmoon.redcontrol.item.FloppyDisk;
import net.brokenmoon.redcontrol.util.FloodFill;
import net.fabricmc.api.ModInitializer;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.fabricmc.fabric.api.object.builder.v1.block.entity.FabricBlockEntityTypeBuilder;
import net.fabricmc.fabric.api.resource.ResourceManagerHelper;
import net.fabricmc.fabric.api.resource.SimpleSynchronousResourceReloadListener;
import net.minecraft.block.Block;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.item.BlockItem;
import net.minecraft.item.Item;
import net.minecraft.item.ItemGroup;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.Registry;
import net.minecraft.registry.Registries;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourceManager;
import net.minecraft.resource.ResourceType;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.text.Text;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
public class RedControl implements ModInitializer {
// This logger is used to write text to the console and the log file.
// It is considered best practice to use your mod id as the logger's name.
// That way, it's clear which mod wrote info, warnings, and errors.
public static final Logger LOGGER = LoggerFactory.getLogger("redcontrol");
//A hashmap of files contained in images
public static final HashMap<String,byte[]> images = new HashMap<>();
//Tags
public static final TagKey<Block> TAG_BUSABLE = TagKey.of(RegistryKeys.BLOCK, modloc("bus_conductive"));
//Blocks
public static final CpuBlock CPU = new CpuBlock(FabricBlockSettings.create().strength(4.0f));
public static final TerminalBlock TERMINAL = new TerminalBlock(FabricBlockSettings.create().strength(4.0f));
public static final DriveBlock DRIVE = new DriveBlock(FabricBlockSettings.create().strength(4.0f));
//Items
public static final FloppyDisk FLOPPY_ITEM = new FloppyDisk(new FabricItemSettings().maxCount(1));
public static final Item SQUEAKY_HAMMER = new Item(new FabricItemSettings());
//Item Stacks
public static final ItemStack BASIC_DISK = new ItemStack(FLOPPY_ITEM);
public static final NbtCompound BASIC_NBT = new NbtCompound();
public static final ItemStack SLIDESHOW_DISK = new ItemStack(FLOPPY_ITEM);
public static final NbtCompound SLIDESHOW_NBT = new NbtCompound();
//Item group
public static final ItemGroup ITEM_GROUP = FabricItemGroup.builder()
.icon(() -> new ItemStack(CPU))
.displayName(Text.translatable("itemGroup.redControl.group"))
.entries(((displayContext, entries) -> {
//Peripherals
entries.add(CPU);
entries.add(TERMINAL);
entries.add(DRIVE);
//Tools
entries.add(SQUEAKY_HAMMER);
//Disks
//Blank
entries.add(FLOPPY_ITEM);
//Basic
BASIC_NBT.putString("uri", "img://basic.img");
BASIC_NBT.putString("serial", "BASIC");
BASIC_NBT.putInt("CustomModelData", 1);
BASIC_DISK.setNbt(BASIC_NBT);
BASIC_DISK.setCustomName(Text.literal("Basic boot disk"));
entries.add(BASIC_DISK);
//Slideshow
SLIDESHOW_NBT.putString("uri", "img://slideshow.img");
SLIDESHOW_NBT.putString("serial", "SLIDESHOW");
SLIDESHOW_NBT.putInt("CustomModelData", 2);
SLIDESHOW_DISK.setNbt(SLIDESHOW_NBT);
SLIDESHOW_DISK.setCustomName(Text.literal("Slideshow disk"));
entries.add(SLIDESHOW_DISK);
}))
.build();
//Block Entities
public static final BlockEntityType<CpuEntity> CPU_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, modloc("cpu_block_entity"), FabricBlockEntityTypeBuilder.create(CpuEntity::new, CPU).build());
public static final BlockEntityType<TerminalEntity> TERMINAL_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, modloc("monitor_block_entity"), FabricBlockEntityTypeBuilder.create(TerminalEntity::new, TERMINAL).build());
public static final BlockEntityType<DriveEntity> DRIVE_BLOCK_ENTITY = Registry.register(Registries.BLOCK_ENTITY_TYPE, modloc("drive_block_entity"), FabricBlockEntityTypeBuilder.create(DriveEntity::new, DRIVE).build());
@Override
public void onInitialize() {
// This code runs as soon as Minecraft is in a mod-load-ready state.
// However, some things (like resources) may still be uninitialized.
// Proceed with mild caution.
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new SimpleSynchronousResourceReloadListener() {
@Override
public Identifier getFabricId() {
return Identifier.of("redcontrol","image");
}
@Override
public void reload(ResourceManager manager) {
images.clear(); //remove all previous images
for(Map.Entry<Identifier,Resource> entry : manager.findResources("image", path -> true).entrySet()) {
try(InputStream stream = entry.getValue().getInputStream()) {
String[] split = entry.getKey().getPath().split("/");
String file = split[split.length-1];
LOGGER.info("Found image {}",file);
images.put(file,stream.readAllBytes());
} catch(Exception e) {
LOGGER.error("Error occurred while loading resource binary {}", entry.getKey().toString(), e);
}
}
}
});
LOGGER.info("Initializing RedControl!");
Registry.register(Registries.BLOCK, modloc("cpu"), CPU);
Registry.register(Registries.BLOCK, modloc("monitor"), TERMINAL);
Registry.register(Registries.BLOCK, modloc("disk_drive"), DRIVE);
Registry.register(Registries.ITEM, modloc("cpu"), new BlockItem(CPU, new FabricItemSettings()));
Registry.register(Registries.ITEM, modloc("monitor"), new BlockItem(TERMINAL, new FabricItemSettings()));
Registry.register(Registries.ITEM, modloc("disk_drive"), new BlockItem(DRIVE, new FabricItemSettings()));
Registry.register(Registries.ITEM, modloc("squeaky_hammer"), SQUEAKY_HAMMER);
Registry.register(Registries.ITEM, modloc("floppy_disk"), FLOPPY_ITEM);
Registry.register(Registries.ITEM_GROUP, modloc("item_group"), ITEM_GROUP);
//Packets
ServerPlayNetworking.registerGlobalReceiver(RedControlNetworking.CPU_START, ((server, player, handler, buf, responseSender) -> server.execute(() -> {
BlockPos blockPos = buf.readBlockPos();
CpuEntity cpu = (CpuEntity) player.getWorld().getBlockEntity(blockPos);
cpu.start();
LOGGER.info("Starting cpu at {}",blockPos);
})));
ServerPlayNetworking.registerGlobalReceiver(RedControlNetworking.CPU_STOP, ((server, player, handler, buf, responseSender) -> server.execute(() -> {
BlockPos blockPos = buf.readBlockPos();
CpuEntity cpu = (CpuEntity) player.getWorld().getBlockEntity(blockPos);
cpu.stop();
LOGGER.info("Stopping cpu at {}",blockPos);
})));
ServerPlayNetworking.registerGlobalReceiver(RedControlNetworking.CPU_RESET, ((server, player, handler, buf, responseSender) -> server.execute(() -> {
BlockPos blockPos = buf.readBlockPos();
CpuEntity cpu = (CpuEntity) player.getWorld().getBlockEntity(blockPos);
cpu.reset();
LOGGER.info("Resetting cpu at {}", blockPos);
})));
ServerPlayNetworking.registerGlobalReceiver(RedControlNetworking.KEY_PRESS, ((server,player,handler,buf,responseSender) -> server.execute(() -> {
BlockPos blockPos = buf.readBlockPos();
byte key = buf.readByte();
BlockEntity term = player.getWorld().getBlockEntity(blockPos);
if (term instanceof TerminalEntity te) {
te.pushKey(key);
}
})));
BlockModificationEvents.ON_CHANGE.register((world,blockPos,oldState,newState) -> {
if (oldState.isIn(TAG_BUSABLE) ^ newState.isIn(TAG_BUSABLE)) {
Vec3d center = blockPos.toCenterPos();
((ServerWorld)world).spawnParticles(ParticleTypes.CRIT,center.x,center.y,center.z,30,0.1,0.1,0.1,0.1);
if (newState.isIn(TAG_BUSABLE)) {
//a bus-block was placed
FloodFill.INSTANCE.blockFloodFiller((ServerWorld) world, blockPos);
} else {
//a bus block was removed
FloodFill.INSTANCE.blockBreakFloodFiller((ServerWorld) world, blockPos);
}
}
});
}
static Identifier modloc(String path) {return new Identifier("redcontrol",path);}
}