Add support for custom block devices via data packs.

This commit is contained in:
Florian Nücke
2022-02-14 00:04:43 +01:00
parent e5256f3ada
commit 14210c538f
3 changed files with 106 additions and 6 deletions

View File

@@ -37,10 +37,16 @@ public final class BlockDeviceDataRegistry {
@Nullable
public static BlockDeviceData getValue(final ResourceLocation location) {
return REGISTRY.get().getValue(location);
final BlockDeviceData value = REGISTRY.get().getValue(location);
if (value != null) {
return value;
}
return FileSystems.getBlockData().get(location);
}
public static Stream<BlockDeviceData> values() {
return REGISTRY.get().getValues().stream();
return Stream.concat(
REGISTRY.get().getValues().stream(),
FileSystems.getBlockData().values().stream());
}
}

View File

@@ -7,6 +7,7 @@ import com.google.gson.JsonParser;
import com.google.gson.JsonPrimitive;
import it.unimi.dsi.fastutil.objects.Object2IntArrayMap;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.device.data.BlockDeviceData;
import li.cil.oc2.common.vm.fs.LayeredFileSystem;
import li.cil.sedna.fs.FileSystem;
import li.cil.sedna.fs.ZipStreamFileSystem;
@@ -24,16 +25,17 @@ import org.apache.logging.log4j.Logger;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import static li.cil.oc2.common.util.TextFormatUtils.formatSize;
@Mod.EventBusSubscriber(modid = API.MOD_ID, bus = Mod.EventBusSubscriber.Bus.FORGE)
public final class FileSystems {
private static final Logger LOGGER = LogManager.getLogger();
private static final LayeredFileSystem LAYERED_FILE_SYSTEM = new LayeredFileSystem();
private static final Map<ResourceLocation, BlockDeviceData> BLOCK_DEVICE_DATA = new HashMap<>();
///////////////////////////////////////////////////////////////////
@@ -41,8 +43,21 @@ public final class FileSystems {
return LAYERED_FILE_SYSTEM;
}
public static Map<ResourceLocation, BlockDeviceData> getBlockData() {
return BLOCK_DEVICE_DATA;
}
public static void reset() {
LAYERED_FILE_SYSTEM.clear();
for (final BlockDeviceData data : BLOCK_DEVICE_DATA.values()) {
try {
((ResourceBlockDeviceData) data).close();
} catch (final Exception e) {
LOGGER.error(e);
}
}
BLOCK_DEVICE_DATA.clear();
}
///////////////////////////////////////////////////////////////////
@@ -99,7 +114,25 @@ public final class FileSystems {
fileSystemOrder.put(fileSystem, 0);
}
}
case "block" -> LOGGER.error("Not yet implemented.");
case "block" -> {
final ResourceLocation location = new ResourceLocation(json.getAsJsonPrimitive("location").getAsString());
if (BlockDeviceDataRegistry.getValue(location) != null) {
LOGGER.error("Block device from datapack collides with already registered location [{}].", location);
continue;
}
final String name;
if (json.has("name")) {
name = json.getAsJsonPrimitive("name").getAsString();
} else {
name = "???";
}
final ResourceBlockDeviceData data = new ResourceBlockDeviceData(resourceManager, location, name);
LOGGER.info(" Adding block device [{}] with id [{}] and a size of [{}].", name, location, formatSize(data.getBlockDevice().getCapacity()));
BLOCK_DEVICE_DATA.put(location, data);
}
default -> LOGGER.error("Unsupported file system type [{}].", type);
}
} catch (final Throwable e) {
@@ -123,4 +156,5 @@ public final class FileSystems {
.thenCompose(stage::wait);
}
}
}

View File

@@ -0,0 +1,60 @@
/* SPDX-License-Identifier: MIT */
package li.cil.oc2.common.bus.device.data;
import li.cil.oc2.api.bus.device.data.BlockDeviceData;
import li.cil.sedna.api.device.BlockDevice;
import li.cil.sedna.device.block.ByteBufferBlockDevice;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraftforge.registries.IForgeRegistryEntry;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import java.io.InputStream;
public final class ResourceBlockDeviceData implements IForgeRegistryEntry<BlockDeviceData>, BlockDeviceData, AutoCloseable {
private final ResourceLocation location;
private final String name;
private final BlockDevice blockDevice;
public ResourceBlockDeviceData(final ResourceManager resourceManager, final ResourceLocation location, final String name) throws IOException {
this.location = location;
this.name = name;
final InputStream stream = resourceManager.getResource(location).getInputStream();
this.blockDevice = ByteBufferBlockDevice.createFromStream(stream, true);
}
@Override
public BlockDeviceData setRegistryName(final ResourceLocation name) {
throw new UnsupportedOperationException();
}
@Nullable
@Override
public ResourceLocation getRegistryName() {
return location;
}
@Override
public Class<BlockDeviceData> getRegistryType() {
return BlockDeviceData.class;
}
@Override
public void close() throws Exception {
blockDevice.close();
}
@Override
public BlockDevice getBlockDevice() {
return blockDevice;
}
@Override
public Component getDisplayName() {
return new TextComponent(name);
}
}