Port to 1.19.2

This commit is contained in:
Jackson Abney
2023-05-13 12:49:54 -08:00
parent 569288c6c8
commit e2dd0663d0
96 changed files with 450 additions and 2368 deletions

View File

@@ -6,13 +6,21 @@ buildscript {
plugins {
id "idea"
id "maven-publish"
id "net.minecraftforge.gradle" version "5.1.+"
id "net.minecraftforge.gradle" version "5.1.73"
id "com.matthewprenger.cursegradle" version "1.4.0"
}
apply plugin: 'org.spongepowered.mixin'
apply from: "minecraft.gradle"
allprojects {
gradle.projectsEvaluated {
tasks.withType(JavaCompile) {
options.compilerArgs << "-Xmaxerrs" << "1000"
}
}
}
def getGitRef() {
try {
final def stdout = new ByteArrayOutputStream()
@@ -42,12 +50,12 @@ final def hasGithubPackageCredentials =
repositories {
mavenCentral()
maven {
url 'https://cursemaven.com'
content { includeGroup 'curse.maven' }
url "https://cursemaven.com"
}
maven {
url 'https://dvs1.progwml6.com/files/maven/'
content { includeGroup 'mezz.jei' }
// location of the maven that hosts JEI files since January 2023
name = "Jared's maven"
url = "https://maven.blamejared.com/"
}
if (hasGithubPackageCredentials) {
final def GithubPackages = [
@@ -69,7 +77,7 @@ repositories {
}
dependencies {
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
minecraft "net.minecraftforge:forge:1.19.2-43.2.10"
annotationProcessor "org.spongepowered:mixin:0.8.5:processor"
// Specify the libs embedded in the library mod explicitly for local development, where
@@ -83,10 +91,13 @@ dependencies {
}
implementation "curse.maven:sedna-511276:3885542"
implementation fg.deobf("curse.maven:markdownmanual-502485:3738124")
implementation fg.deobf("curse.maven:markdownmanual-502485:4306669")
implementation fg.deobf("curse.maven:architectury-api-419699:4521273")
compileOnly fg.deobf("mezz.jei:jei-${minecraft_version}:9.7.0.180:api")
runtimeOnly fg.deobf("mezz.jei:jei-${minecraft_version}:9.7.0.180")
compileOnly fg.deobf("mezz.jei:jei-1.19.2-common-api:11.6.0.1015")
compileOnly fg.deobf("mezz.jei:jei-1.19.2-forge-api:11.6.0.1015")
runtimeOnly fg.deobf("mezz.jei:jei-1.19.2-forge:11.6.0.1015")
testImplementation "org.mockito:mockito-inline:4.3.1"
testImplementation "org.junit.jupiter:junit-jupiter-api:5.8.2"
@@ -116,7 +127,7 @@ minecraft {
runs {
all {
property "forge.logging.markers", "REGISTRIES"
property "forge.logging.console.level", "info"
property "forge.logging.console.level", "debug"
mods {
oc2 {
@@ -126,7 +137,7 @@ minecraft {
}
client {
workingDirectory project.file("run")
workingDirectory project.file("runclient")
property "forge.enabledGameTestNamespaces", "oc2"
}

View File

@@ -3,7 +3,7 @@
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=false
forge_version=40.1.68
forge_version=43.2.10
semver=0.0.0

View File

@@ -1,4 +1,4 @@
ext {
minecraft_version = '1.18.2'
minecraft_version = '1.19.2'
minecraft_sdk = 'forge'
}

View File

@@ -9,7 +9,7 @@ import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistry;
/**
* Implementations describe individual slot types. Slot types are only used
@@ -18,7 +18,7 @@ import net.minecraftforge.registries.IForgeRegistryEntry;
* <p>
* For built-in slot types, see {@link DeviceTypes}.
*/
public interface DeviceType extends IForgeRegistryEntry<DeviceType> {
public interface DeviceType {
/**
* The registry name of the registry holding device types.
*/

View File

@@ -3,18 +3,21 @@
package li.cil.oc2.api.bus.device;
import li.cil.oc2.api.API;
import net.minecraftforge.registries.ObjectHolder;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.registries.RegistryObject;
/**
* Lists built-in device types for convenience.
*/
@ObjectHolder(API.MOD_ID)
public final class DeviceTypes {
@ObjectHolder("memory") public static DeviceType MEMORY = null;
@ObjectHolder("hard_drive") public static DeviceType HARD_DRIVE = null;
@ObjectHolder("flash_memory") public static DeviceType FLASH_MEMORY = null;
@ObjectHolder("card") public static DeviceType CARD = null;
@ObjectHolder("robot_module") public static DeviceType ROBOT_MODULE = null;
@ObjectHolder("floppy") public static DeviceType FLOPPY = null;
@ObjectHolder("network_tunnel") public static DeviceType NETWORK_TUNNEL = null;
public static DeviceType MEMORY = (DeviceType) RegistryObject.create(new ResourceLocation(API.MOD_ID, "memory"), new ResourceLocation("minecraft", "device_type"), API.MOD_ID).get();
public static DeviceType HARD_DRIVE = (DeviceType) RegistryObject.create(new ResourceLocation(API.MOD_ID, "hard_drive"), new ResourceLocation("minecraft", "device_type"), API.MOD_ID).get();
public static DeviceType FLASH_MEMORY = (DeviceType) RegistryObject.create(new ResourceLocation(API.MOD_ID, "flash_memory"), new ResourceLocation("minecraft", "device_type"), API.MOD_ID).get();
public static DeviceType CARD = (DeviceType) RegistryObject.create(new ResourceLocation(API.MOD_ID, "card"), new ResourceLocation("minecraft", "device_type"), API.MOD_ID).get();
public static DeviceType ROBOT_MODULE = (DeviceType) RegistryObject.create(new ResourceLocation(API.MOD_ID, "robot_module"), new ResourceLocation("minecraft", "device_type"), API.MOD_ID).get();
public static DeviceType FLOPPY = (DeviceType) RegistryObject.create(new ResourceLocation(API.MOD_ID, "floppy"), new ResourceLocation("minecraft", "device_type"), API.MOD_ID).get();
public static DeviceType NETWORK_TUNNEL = (DeviceType) RegistryObject.create(new ResourceLocation(API.MOD_ID, "network_tunnel"), new ResourceLocation("minecraft", "device_type"), API.MOD_ID).get();
}

View File

@@ -4,7 +4,9 @@ package li.cil.oc2.api.bus.device.data;
import li.cil.sedna.api.device.BlockDevice;
import net.minecraft.network.chat.Component;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistry;
import java.util.function.Supplier;
/**
* Implementations of this interface that are registered with the registry for
@@ -25,7 +27,8 @@ import net.minecraftforge.registries.IForgeRegistryEntry;
* /give ? oc2:hard_drive{oc2:{data:"my_mod:my_block_device",readonly:true}}
* </pre>
*/
public interface BlockDeviceData extends IForgeRegistryEntry<BlockDeviceData> {
public interface BlockDeviceData {
/**
* Gets the read-only base block device this implementation describes.
*

View File

@@ -4,7 +4,7 @@ package li.cil.oc2.api.bus.device.data;
import li.cil.sedna.api.memory.MemoryMap;
import net.minecraft.network.chat.Component;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistry;
/**
* Implementations of this interface that are registered with the registry for
@@ -20,7 +20,7 @@ import net.minecraftforge.registries.IForgeRegistryEntry;
* /give &#64;p oc2:flash_memory{oc2:{firmware:"my_mod:my_firmware"}}
* </pre>
*/
public interface Firmware extends IForgeRegistryEntry<Firmware> {
public interface Firmware {
/**
* Runs this firmware.
* <p>

View File

@@ -7,7 +7,7 @@ import li.cil.oc2.api.bus.device.rpc.RPCDevice;
import li.cil.oc2.api.bus.device.vm.VMDevice;
import li.cil.oc2.api.util.Invalidatable;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistry;
/**
* This is used to query for devices given a block face.
@@ -45,7 +45,7 @@ import net.minecraftforge.registries.IForgeRegistryEntry;
* @see li.cil.oc2.api.bus.device.vm.VMDevice
* @see BlockDeviceQuery
*/
public interface BlockDeviceProvider extends IForgeRegistryEntry<BlockDeviceProvider> {
public interface BlockDeviceProvider {
/**
* Get a device for the specified query.
*

View File

@@ -6,7 +6,7 @@ import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.rpc.RPCDevice;
import li.cil.oc2.api.bus.device.vm.VMDevice;
import net.minecraft.nbt.CompoundTag;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistry;
import javax.annotation.Nullable;
import java.util.Optional;
@@ -42,7 +42,7 @@ import java.util.Optional;
* @see li.cil.oc2.api.bus.device.vm.VMDevice
* @see ItemDeviceQuery
*/
public interface ItemDeviceProvider extends IForgeRegistryEntry<ItemDeviceProvider> {
public interface ItemDeviceProvider {
/**
* Get a device for the specified query.
*

View File

@@ -24,9 +24,10 @@ import net.minecraft.client.renderer.ItemBlockRenderTypes;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.world.inventory.InventoryMenu;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.ModelRegistryEvent;
import net.minecraftforge.client.event.ModelEvent.RegisterGeometryLoaders;
import net.minecraftforge.client.event.RenderGuiOverlayEvent;
import net.minecraftforge.client.event.TextureStitchEvent;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
@@ -62,8 +63,17 @@ public final class ClientSetup {
}
@SubscribeEvent
public static void handleModelRegistryEvent(final ModelRegistryEvent event) {
ModelLoaderRegistry.registerLoader(Blocks.BUS_CABLE.getId(), new BusCableModelLoader());
public static void handleModelRegistryEvent(final RegisterGeometryLoaders event) {
event.register(Blocks.BUS_CABLE.getId().toString().replace("oc2:", ""), new BusCableModelLoader());
}
@SubscribeEvent
public void renderHotbar(RenderGuiOverlayEvent event) {
if(event.getOverlay().id() == VanillaGuiOverlay.HOTBAR.id() && KeyboardScreen.hideHotbar) {
event.setCanceled(true);
} else if(event.getOverlay().id() == VanillaGuiOverlay.HOTBAR.id()) {
event.setCanceled(false);
}
}
@SubscribeEvent

View File

@@ -7,6 +7,7 @@ import net.minecraft.client.resources.sounds.AbstractTickableSoundInstance;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
@@ -25,7 +26,7 @@ public final class LoopingBlockEntitySound extends AbstractTickableSoundInstance
///////////////////////////////////////////////////////////////////
public LoopingBlockEntitySound(final BlockEntity blockEntity, final SoundEvent sound) {
super(sound, SoundSource.BLOCKS);
super(sound, SoundSource.BLOCKS, RandomSource.create());
this.blockEntity = blockEntity;
this.volume = 0;

View File

@@ -16,7 +16,6 @@ import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.client.renderer.Rect2i;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Inventory;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -81,8 +80,8 @@ public abstract class AbstractMachineInventoryScreen<T extends AbstractMachineTe
return menu.getVirtualMachine().isRunning();
}
}).withTooltip(
new TranslatableComponent(Constants.COMPUTER_SCREEN_POWER_CAPTION),
new TranslatableComponent(Constants.COMPUTER_SCREEN_POWER_DESCRIPTION)
Component.translatable(Constants.COMPUTER_SCREEN_POWER_CAPTION),
Component.translatable(Constants.COMPUTER_SCREEN_POWER_DESCRIPTION)
);
addRenderableWidget(new ImageButton(
@@ -95,7 +94,7 @@ public abstract class AbstractMachineInventoryScreen<T extends AbstractMachineTe
public void onPress() {
menu.switchToTerminal();
}
}.withTooltip(new TranslatableComponent(Constants.MACHINE_OPEN_TERMINAL_CAPTION)));
}.withTooltip(Component.translatable(Constants.MACHINE_OPEN_TERMINAL_CAPTION)));
}
@Override
@@ -139,9 +138,9 @@ public abstract class AbstractMachineInventoryScreen<T extends AbstractMachineTe
if (shouldRenderEnergyBar()) {
if (isMouseOver(mouseX, mouseY, -Sprites.SIDEBAR_2.width + 4, ENERGY_TOP + 4, Sprites.ENERGY_BAR.width, Sprites.ENERGY_BAR.height)) {
final List<? extends FormattedText> tooltip = asList(
new TranslatableComponent(Constants.TOOLTIP_ENERGY,
Component.translatable(Constants.TOOLTIP_ENERGY,
withFormat(menu.getEnergy() + "/" + menu.getEnergyCapacity(), ChatFormatting.GREEN)),
new TranslatableComponent(Constants.TOOLTIP_ENERGY_CONSUMPTION,
Component.translatable(Constants.TOOLTIP_ENERGY_CONSUMPTION,
withFormat(String.valueOf(menu.getEnergyConsumption()), ChatFormatting.GREEN))
);
TooltipUtils.drawTooltip(stack, tooltip, mouseX, mouseY, 200);

View File

@@ -14,8 +14,6 @@ import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.renderer.Rect2i;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.FormattedText;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.world.entity.player.Inventory;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
@@ -101,7 +99,7 @@ public abstract class AbstractMachineTerminalScreen<T extends AbstractMachineTer
super.init();
terminalWidget.init();
final EditBox focusIndicatorEditBox = new EditBox(font, 0, 0, 0, 0, TextComponent.EMPTY);
final EditBox focusIndicatorEditBox = new EditBox(font, 0, 0, 0, 0, Component.empty());
focusIndicatorEditBox.setFocus(true);
setFocusIndicatorEditBox(focusIndicatorEditBox);
@@ -123,8 +121,8 @@ public abstract class AbstractMachineTerminalScreen<T extends AbstractMachineTer
return menu.getVirtualMachine().isRunning();
}
}).withTooltip(
new TranslatableComponent(Constants.COMPUTER_SCREEN_POWER_CAPTION),
new TranslatableComponent(Constants.COMPUTER_SCREEN_POWER_DESCRIPTION)
Component.translatable(Constants.COMPUTER_SCREEN_POWER_CAPTION),
Component.translatable(Constants.COMPUTER_SCREEN_POWER_DESCRIPTION)
);
addRenderableWidget(new ToggleImageButton(
@@ -145,8 +143,8 @@ public abstract class AbstractMachineTerminalScreen<T extends AbstractMachineTer
return isInputCaptureEnabled;
}
}).withTooltip(
new TranslatableComponent(Constants.TERMINAL_CAPTURE_INPUT_CAPTION),
new TranslatableComponent(Constants.TERMINAL_CAPTURE_INPUT_DESCRIPTION)
Component.translatable(Constants.TERMINAL_CAPTURE_INPUT_CAPTION),
Component.translatable(Constants.TERMINAL_CAPTURE_INPUT_DESCRIPTION)
);
addRenderableWidget(new ImageButton(
@@ -159,7 +157,7 @@ public abstract class AbstractMachineTerminalScreen<T extends AbstractMachineTer
public void onPress() {
menu.switchToInventory();
}
}).withTooltip(new TranslatableComponent(Constants.MACHINE_OPEN_INVENTORY_CAPTION));
}).withTooltip(Component.translatable(Constants.MACHINE_OPEN_INVENTORY_CAPTION));
}
@Override
@@ -210,9 +208,9 @@ public abstract class AbstractMachineTerminalScreen<T extends AbstractMachineTer
if (isMouseOver(mouseX, mouseY, -Sprites.SIDEBAR_2.width + 4, ENERGY_TOP + 4, Sprites.ENERGY_BAR.width, Sprites.ENERGY_BAR.height)) {
final List<? extends FormattedText> tooltip = asList(
new TranslatableComponent(Constants.TOOLTIP_ENERGY,
Component.translatable(Constants.TOOLTIP_ENERGY,
withFormat(menu.getEnergy() + "/" + menu.getEnergyCapacity(), ChatFormatting.GREEN)),
new TranslatableComponent(Constants.TOOLTIP_ENERGY_CONSUMPTION,
Component.translatable(Constants.TOOLTIP_ENERGY_CONSUMPTION,
withFormat(String.valueOf(menu.getEnergyConsumption()), ChatFormatting.GREEN))
);
TooltipUtils.drawTooltip(stack, tooltip, mouseX, mouseY, 200);

View File

@@ -13,7 +13,7 @@ import li.cil.oc2.common.network.message.BusInterfaceNameMessage;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.phys.Vec3;
import org.lwjgl.glfw.GLFW;
@@ -74,7 +74,7 @@ public final class BusInterfaceScreen extends Screen {
setInterfaceName(nameField.getValue());
onClose();
}
}).withTooltip(new TranslatableComponent(Constants.TOOLTIP_CONFIRM));
}).withTooltip(Component.translatable(Constants.TOOLTIP_CONFIRM));
addRenderableWidget(new ImageButton(
left + CANCEL_LEFT, top + CANCEL_TOP,
@@ -87,7 +87,7 @@ public final class BusInterfaceScreen extends Screen {
super.onPress();
onClose();
}
}).withTooltip(new TranslatableComponent(Constants.TOOLTIP_CANCEL));
}).withTooltip(Component.translatable(Constants.TOOLTIP_CANCEL));
}
@Override

View File

@@ -11,8 +11,6 @@ import net.minecraft.client.gui.components.ObjectSelectionList;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextColor;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -22,6 +20,7 @@ import java.nio.file.*;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import static li.cil.oc2.common.util.TranslationUtils.text;
@@ -157,7 +156,7 @@ public final class FileChooserScreen extends Screen {
final int buttonTop = fileNameTop + TEXT_FIELD_HEIGHT + WIDGET_SPACING;
final int buttonCount = 2;
final int buttonWidth = widgetsWidth / buttonCount - (buttonCount - 1) * WIDGET_SPACING;
okButton = addRenderableWidget(new Button(MARGIN, buttonTop, buttonWidth, BUTTON_HEIGHT, TextComponent.EMPTY, this::handleOkPressed));
okButton = addRenderableWidget(new Button(MARGIN, buttonTop, buttonWidth, BUTTON_HEIGHT, Component.empty(), this::handleOkPressed));
addRenderableWidget(new Button(MARGIN + buttonWidth + WIDGET_SPACING, buttonTop, buttonWidth, BUTTON_HEIGHT, CANCEL_TEXT, this::handleCancelPressed));
fileList.refreshFiles(directory);
@@ -300,7 +299,7 @@ public final class FileChooserScreen extends Screen {
return 1;
}
return p1.getFileName().compareTo(p2.getFileName());
}).toList();
}).collect(Collectors.toList());
for (final Path path : files) {
try {
if (Files.isHidden(path)) {
@@ -347,7 +346,7 @@ public final class FileChooserScreen extends Screen {
}
private FileList.FileEntry createFileEntry(final Path file) {
return new FileList.FileEntry(file, new TextComponent(file.getFileName().toString()));
return new FileList.FileEntry(file, Component.literal(file.getFileName().toString()));
}
private FileList.FileEntry createDirectoryEntry(final Path path) {
@@ -358,7 +357,7 @@ public final class FileChooserScreen extends Screen {
final TextColor color = path != null && Files.exists(path)
? TextColor.fromRgb(0xA0A0FF)
: TextColor.fromLegacyFormat(ChatFormatting.GRAY);
return new FileList.FileEntry(path, new TextComponent(displayName)
return new FileList.FileEntry(path, Component.literal(displayName)
.withStyle(s -> s.withColor(color)));
}
@@ -412,7 +411,7 @@ public final class FileChooserScreen extends Screen {
@Override
public Component getNarration() {
return new TranslatableComponent("narrator.select", displayName);
return Component.translatable("narrator.select", displayName);
}
}
}

View File

@@ -14,21 +14,22 @@ import net.minecraft.client.MouseHandler;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.GameRenderer;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.gui.ForgeIngameGui;
import net.minecraftforge.client.gui.OverlayRegistry;
import net.minecraftforge.client.event.RenderGuiOverlayEvent;
import net.minecraftforge.client.gui.overlay.VanillaGuiOverlay;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import org.lwjgl.glfw.GLFW;
import java.util.Random;
public final class KeyboardScreen extends Screen {
private static final int BORDER_SIZE = 4;
private static final float ARM_SWING_RATE = 0.8f;
private static final int BORDER_COLOR = 0xFFFFFFFF;
private static final TranslatableComponent CLOSE_INFO = new TranslatableComponent("gui.oc2.keyboard.close_info");
private static final MutableComponent CLOSE_INFO = Component.translatable("gui.oc2.keyboard.close_info");
///////////////////////////////////////////////////////////////////
@@ -36,6 +37,8 @@ public final class KeyboardScreen extends Screen {
///////////////////////////////////////////////////////////////////
public static boolean hideHotbar = false;
public KeyboardScreen(final KeyboardBlockEntity keyboard) {
super(Items.KEYBOARD.get().getDescription());
this.keyboard = keyboard;
@@ -52,7 +55,7 @@ public final class KeyboardScreen extends Screen {
grabMouse();
// Disable hotbar since we don't need it here, and it just blocks screen space.
OverlayRegistry.enableOverlay(ForgeIngameGui.HOTBAR_ELEMENT, false);
hideHotbar = true;
}
@Override
@@ -109,7 +112,7 @@ public final class KeyboardScreen extends Screen {
public void removed() {
super.removed();
OverlayRegistry.enableOverlay(ForgeIngameGui.HOTBAR_ELEMENT, true);
hideHotbar = false;
}
///////////////////////////////////////////////////////////////////
@@ -155,7 +158,7 @@ public final class KeyboardScreen extends Screen {
return;
}
final Random random = player.getRandom();
final RandomSource random = player.getRandom();
if (random.nextFloat() < ARM_SWING_RATE) {
return;
}

View File

@@ -24,7 +24,7 @@ import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.sounds.SimpleSoundInstance;
import net.minecraft.core.Direction;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
@@ -33,6 +33,7 @@ import net.minecraft.world.inventory.InventoryMenu;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.spongepowered.asm.mixin.Mutable;
import javax.annotation.Nullable;
@@ -159,7 +160,7 @@ public final class NetworkInterfaceCardScreen extends Screen {
if (focusedSide != null) {
final Component enabledComponent = getConfiguration(focusedSide) ? CONNECTIVITY_ENABLED_TEXT : CONNECTIVITY_DISABLED_TEXT;
final TranslatableComponent tooltip = new TranslatableComponent(SIDE_STATE_TEXT, enabledComponent);
final MutableComponent tooltip = Component.translatable(SIDE_STATE_TEXT, enabledComponent);
renderTooltip(stack, tooltip, mouseX, mouseY);
}

View File

@@ -10,7 +10,6 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.components.AbstractButton;
import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.util.Mth;
import java.util.Arrays;
@@ -35,7 +34,7 @@ public abstract class ImageButton extends AbstractButton {
///////////////////////////////////////////////////////////////////
protected ImageButton(final int x, final int y, final int width, final int height, final Sprite baseImage, final Sprite pressedImage) {
super(x, y, width, height, TextComponent.EMPTY);
super(x, y, width, height, Component.empty());
this.baseImage = baseImage;
this.pressedImage = pressedImage;
}
@@ -104,7 +103,7 @@ public abstract class ImageButton extends AbstractButton {
background.draw(stack, x, y);
if (!Objects.equals(getMessage(), TextComponent.EMPTY)) {
if (!Objects.equals(getMessage(), Component.empty())) {
drawCenteredString(stack, Minecraft.getInstance().font, getMessage(),
x + width / 2, y + (height - 8) / 2,
getFGColor() | Mth.ceil(alpha * 255) << 24);

View File

@@ -16,17 +16,21 @@ import li.cil.oc2.api.API;
import li.cil.oc2.common.block.Blocks;
import li.cil.oc2.common.item.Items;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.RegistryObject;
@OnlyIn(Dist.CLIENT)
public final class Manuals {
private static final DeferredRegister<ManualModel> MANUALS = RegistryUtils.getInitializerFor(Constants.MANUAL_REGISTRY);
private static final DeferredRegister<ManualModel> MANUALS = DeferredRegister.create(Constants.MANUAL_REGISTRY, Constants.MOD_ID);
private static final DeferredRegister<PathProvider> PATH_PROVIDERS = DeferredRegister.create(Constants.PATH_PROVIDER_REGISTRY, Constants.MOD_ID);
private static final DeferredRegister<DocumentProvider> CONTENT_PROVIDERS = DeferredRegister.create(Constants.DOCUMENT_PROVIDER_REGISTRY, Constants.MOD_ID);
private static final DeferredRegister<Tab> TABS = DeferredRegister.create(Constants.TAB_REGISTRY, Constants.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -35,24 +39,26 @@ public final class Manuals {
///////////////////////////////////////////////////////////////////
public static void initialize() {
final DeferredRegister<PathProvider> pathProviders = RegistryUtils.getInitializerFor(Constants.PATH_PROVIDER_REGISTRY);
final DeferredRegister<DocumentProvider> contentProviders = RegistryUtils.getInitializerFor(Constants.DOCUMENT_PROVIDER_REGISTRY);
final DeferredRegister<Tab> tabs = RegistryUtils.getInitializerFor(Constants.TAB_REGISTRY);
MANUALS.register(FMLJavaModLoadingContext.get().getModEventBus());
pathProviders.register("path_provider", () -> new NamespacePathProvider(API.MOD_ID));
contentProviders.register("content_provider", () -> new NamespaceDocumentProvider(API.MOD_ID, "doc"));
PATH_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus());
CONTENT_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus());
TABS.register(FMLJavaModLoadingContext.get().getModEventBus());
tabs.register("home", () -> new TextureTab(
PATH_PROVIDERS.register("path_provider", () -> new NamespacePathProvider(API.MOD_ID));
CONTENT_PROVIDERS.register("content_provider", () -> new NamespaceDocumentProvider(API.MOD_ID, "doc"));
TABS.register("home", () -> new TextureTab(
ManualModel.LANGUAGE_KEY + "/index.md",
new TranslatableComponent("manual." + API.MOD_ID + ".home"),
Component.translatable("manual." + API.MOD_ID + ".home"),
new ResourceLocation(API.MOD_ID, "textures/gui/manual/home.png")));
tabs.register("blocks", () -> new ItemStackTab(
TABS.register("blocks", () -> new ItemStackTab(
ManualModel.LANGUAGE_KEY + "/block/index.md",
new TranslatableComponent("manual." + API.MOD_ID + ".blocks"),
Component.translatable("manual." + API.MOD_ID + ".blocks"),
new ItemStack(Blocks.COMPUTER.get())));
tabs.register("modules", () -> new ItemStackTab(
TABS.register("modules", () -> new ItemStackTab(
ManualModel.LANGUAGE_KEY + "/item/index.md",
new TranslatableComponent("manual." + API.MOD_ID + ".items"),
Component.translatable("manual." + API.MOD_ID + ".items"),
new ItemStack(Items.TRANSISTOR.get())));
}
}

View File

@@ -16,16 +16,16 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.util.RandomSource;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.BlockAndTintGetter;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.EnumProperty;
import net.minecraftforge.client.MinecraftForgeClient;
import net.minecraftforge.client.model.data.IDynamicBakedModel;
import net.minecraftforge.client.model.data.IModelData;
import net.minecraftforge.client.model.data.ModelDataMap;
import net.minecraftforge.client.model.IDynamicBakedModel;
import net.minecraftforge.client.model.data.ModelData;
import net.minecraftforge.client.model.data.ModelDataManager;
import net.minecraftforge.client.model.data.ModelProperty;
import javax.annotation.Nonnull;
@@ -33,51 +33,51 @@ import javax.annotation.Nullable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
public record BusCableBakedModel(
BakedModel proxy,
BakedModel[] straightModelByAxis,
BakedModel[] supportModelByFace
) implements IDynamicBakedModel {
public final class BusCableBakedModel implements IDynamicBakedModel {
private static final ModelProperty<BusCableSupportSide> BUS_CABLE_SUPPORT_PROPERTY = new ModelProperty<>();
private static final ModelProperty<BusCableFacade> BUS_CABLE_FACADE_PROPERTY = new ModelProperty<>();
private final BakedModel proxy;
///////////////////////////////////////////////////////////////////
BusCableBakedModel(final BakedModel proxy) {
this.proxy = proxy;
}
@Override
@Nonnull
public List<BakedQuad> getQuads(@Nullable final BlockState state, @Nullable final Direction side, final Random rand, final IModelData extraData) {
final RenderType layer = MinecraftForgeClient.getRenderType();
public List<BakedQuad> getQuads(@Nullable final BlockState state, @Nullable final Direction side, final RandomSource rand, final ModelData extraData, @Nullable RenderType renderType) {
if (extraData.hasProperty(BUS_CABLE_FACADE_PROPERTY)) {
final BusCableFacade facade = extraData.getData(BUS_CABLE_FACADE_PROPERTY);
if (facade != null && (layer == null || ItemBlockRenderTypes.canRenderInLayer(facade.blockState, layer))) {
return facade.model.getQuads(facade.blockState, side, rand, facade.data);
final BusCableFacade facade = extraData.get(BUS_CABLE_FACADE_PROPERTY);
if (side != null) {
if (facade != null && (renderType != null && renderType.equals(RenderType.solid()))) {
return facade.model.getQuads(state, side, rand, facade.data, renderType);
} else {
return Collections.emptyList();
}
}
if (state == null || !state.getValue(BusCableBlock.HAS_CABLE) || layer == null || !layer.equals(RenderType.solid())) {
return Collections.emptyList();
}
for (int i = 0; i < Constants.AXES.length; i++) {
final Direction.Axis axis = Constants.AXES[i];
if (isStraightAlongAxis(state, axis)) {
return straightModelByAxis[i].getQuads(state, side, rand, extraData);
} else {
if (state == null || !state.getValue(BusCableBlock.HAS_CABLE) || renderType == null || !renderType.equals(RenderType.solid())) {
return Collections.emptyList();
}
for (int i = 0; i < Constants.AXES.length; i++) {
final Direction.Axis axis = Constants.AXES[i];
if (isStraightAlongAxis(state, axis)) {
return proxy.getQuads(state, side, rand, extraData, renderType);
}
}
final ArrayList<BakedQuad> quads = new ArrayList<>(proxy.getQuads(state, side, rand, extraData, renderType));
final BusCableSupportSide supportSide = extraData.get(BUS_CABLE_SUPPORT_PROPERTY);
if (supportSide != null) {
quads.addAll(proxy.getQuads(state, side, rand, extraData, renderType));
}
return quads;
}
final ArrayList<BakedQuad> quads = new ArrayList<>(proxy.getQuads(state, side, rand, extraData));
final BusCableSupportSide supportSide = extraData.getData(BUS_CABLE_SUPPORT_PROPERTY);
if (supportSide != null) {
quads.addAll(supportModelByFace[supportSide.value.get3DDataValue()].getQuads(state, side, rand, extraData));
}
return quads;
}
@Override
@@ -113,7 +113,7 @@ public record BusCableBakedModel(
@Override
@Nonnull
public IModelData getModelData(final BlockAndTintGetter level, final BlockPos pos, final BlockState state, final IModelData blockEntityData) {
public ModelData getModelData(final BlockAndTintGetter level, final BlockPos pos, final BlockState state, final ModelData blockEntityData) {
if (state.hasProperty(BusCableBlock.HAS_FACADE) && state.getValue(BusCableBlock.HAS_FACADE)) {
final BlockEntity blockEntity = level.getBlockEntity(pos);
@@ -128,10 +128,10 @@ public record BusCableBakedModel(
final BlockModelShaper shapes = Minecraft.getInstance().getBlockRenderer().getBlockModelShaper();
final BakedModel model = shapes.getBlockModel(facadeState);
final IModelData data = model.getModelData(level, pos, facadeState, blockEntityData);
final ModelData data = model.getModelData(level, pos, facadeState, blockEntityData);
return new ModelDataMap.Builder()
.withInitial(BUS_CABLE_FACADE_PROPERTY, new BusCableFacade(facadeState, model, data))
return ModelData.builder()
.with(BUS_CABLE_FACADE_PROPERTY, new BusCableFacade(facadeState, model, data))
.build();
}
@@ -150,8 +150,8 @@ public record BusCableBakedModel(
}
if (supportSide != null) {
return new ModelDataMap.Builder()
.withInitial(BUS_CABLE_SUPPORT_PROPERTY, new BusCableSupportSide(supportSide))
return ModelData.builder()
.with(BUS_CABLE_SUPPORT_PROPERTY, new BusCableSupportSide(supportSide))
.build();
}
@@ -186,5 +186,5 @@ public record BusCableBakedModel(
private record BusCableSupportSide(Direction value) { }
private record BusCableFacade(BlockState blockState, BakedModel model, IModelData data) { }
private record BusCableFacade(BlockState blockState, BakedModel model, ModelData data) { }
}

View File

@@ -8,10 +8,8 @@ import net.minecraft.client.renderer.block.model.ItemOverrides;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.*;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.client.model.CompositeModelState;
import net.minecraftforge.client.model.IModelConfiguration;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.geometry.IModelGeometry;
import net.minecraftforge.client.model.geometry.IGeometryBakingContext;
import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
import java.util.ArrayList;
import java.util.Collection;
@@ -20,35 +18,25 @@ import java.util.function.Function;
import static java.util.Objects.requireNonNull;
public record BusCableModel(ModelLoaderRegistry.VanillaProxy proxy) implements IModelGeometry<BusCableModel> {
public final class BusCableModel implements IUnbakedGeometry<BusCableModel> {
private static final ResourceLocation BUS_CABLE_STRAIGHT_MODEL = new ResourceLocation(API.MOD_ID, "block/cable_straight");
private static final ResourceLocation BUS_CABLE_SUPPORT_MODEL = new ResourceLocation(API.MOD_ID, "block/cable_support");
private final IUnbakedGeometry<?> proxy;
BusCableModel(final IUnbakedGeometry<?> proxy) {
this.proxy = proxy;
}
///////////////////////////////////////////////////////////////////
@Override
public BakedModel bake(final IModelConfiguration owner, final ModelBakery bakery, final Function<Material, TextureAtlasSprite> spriteGetter, final ModelState modelTransform, final ItemOverrides overrides, final ResourceLocation modelLocation) {
final BakedModel bakedBaseModel = proxy.bake(owner, bakery, spriteGetter, modelTransform, overrides, modelLocation);
final BakedModel[] straightModelByAxis = {
requireNonNull(bakery.bake(BUS_CABLE_STRAIGHT_MODEL, new CompositeModelState(modelTransform, BlockModelRotation.X0_Y90), spriteGetter)),
requireNonNull(bakery.bake(BUS_CABLE_STRAIGHT_MODEL, new CompositeModelState(modelTransform, BlockModelRotation.X90_Y0), spriteGetter)),
requireNonNull(bakery.bake(BUS_CABLE_STRAIGHT_MODEL, modelTransform, spriteGetter))
};
final BakedModel[] supportModelByFace = {
requireNonNull(bakery.bake(BUS_CABLE_SUPPORT_MODEL, new CompositeModelState(modelTransform, BlockModelRotation.X270_Y0), spriteGetter)), // -y
requireNonNull(bakery.bake(BUS_CABLE_SUPPORT_MODEL, new CompositeModelState(modelTransform, BlockModelRotation.X90_Y0), spriteGetter)), // +y
requireNonNull(bakery.bake(BUS_CABLE_SUPPORT_MODEL, new CompositeModelState(modelTransform, BlockModelRotation.X0_Y180), spriteGetter)), // -z
requireNonNull(bakery.bake(BUS_CABLE_SUPPORT_MODEL, modelTransform, spriteGetter)), // +z
requireNonNull(bakery.bake(BUS_CABLE_SUPPORT_MODEL, new CompositeModelState(modelTransform, BlockModelRotation.X0_Y90), spriteGetter)), // -x
requireNonNull(bakery.bake(BUS_CABLE_SUPPORT_MODEL, new CompositeModelState(modelTransform, BlockModelRotation.X0_Y270), spriteGetter)) // +x
};
return new BusCableBakedModel(bakedBaseModel, straightModelByAxis, supportModelByFace);
public BakedModel bake(final IGeometryBakingContext owner, final ModelBakery bakery, final Function<Material, TextureAtlasSprite> spriteGetter, final ModelState modelTransform, final ItemOverrides overrides, final ResourceLocation modelLocation) {
return new BusCableBakedModel(proxy.bake(owner, bakery, spriteGetter, modelTransform, overrides, modelLocation));
}
@Override
public Collection<Material> getTextures(final IModelConfiguration owner, final Function<ResourceLocation, UnbakedModel> modelGetter, final Set<Pair<String, String>> missingTextureErrors) {
final ArrayList<Material> textures = new ArrayList<>(proxy.getTextures(owner, modelGetter, missingTextureErrors));
public Collection<Material> getMaterials(final IGeometryBakingContext owner, final Function<ResourceLocation, UnbakedModel> modelGetter, final Set<Pair<String, String>> missingTextureErrors) {
final ArrayList<Material> textures = new ArrayList<>(proxy.getMaterials(owner, modelGetter, missingTextureErrors));
textures.addAll(modelGetter.apply(BUS_CABLE_STRAIGHT_MODEL).getMaterials(modelGetter, missingTextureErrors));
textures.addAll(modelGetter.apply(BUS_CABLE_SUPPORT_MODEL).getMaterials(modelGetter, missingTextureErrors));
return textures;

View File

@@ -4,17 +4,13 @@ package li.cil.oc2.client.model;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonObject;
import net.minecraft.server.packs.resources.ResourceManager;
import net.minecraftforge.client.model.IModelLoader;
import net.minecraftforge.client.model.ModelLoaderRegistry;
import net.minecraftforge.client.model.ElementsModel;
import net.minecraftforge.client.model.geometry.IGeometryLoader;
public final class BusCableModelLoader implements IModelLoader<BusCableModel> {
@Override
public void onResourceManagerReload(final ResourceManager resourceManager) {
}
public final class BusCableModelLoader implements IGeometryLoader<BusCableModel> {
@Override
public BusCableModel read(final JsonDeserializationContext context, final JsonObject modelContents) {
return new BusCableModel(ModelLoaderRegistry.VanillaProxy.Loader.INSTANCE.read(context, modelContents));
public BusCableModel read(final JsonObject modelContents, final JsonDeserializationContext context) {
return new BusCableModel(ElementsModel.Loader.INSTANCE.read(modelContents, context));
}
}

View File

@@ -21,8 +21,8 @@ import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.RenderLevelStageEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
@@ -80,7 +80,7 @@ public final class NetworkCableRenderer {
@SubscribeEvent
public static void handleChunkUnloadEvent(final ChunkEvent.Unload event) {
if (event.getWorld().isClientSide()) {
if (event.getLevel().isClientSide()) {
final ChunkPos chunkPos = event.getChunk().getPos();
final ArrayList<NetworkConnectorBlockEntity> list = new ArrayList<>(NetworkCableRenderer.connectors);
@@ -96,9 +96,9 @@ public final class NetworkCableRenderer {
}
@SubscribeEvent
public static void handleWorldUnloadEvent(final WorldEvent.Unload event) {
if (event.getWorld().isClientSide()) {
final LevelAccessor level = event.getWorld();
public static void handleWorldUnloadEvent(final LevelEvent.Unload event) {
if (event.getLevel().isClientSide()) {
final LevelAccessor level = event.getLevel();
final ArrayList<NetworkConnectorBlockEntity> list = new ArrayList<>(NetworkCableRenderer.connectors);
for (final NetworkConnectorBlockEntity connector : list) {

View File

@@ -40,9 +40,9 @@ import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.event.EntityViewRenderEvent;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.client.event.RenderLevelStageEvent;
import net.minecraftforge.client.event.RenderNameplateEvent;
import net.minecraftforge.client.event.RenderNameTagEvent;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.eventbus.api.Event;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@@ -203,7 +203,7 @@ public final class ProjectorDepthRenderer {
* Suppresses fog rendering while rendering depth buffer for projectors.
*/
@SubscribeEvent
public static void handleFog(final EntityViewRenderEvent.RenderFogEvent event) {
public static void handleFog(final EntityRenderersEvent event) {
if (isRenderingProjectorDepth) {
FogRenderer.setupNoFog();
}
@@ -213,7 +213,7 @@ public final class ProjectorDepthRenderer {
* Suppresses nameplate rendering while rendering depth buffer for projectors.
*/
@SubscribeEvent
public static void handleNameplate(final RenderNameplateEvent event) {
public static void handleNameplate(final RenderNameTagEvent event) {
if (isRenderingProjectorDepth) {
event.setResult(Event.Result.DENY);
}
@@ -275,8 +275,8 @@ public final class ProjectorDepthRenderer {
minecraft.hitResult = null;
// Skip shadow rendering for perf.
entityShadowsBak = minecraft.options.entityShadows;
minecraft.options.entityShadows = false;
entityShadowsBak = minecraft.options.entityShadows().get();
minecraft.options.entityShadows().set(false);
minecraftCameraEntityBak = minecraft.getCameraEntity();
minecraft.setCameraEntity(ProjectorCameraEntity.get(level, Vec3.ZERO, partialTicks));
@@ -288,7 +288,7 @@ public final class ProjectorDepthRenderer {
private static void finishDepthBufferRendering(final Minecraft minecraft) {
minecraft.hitResult = hitResultBak;
minecraft.options.entityShadows = entityShadowsBak;
minecraft.options.entityShadows().set(entityShadowsBak);
RenderSystem.restoreProjectionMatrix();
@@ -566,7 +566,7 @@ public final class ProjectorDepthRenderer {
}
private ProjectorCameraEntity(final Level level, final BlockPos blockPos, final float rotationY) {
super(level, blockPos, rotationY, FakePlayerUtils.getFakePlayerProfile());
super(level, blockPos, rotationY, FakePlayerUtils.getFakePlayerProfile(), null);
}
@Override

View File

@@ -16,7 +16,7 @@ import net.minecraft.client.model.geom.builders.MeshDefinition;
import net.minecraft.client.model.geom.builders.PartDefinition;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.common.model.TransformationHelper;
import net.minecraftforge.common.util.TransformationHelper;
public final class RobotModel extends EntityModel<Robot> {
public static final ModelLayerLocation ROBOT_MODEL_LAYER = new ModelLayerLocation(new ResourceLocation(API.MOD_ID, "robot"), "main");

View File

@@ -2,6 +2,7 @@
package li.cil.oc2.common;
import dev.architectury.platform.forge.EventBuses;
import li.cil.ceres.Ceres;
import li.cil.oc2.api.API;
import li.cil.oc2.client.ClientSetup;
@@ -25,13 +26,16 @@ import li.cil.oc2.common.util.SoundEvents;
import li.cil.oc2.common.vm.provider.DeviceTreeProviders;
import li.cil.sedna.Sedna;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.DistExecutor;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.NewRegistryEvent;
@Mod(API.MOD_ID)
public final class Main {
public Main() {
EventBuses.registerModEventBus(API.MOD_ID, FMLJavaModLoadingContext.get().getModEventBus());
Ceres.initialize();
Sedna.initialize();
DeviceTreeProviders.initialize();
@@ -57,12 +61,9 @@ public final class Main {
BlockDeviceDataRegistry.initialize();
FirmwareRegistry.initialize();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> Manuals::initialize);
RegistryUtils.finish();
ItemRenameHandler.initialize();
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> Manuals::initialize);
FMLJavaModLoadingContext.get().getModEventBus().register(CommonSetup.class);
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () ->
FMLJavaModLoadingContext.get().getModEventBus().register(ClientSetup.class));

View File

@@ -2,14 +2,16 @@
package li.cil.oc2.common.block;
import li.cil.oc2.api.API;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public final class Blocks {
private static final DeferredRegister<Block> BLOCKS = RegistryUtils.getInitializerFor(ForgeRegistries.BLOCKS);
private static final DeferredRegister<Block> BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, API.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -27,5 +29,6 @@ public final class Blocks {
///////////////////////////////////////////////////////////////////
public static void initialize() {
BLOCKS.register(FMLJavaModLoadingContext.get().getModEventBus());
}
}

View File

@@ -230,7 +230,7 @@ public final class ComputerBlock extends HorizontalDirectionalBlock implements E
final ItemStack computer = new ItemStack(this);
final CompoundTag itemsTag = NBTUtils.getOrCreateChildTag(computer.getOrCreateTag(), BLOCK_ENTITY_TAG_NAME_IN_ITEM, ITEMS_TAG_NAME);
itemsTag.put(key(DeviceTypes.FLASH_MEMORY), makeInventoryTag(
itemsTag.put(DeviceTypes.FLASH_MEMORY.getName().toString(), makeInventoryTag(
new ItemStack(Items.FLASH_MEMORY_CUSTOM.get())
));
@@ -241,16 +241,16 @@ public final class ComputerBlock extends HorizontalDirectionalBlock implements E
final ItemStack computer = getComputerWithFlash();
final CompoundTag itemsTag = NBTUtils.getOrCreateChildTag(computer.getOrCreateTag(), BLOCK_ENTITY_TAG_NAME_IN_ITEM, ITEMS_TAG_NAME);
itemsTag.put(key(DeviceTypes.MEMORY), makeInventoryTag(
itemsTag.put(DeviceTypes.MEMORY.getName().toString(), makeInventoryTag(
new ItemStack(Items.MEMORY_LARGE.get()),
new ItemStack(Items.MEMORY_LARGE.get()),
new ItemStack(Items.MEMORY_LARGE.get()),
new ItemStack(Items.MEMORY_LARGE.get())
));
itemsTag.put(key(DeviceTypes.HARD_DRIVE), makeInventoryTag(
itemsTag.put(DeviceTypes.HARD_DRIVE.getName().toString(), makeInventoryTag(
new ItemStack(Items.HARD_DRIVE_CUSTOM.get())
));
itemsTag.put(key(DeviceTypes.CARD), makeInventoryTag(
itemsTag.put(DeviceTypes.CARD.getName().toString(), makeInventoryTag(
new ItemStack(Items.NETWORK_INTERFACE_CARD.get())
));

View File

@@ -23,7 +23,7 @@ public final class CreativeEnergyBlock extends Block implements EntityBlock {
.of(Material.METAL)
.sound(SoundType.METAL)
.strength(-1, 3600000)
.noDrops());
.noLootTable());
}
///////////////////////////////////////////////////////////////////

View File

@@ -2,17 +2,19 @@
package li.cil.oc2.common.blockentity;
import li.cil.oc2.api.API;
import li.cil.oc2.common.block.Blocks;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.entity.BlockEntityType;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public final class BlockEntities {
private static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = RegistryUtils.getInitializerFor(ForgeRegistries.BLOCK_ENTITIES);
private static final DeferredRegister<BlockEntityType<?>> BLOCK_ENTITIES = DeferredRegister.create(ForgeRegistries.BLOCK_ENTITY_TYPES, API.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -30,6 +32,7 @@ public final class BlockEntities {
///////////////////////////////////////////////////////////////////
public static void initialize() {
BLOCK_ENTITIES.register(FMLJavaModLoadingContext.get().getModEventBus());
}
///////////////////////////////////////////////////////////////////

View File

@@ -7,6 +7,7 @@ import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider;
import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery;
import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import li.cil.oc2.api.util.Invalidatable;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.provider.Providers;

View File

@@ -3,6 +3,7 @@
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import li.cil.oc2.common.util.NBTTagIds;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.ListTag;

View File

@@ -90,10 +90,8 @@ public abstract class AbstractItemDeviceBusElement extends AbstractGroupingDevic
return;
}
final ResourceLocation registryName = query.getItemStack().getItem().getRegistryName();
if (registryName != null) {
final String itemName = registryName.toString();
entries.add(new ItemEntry(new ItemDeviceInfo(null, new TypeNameRPCDevice(itemName), 0)));
if (query.getItemStack().getDisplayName() != null) {
entries.add(new ItemEntry(new ItemDeviceInfo(null, new TypeNameRPCDevice(query.getItemStack().getDisplayName().toString()), 0)));
}
}

View File

@@ -10,6 +10,7 @@ import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryBuilder;
@@ -19,15 +20,18 @@ import java.util.function.Supplier;
import static li.cil.oc2.common.util.TranslationUtils.text;
public final class DeviceTypes {
private static final DeferredRegister<DeviceType> DEVICE_TYPES = RegistryUtils.getInitializerFor(DeviceType.REGISTRY);
private static final DeferredRegister<DeviceType> DEVICE_TYPES = DeferredRegister.create(new ResourceLocation("device_type"), API.MOD_ID);
///////////////////////////////////////////////////////////////////
public static final Supplier<IForgeRegistry<DeviceType>> DEVICE_TYPE_REGISTRY = DEVICE_TYPES.makeRegistry(DeviceType.class, RegistryBuilder::new);
public static final Supplier<IForgeRegistry<DeviceType>> DEVICE_TYPE_REGISTRY = DEVICE_TYPES.makeRegistry(RegistryBuilder::new);
///////////////////////////////////////////////////////////////////
public static void initialize() {
DEVICE_TYPES.register(FMLJavaModLoadingContext.get().getModEventBus());
register(ItemTags.DEVICES_MEMORY);
register(ItemTags.DEVICES_HARD_DRIVE);
register(ItemTags.DEVICES_FLASH_MEMORY);

View File

@@ -2,10 +2,12 @@
package li.cil.oc2.common.bus.device.data;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.device.data.BlockDeviceData;
import li.cil.oc2.api.util.Registries;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryBuilder;
@@ -16,11 +18,11 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
public final class BlockDeviceDataRegistry {
private static final DeferredRegister<BlockDeviceData> INITIALIZER = RegistryUtils.getInitializerFor(Registries.BLOCK_DEVICE_DATA);
private static final DeferredRegister<BlockDeviceData> INITIALIZER = DeferredRegister.create(new ResourceLocation("block_device_data"), API.MOD_ID);
///////////////////////////////////////////////////////////////////
private static final Supplier<IForgeRegistry<BlockDeviceData>> REGISTRY = INITIALIZER.makeRegistry(BlockDeviceData.class, RegistryBuilder::new);
private static final Supplier<IForgeRegistry<BlockDeviceData>> REGISTRY = INITIALIZER.makeRegistry(RegistryBuilder::new);
///////////////////////////////////////////////////////////////////
@@ -29,11 +31,12 @@ public final class BlockDeviceDataRegistry {
///////////////////////////////////////////////////////////////////
public static void initialize() {
INITIALIZER.register(FMLJavaModLoadingContext.get().getModEventBus());
}
@Nullable
public static ResourceLocation getKey(final BlockDeviceData data) {
return data.getRegistryName();
return INITIALIZER.getRegistryName();
}
@Nullable

View File

@@ -2,19 +2,20 @@
package li.cil.oc2.common.bus.device.data;
import com.mojang.serialization.Codec;
import li.cil.oc2.api.bus.device.data.BlockDeviceData;
import li.cil.sedna.api.device.BlockDevice;
import li.cil.sedna.buildroot.Buildroot;
import li.cil.sedna.device.block.ByteBufferBlockDevice;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.registries.ForgeRegistryEntry;
import net.minecraftforge.registries.*;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.util.*;
public final class BuildrootBlockDeviceData extends ForgeRegistryEntry<BlockDeviceData> implements BlockDeviceData {
public final class BuildrootBlockDeviceData implements BlockDeviceData {
private static final Logger LOGGER = LogManager.getLogger();
///////////////////////////////////////////////////////////////////
@@ -34,13 +35,11 @@ public final class BuildrootBlockDeviceData extends ForgeRegistryEntry<BlockDevi
///////////////////////////////////////////////////////////////////
@Override
public BlockDevice getBlockDevice() {
return INSTANCE;
}
@Override
public Component getDisplayName() {
return new TextComponent("Sedna Linux");
return Component.literal("Sedna Linux");
}
}

View File

@@ -7,12 +7,10 @@ import li.cil.sedna.api.memory.MemoryMap;
import li.cil.sedna.buildroot.Buildroot;
import li.cil.sedna.memory.MemoryMaps;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraftforge.registries.ForgeRegistryEntry;
import java.io.IOException;
public final class BuildrootFirmware extends ForgeRegistryEntry<Firmware> implements Firmware {
public final class BuildrootFirmware implements Firmware {
@Override
public boolean run(final MemoryMap memory, final long startAddress) {
try {
@@ -26,6 +24,6 @@ public final class BuildrootFirmware extends ForgeRegistryEntry<Firmware> implem
@Override
public Component getDisplayName() {
return new TextComponent("Sedna Linux");
return Component.literal("Sedna Linux");
}
}

View File

@@ -79,7 +79,7 @@ public final class FileSystems {
LOGGER.info("Searching for datapack filesystems...");
final Collection<ResourceLocation> fileSystemDescriptorLocations = resourceManager
.listResources("file_systems", s -> s.endsWith(".json"));
.listResources("file_systems", s -> s.toString().endsWith(".json")).keySet();
final ArrayList<ZipStreamFileSystem> fileSystems = new ArrayList<>();
final Object2IntArrayMap<ZipStreamFileSystem> fileSystemOrder = new Object2IntArrayMap<>();
@@ -87,15 +87,15 @@ public final class FileSystems {
for (final ResourceLocation fileSystemDescriptorLocation : fileSystemDescriptorLocations) {
LOGGER.info("Found [{}]", fileSystemDescriptorLocation);
try {
final Resource fileSystemDescriptor = resourceManager.getResource(fileSystemDescriptorLocation);
final JsonObject json = JsonParser.parseReader(new InputStreamReader(fileSystemDescriptor.getInputStream())).getAsJsonObject();
final Resource fileSystemDescriptor = resourceManager.getResource(fileSystemDescriptorLocation).get();
final JsonObject json = JsonParser.parseReader(new InputStreamReader(fileSystemDescriptor.open())).getAsJsonObject();
final String type = json.getAsJsonPrimitive("type").getAsString();
switch (type) {
case "layer" -> {
final ResourceLocation location = new ResourceLocation(json.getAsJsonPrimitive("location").getAsString());
final ZipStreamFileSystem fileSystem;
try (final InputStream stream = resourceManager.getResource(location).getInputStream()) {
try (final InputStream stream = resourceManager.getResource(location).get().open()) {
fileSystem = new ZipStreamFileSystem(stream);
}

View File

@@ -2,10 +2,12 @@
package li.cil.oc2.common.bus.device.data;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.device.data.Firmware;
import li.cil.oc2.api.util.Registries;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryBuilder;
@@ -16,11 +18,11 @@ import java.util.function.Supplier;
import java.util.stream.Stream;
public final class FirmwareRegistry {
private static final DeferredRegister<Firmware> INITIALIZER = RegistryUtils.getInitializerFor(Registries.FIRMWARE);
private static final DeferredRegister<Firmware> INITIALIZER = DeferredRegister.create(new ResourceLocation("firmware"), API.MOD_ID);
///////////////////////////////////////////////////////////////////
private static final Supplier<IForgeRegistry<Firmware>> REGISTRY = INITIALIZER.makeRegistry(Firmware.class, RegistryBuilder::new);
private static final Supplier<IForgeRegistry<Firmware>> REGISTRY = INITIALIZER.makeRegistry(RegistryBuilder::new);
///////////////////////////////////////////////////////////////////
@@ -29,11 +31,12 @@ public final class FirmwareRegistry {
///////////////////////////////////////////////////////////////////
public static void initialize() {
INITIALIZER.register(FMLJavaModLoadingContext.get().getModEventBus());
}
@Nullable
public static ResourceLocation getKey(final Firmware firmware) {
return firmware.getRegistryName();
return INITIALIZER.getRegistryName();
}
@Nullable

View File

@@ -6,43 +6,23 @@ 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;
public final class ResourceBlockDeviceData implements BlockDeviceData, AutoCloseable {
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();
final InputStream stream = resourceManager.getResource(location).get().open();
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();
@@ -55,6 +35,6 @@ public final class ResourceBlockDeviceData implements IForgeRegistryEntry<BlockD
@Override
public Component getDisplayName() {
return new TextComponent(name);
return Component.literal(name);
}
}

View File

@@ -2,10 +2,17 @@
package li.cil.oc2.common.bus.device.provider;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider;
import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import li.cil.oc2.api.util.Registries;
import li.cil.oc2.common.bus.device.provider.block.BlockEntityCapabilityDeviceProvider;
import li.cil.oc2.common.bus.device.provider.item.*;
import li.cil.oc2.common.bus.device.rpc.block.*;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.RegistryBuilder;
@@ -13,18 +20,46 @@ import net.minecraftforge.registries.RegistryBuilder;
import java.util.function.Supplier;
public final class ProviderRegistry {
private static final DeferredRegister<BlockDeviceProvider> BLOCK_DEVICE_PROVIDERS = RegistryUtils.getInitializerFor(Registries.BLOCK_DEVICE_PROVIDER);
public static final Supplier<IForgeRegistry<BlockDeviceProvider>> BLOCK_DEVICE_PROVIDER_REGISTRY = BLOCK_DEVICE_PROVIDERS.makeRegistry(BlockDeviceProvider.class, RegistryBuilder::new);
private static final DeferredRegister<BlockDeviceProvider> BLOCK_DEVICE_PROVIDERS = DeferredRegister.create(new ResourceLocation("block_device_provider"), API.MOD_ID);
public static final Supplier<IForgeRegistry<BlockDeviceProvider>> BLOCK_DEVICE_PROVIDER_REGISTRY = BLOCK_DEVICE_PROVIDERS.makeRegistry(RegistryBuilder::new);
///////////////////////////////////////////////////////////////////
private static final DeferredRegister<ItemDeviceProvider> ITEM_DEVICE_PROVIDERS = RegistryUtils.getInitializerFor(Registries.ITEM_DEVICE_PROVIDER);
public static final Supplier<IForgeRegistry<ItemDeviceProvider>> ITEM_DEVICE_PROVIDER_REGISTRY = ITEM_DEVICE_PROVIDERS.makeRegistry(ItemDeviceProvider.class, RegistryBuilder::new);
private static final DeferredRegister<ItemDeviceProvider> ITEM_DEVICE_PROVIDERS = DeferredRegister.create(new ResourceLocation("item_device_provider"), API.MOD_ID);
public static final Supplier<IForgeRegistry<ItemDeviceProvider>> ITEM_DEVICE_PROVIDER_REGISTRY = ITEM_DEVICE_PROVIDERS.makeRegistry(RegistryBuilder::new);
///////////////////////////////////////////////////////////////////
public static void initialize() {
Providers.registerBlockDeviceProviders(BLOCK_DEVICE_PROVIDERS::register);
Providers.registerItemDeviceProviders(ITEM_DEVICE_PROVIDERS::register);
ITEM_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus());
BLOCK_DEVICE_PROVIDERS.register(FMLJavaModLoadingContext.get().getModEventBus());
ITEM_DEVICE_PROVIDERS.register("memory", MemoryItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("hard_drive", HardDriveItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("hard_drive_custom", HardDriveWithExternalDataItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("flash_memory", FlashMemoryItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("flash_memory_custom", FlashMemoryWithExternalDataItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("redstone_interface_card", RedstoneInterfaceCardItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("network_interface_card", NetworkInterfaceCardItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("network_tunnel_card", NetworkTunnelCardItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("file_import_export_card", FileImportExportCardItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("sound_card", SoundCardItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("inventory_operations_module", InventoryOperationsModuleDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("block_operations_module", BlockOperationsModuleDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("network_tunnel_module", NetworkTunnelModuleItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("item_stack/capability", ItemStackCapabilityDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("energy_storage", EnergyStorageItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("fluid_handler", FluidHandlerItemDeviceProvider::new);
ITEM_DEVICE_PROVIDERS.register("item_handler", ItemHandlerItemDeviceProvider::new);
BLOCK_DEVICE_PROVIDERS.register("block", BlockStateObjectDeviceProvider::new);
BLOCK_DEVICE_PROVIDERS.register("block_entity", BlockEntityObjectDeviceProvider::new);
BLOCK_DEVICE_PROVIDERS.register("block_entity/capability", BlockEntityCapabilityDeviceProvider::new);
BLOCK_DEVICE_PROVIDERS.register("energy_storage", EnergyStorageBlockDeviceProvider::new);
BLOCK_DEVICE_PROVIDERS.register("fluid_handler", FluidHandlerBlockDeviceProvider::new);
BLOCK_DEVICE_PROVIDERS.register("item_handler", ItemHandlerBlockDeviceProvider::new);
}
}

View File

@@ -22,34 +22,10 @@ public final class Providers {
}
public static void registerBlockDeviceProviders(final BiConsumer<String, Supplier<BlockDeviceProvider>> registry) {
registry.accept("block", BlockStateObjectDeviceProvider::new);
registry.accept("block_entity", BlockEntityObjectDeviceProvider::new);
registry.accept("block_entity/capability", BlockEntityCapabilityDeviceProvider::new);
registry.accept("energy_storage", EnergyStorageBlockDeviceProvider::new);
registry.accept("fluid_handler", FluidHandlerBlockDeviceProvider::new);
registry.accept("item_handler", ItemHandlerBlockDeviceProvider::new);
}
public static void registerItemDeviceProviders(final BiConsumer<String, Supplier<ItemDeviceProvider>> registry) {
registry.accept("memory", MemoryItemDeviceProvider::new);
registry.accept("hard_drive", HardDriveItemDeviceProvider::new);
registry.accept("hard_drive_custom", HardDriveWithExternalDataItemDeviceProvider::new);
registry.accept("flash_memory", FlashMemoryItemDeviceProvider::new);
registry.accept("flash_memory_custom", FlashMemoryWithExternalDataItemDeviceProvider::new);
registry.accept("redstone_interface_card", RedstoneInterfaceCardItemDeviceProvider::new);
registry.accept("network_interface_card", NetworkInterfaceCardItemDeviceProvider::new);
registry.accept("network_tunnel_card", NetworkTunnelCardItemDeviceProvider::new);
registry.accept("file_import_export_card", FileImportExportCardItemDeviceProvider::new);
registry.accept("sound_card", SoundCardItemDeviceProvider::new);
registry.accept("inventory_operations_module", InventoryOperationsModuleDeviceProvider::new);
registry.accept("block_operations_module", BlockOperationsModuleDeviceProvider::new);
registry.accept("network_tunnel_module", NetworkTunnelModuleItemDeviceProvider::new);
registry.accept("item_stack/capability", ItemStackCapabilityDeviceProvider::new);
registry.accept("energy_storage", EnergyStorageItemDeviceProvider::new);
registry.accept("fluid_handler", FluidHandlerItemDeviceProvider::new);
registry.accept("item_handler", ItemHandlerItemDeviceProvider::new);
}
}

View File

@@ -3,6 +3,5 @@
package li.cil.oc2.common.bus.device.provider.util;
import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider;
import net.minecraftforge.registries.ForgeRegistryEntry;
public abstract class AbstractBlockDeviceProvider extends ForgeRegistryEntry<BlockDeviceProvider> implements BlockDeviceProvider { }
public abstract class AbstractBlockDeviceProvider implements BlockDeviceProvider { }

View File

@@ -7,13 +7,12 @@ import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.ForgeRegistryEntry;
import net.minecraftforge.registries.RegistryObject;
import java.util.Optional;
import java.util.function.Predicate;
public abstract class AbstractItemDeviceProvider extends ForgeRegistryEntry<ItemDeviceProvider> implements ItemDeviceProvider {
public abstract class AbstractItemDeviceProvider implements ItemDeviceProvider {
private final Predicate<Item> predicate;
///////////////////////////////////////////////////////////////////

View File

@@ -8,6 +8,7 @@ import net.minecraft.nbt.Tag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringUtil;
import net.minecraft.world.item.ItemStack;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.Nullable;
import java.util.Objects;
@@ -26,7 +27,7 @@ public final class RPCItemStackTagFilter {
return null;
}
if (item != null && !Objects.equals(stack.getItem().getRegistryName(), item)) {
if (item != null && !Objects.equals(ForgeRegistries.ITEMS.getKey(stack.getItem()), item)) {
return null;
}

View File

@@ -3,12 +3,12 @@
package li.cil.oc2.common.bus.device.util;
import li.cil.oc2.api.bus.device.Device;
import net.minecraftforge.registries.IForgeRegistryEntry;
import net.minecraftforge.registries.IForgeRegistry;
import javax.annotation.Nullable;
import java.util.Objects;
public abstract class AbstractDeviceInfo<TProvider extends IForgeRegistryEntry<TProvider>, TDevice extends Device> {
public abstract class AbstractDeviceInfo<TProvider, TDevice extends Device> {
@Nullable public final TProvider provider;
public final TDevice device;

View File

@@ -7,9 +7,8 @@ import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.tags.TagKey;
import net.minecraft.world.item.Item;
import net.minecraftforge.registries.ForgeRegistryEntry;
public final class DeviceTypeImpl extends ForgeRegistryEntry<DeviceType> implements DeviceType {
public final class DeviceTypeImpl implements DeviceType {
private final TagKey<Item> tag;
private final ResourceLocation icon;
private final Component name;

View File

@@ -18,7 +18,7 @@ import li.cil.sedna.api.memory.MemoryMap;
import li.cil.sedna.device.flash.FlashMemoryDevice;
import li.cil.sedna.memory.MemoryMaps;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
import java.nio.ByteBuffer;
@@ -133,7 +133,7 @@ public final class ByteBufferFlashStorageDevice extends IdentityProxy<ItemStack>
try {
MemoryMaps.store(memoryMap, startAddress, data);
} catch (final MemoryAccessException e) {
throw new VMInitializationException(new TranslatableComponent(Constants.COMPUTER_ERROR_INSUFFICIENT_MEMORY));
throw new VMInitializationException(Component.translatable(Constants.COMPUTER_ERROR_INSUFFICIENT_MEMORY));
}
}
}

View File

@@ -14,7 +14,7 @@ import li.cil.oc2.api.bus.device.vm.event.VMInitializingEvent;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.util.IdentityProxy;
import li.cil.sedna.api.memory.MemoryMap;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.ItemStack;
public final class FirmwareFlashStorageDevice extends IdentityProxy<ItemStack> implements VMDevice, ItemDevice, FirmwareLoader {
@@ -57,7 +57,7 @@ public final class FirmwareFlashStorageDevice extends IdentityProxy<ItemStack> i
private void copyDataToMemory(final long address) {
if (!firmware.run(memoryMap, address)) {
throw new VMInitializationException(new TranslatableComponent(Constants.COMPUTER_ERROR_INSUFFICIENT_MEMORY));
throw new VMInitializationException(Component.translatable(Constants.COMPUTER_ERROR_INSUFFICIENT_MEMORY));
}
}
}

View File

@@ -9,7 +9,6 @@ import li.cil.oc2.common.vm.VMItemStackHandlers;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
@@ -21,10 +20,10 @@ import net.minecraftforge.network.NetworkHooks;
public final class ComputerInventoryContainer extends AbstractComputerContainer {
public static void createServer(final ComputerBlockEntity computer, final IEnergyStorage energy, final CommonDeviceBusController busController, final ServerPlayer player) {
NetworkHooks.openGui(player, new MenuProvider() {
NetworkHooks.openScreen(player, new MenuProvider() {
@Override
public Component getDisplayName() {
return new TranslatableComponent(computer.getBlockState().getBlock().getDescriptionId());
return Component.translatable(computer.getBlockState().getBlock().getDescriptionId());
}
@Override

View File

@@ -7,7 +7,6 @@ import li.cil.oc2.common.bus.CommonDeviceBusController;
import net.minecraft.core.BlockPos;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.MenuProvider;
import net.minecraft.world.entity.player.Inventory;
@@ -19,10 +18,10 @@ import net.minecraftforge.network.NetworkHooks;
public final class ComputerTerminalContainer extends AbstractComputerContainer {
public static void createServer(final ComputerBlockEntity computer, final IEnergyStorage energy, final CommonDeviceBusController busController, final ServerPlayer player) {
NetworkHooks.openGui(player, new MenuProvider() {
NetworkHooks.openScreen(player, new MenuProvider() {
@Override
public Component getDisplayName() {
return new TranslatableComponent(computer.getBlockState().getBlock().getDescriptionId());
return Component.translatable(computer.getBlockState().getBlock().getDescriptionId());
}
@Override

View File

@@ -2,15 +2,17 @@
package li.cil.oc2.common.container;
import li.cil.oc2.api.API;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.world.inventory.MenuType;
import net.minecraftforge.common.extensions.IForgeMenuType;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public final class Containers {
private static final DeferredRegister<MenuType<?>> CONTAINERS = RegistryUtils.getInitializerFor(ForgeRegistries.CONTAINERS);
private static final DeferredRegister<MenuType<?>> CONTAINERS = DeferredRegister.create(ForgeRegistries.MENU_TYPES, API.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -23,5 +25,6 @@ public final class Containers {
///////////////////////////////////////////////////////////////////
public static void initialize() {
CONTAINERS.register(FMLJavaModLoadingContext.get().getModEventBus());
}
}

View File

@@ -22,7 +22,7 @@ import java.util.UUID;
public final class NetworkTunnelContainer extends AbstractContainer {
public static void createServer(final ServerPlayer player, final InteractionHand hand) {
NetworkHooks.openGui(player, new MenuProvider() {
NetworkHooks.openScreen(player, new MenuProvider() {
@Override
public Component getDisplayName() {
return player.getItemInHand(hand).getItem().getDescription();

View File

@@ -20,7 +20,7 @@ import net.minecraftforge.network.NetworkHooks;
public final class RobotInventoryContainer extends AbstractRobotContainer {
public static void createServer(final Robot robot, final FixedEnergyStorage energy, final CommonDeviceBusController busController, final ServerPlayer player) {
NetworkHooks.openGui(player, new MenuProvider() {
NetworkHooks.openScreen(player, new MenuProvider() {
@Override
public Component getDisplayName() {
return robot.getName();

View File

@@ -19,7 +19,7 @@ import net.minecraftforge.network.NetworkHooks;
public final class RobotTerminalContainer extends AbstractRobotContainer {
public static void createServer(final Robot robot, final FixedEnergyStorage energy, final CommonDeviceBusController busController, final ServerPlayer player) {
NetworkHooks.openGui(player, new MenuProvider() {
NetworkHooks.openScreen(player, new MenuProvider() {
@Override
public Component getDisplayName() {
return robot.getName();

View File

@@ -2,10 +2,12 @@
package li.cil.oc2.common.entity;
import li.cil.oc2.api.API;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.MobCategory;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
@@ -13,7 +15,7 @@ import net.minecraftforge.registries.RegistryObject;
import java.util.function.Function;
public final class Entities {
private static final DeferredRegister<EntityType<?>> ENTITIES = RegistryUtils.getInitializerFor(ForgeRegistries.ENTITIES);
private static final DeferredRegister<EntityType<?>> ENTITIES = DeferredRegister.create(ForgeRegistries.ENTITY_TYPES, API.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -22,6 +24,7 @@ public final class Entities {
///////////////////////////////////////////////////////////////////
public static void initialize() {
ENTITIES.register(FMLJavaModLoadingContext.get().getModEventBus());
}
///////////////////////////////////////////////////////////////////

View File

@@ -43,6 +43,7 @@ import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
@@ -69,8 +70,8 @@ import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.items.ItemStackHandler;
import net.minecraftforge.network.NetworkHooks;
@@ -108,7 +109,7 @@ public final class Robot extends Entity implements li.cil.oc2.api.capabilities.R
///////////////////////////////////////////////////////////////////
private final Consumer<ChunkEvent.Unload> chunkUnloadListener = this::handleChunkUnload;
private final Consumer<WorldEvent.Unload> worldUnloadListener = this::handleWorldUnload;
private final Consumer<LevelEvent.Unload> worldUnloadListener = this::handleWorldUnload;
private final BlockPos.MutableBlockPos mutablePosition = new BlockPos.MutableBlockPos();
private final AnimationState animationState = new AnimationState();
@@ -471,7 +472,7 @@ public final class Robot extends Entity implements li.cil.oc2.api.capabilities.R
}
private void handleChunkUnload(final ChunkEvent.Unload event) {
if (event.getWorld() != level) {
if (event.getLevel() != level) {
return;
}
@@ -485,8 +486,8 @@ public final class Robot extends Entity implements li.cil.oc2.api.capabilities.R
virtualMachine.dispose();
}
private void handleWorldUnload(final WorldEvent.Unload event) {
if (event.getWorld() != level) {
private void handleWorldUnload(final LevelEvent.Unload event) {
if (event.getLevel() != level) {
return;
}
@@ -541,7 +542,7 @@ public final class Robot extends Entity implements li.cil.oc2.api.capabilities.R
public float topRenderRotationSpeed;
public float topRenderHover = -(hashCode() & 0xFFFF); // init to "random" to avoid synchronous hovering
public void update(final float deltaTime, final Random random) {
public void update(final float deltaTime, final RandomSource random) {
if (getVirtualMachine().isRunning() || actionProcessor.hasQueuedActions()) {
topRenderHover = topRenderHover + deltaTime * HOVER_ANIMATION_SPEED;
final float topOffsetY = Mth.sin(topRenderHover) / 32f;

View File

@@ -7,7 +7,6 @@ import li.cil.oc2.common.bus.device.data.BlockDeviceDataRegistry;
import li.cil.oc2.common.util.ItemStackUtils;
import net.minecraft.ResourceLocationException;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringUtil;
import net.minecraft.world.item.ItemStack;
@@ -76,7 +75,7 @@ public abstract class AbstractBlockDeviceItem extends ModItem {
public Component getName(final ItemStack stack) {
final BlockDeviceData data = getData(stack);
if (data != null) {
return new TextComponent("")
return Component.literal("")
.append(super.getName(stack))
.append(" (")
.append(data.getDisplayName())

View File

@@ -7,7 +7,6 @@ import li.cil.oc2.common.util.NBTTagIds;
import li.cil.oc2.common.util.TextFormatUtils;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.world.item.ItemStack;
public abstract class AbstractStorageItem extends ModItem {
@@ -51,7 +50,7 @@ public abstract class AbstractStorageItem extends ModItem {
@Override
public Component getName(final ItemStack stack) {
final int capacity = getCapacity(stack);
return new TextComponent("")
return Component.literal("")
.append(super.getName(stack))
.append(" (")
.append(TextFormatUtils.formatSize(capacity))

View File

@@ -70,7 +70,7 @@ public final class BusInterfaceItem extends ModBlockItem {
@Override
public void fillItemCategory(final CreativeModeTab tab, final NonNullList<ItemStack> items) {
if (allowdedIn(tab)) {
if (this.allowedIn(tab)) {
items.add(new ItemStack(this));
}
}

View File

@@ -8,7 +8,6 @@ import li.cil.oc2.common.util.ItemStackUtils;
import net.minecraft.ResourceLocationException;
import net.minecraft.Util;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.StringUtil;
import net.minecraft.world.item.ItemStack;
@@ -74,7 +73,7 @@ public final class FlashMemoryWithExternalDataItem extends ModItem {
public Component getName(final ItemStack stack) {
final Firmware firmware = getFirmware(stack);
if (firmware != null) {
return new TextComponent("")
return Component.literal("")
.append(super.getName(stack))
.append(" (")
.append(firmware.getDisplayName())

View File

@@ -1,13 +1,12 @@
/* SPDX-License-Identifier: MIT */
package li.cil.oc2.common.item;
import li.cil.oc2.api.API;
import net.minecraft.Util;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.registries.MissingMappingsEvent;
import java.util.HashMap;
import java.util.Map;
@@ -26,15 +25,13 @@ public final class ItemRenameHandler {
///////////////////////////////////////////////////////////////////
public static void initialize() {
MinecraftForge.EVENT_BUS.addGenericListener(Item.class, ItemRenameHandler::handleMissingMappings);
}
///////////////////////////////////////////////////////////////////
private static void handleMissingMappings(final RegistryEvent.MissingMappings<Item> event) {
for (final RegistryEvent.MissingMappings.Mapping<Item> mapping : event.getAllMappings()) {
final ResourceLocation key = mapping.key;
@SubscribeEvent
private static void handleMissingMappings(final MissingMappingsEvent event) {
for (final MissingMappingsEvent.Mapping mapping : event.getAllMappings(ResourceKey.createRegistryKey(event.getKey().location()))) {
final ResourceLocation key = mapping.getKey();
if (key == null || !Objects.equals(key.getNamespace(), API.MOD_ID)) {
continue;
}

View File

@@ -2,6 +2,7 @@
package li.cil.oc2.common.item;
import li.cil.oc2.api.API;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.block.Blocks;
import li.cil.oc2.common.bus.device.data.BlockDeviceDataRegistry;
@@ -10,6 +11,7 @@ import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.world.item.DyeColor;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
@@ -18,7 +20,7 @@ import java.util.function.Function;
import java.util.function.Supplier;
public final class Items {
private static final DeferredRegister<Item> ITEMS = RegistryUtils.getInitializerFor(ForgeRegistries.ITEMS);
private static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, API.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -82,6 +84,7 @@ public final class Items {
///////////////////////////////////////////////////////////////////
public static void initialize() {
ITEMS.register(FMLJavaModLoadingContext.get().getModEventBus());
}
///////////////////////////////////////////////////////////////////

View File

@@ -11,6 +11,7 @@ import li.cil.oc2.client.manual.ModManualScreenStyle;
import li.cil.oc2.client.manual.ModManualStyle;
import li.cil.oc2.common.util.TooltipUtils;
import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.level.Level;
@@ -22,7 +23,7 @@ import java.util.List;
public final class ManualItem extends AbstractManualItem {
public ManualItem() {
super(new Properties().tab(ItemGroup.COMMON));
super(new Item.Properties().tab(ItemGroup.COMMON));
}
///////////////////////////////////////////////////////////////////

View File

@@ -9,7 +9,7 @@ import li.cil.oc2.common.blockentity.NetworkConnectorBlockEntity.ConnectionResul
import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtUtils;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
@@ -70,7 +70,7 @@ public final class NetworkCableItem extends ModItem {
if (currentConnector.canConnectMore()) {
persistentData.put(LINK_START_TAG_NAME, NbtUtils.writeBlockPos(currentPos));
} else {
player.displayClientMessage(new TranslatableComponent(Constants.CONNECTOR_ERROR_FULL), true);
player.displayClientMessage(Component.translatable(Constants.CONNECTOR_ERROR_FULL), true);
}
} else {
final BlockEntity startBlockEntity = level.getBlockEntity(startPos);
@@ -92,15 +92,15 @@ public final class NetworkCableItem extends ModItem {
break;
case FAILURE_FULL:
persistentData.put(LINK_START_TAG_NAME, NbtUtils.writeBlockPos(startPos));
player.displayClientMessage(new TranslatableComponent(Constants.CONNECTOR_ERROR_FULL), true);
player.displayClientMessage(Component.translatable(Constants.CONNECTOR_ERROR_FULL), true);
break;
case FAILURE_TOO_FAR:
persistentData.put(LINK_START_TAG_NAME, NbtUtils.writeBlockPos(startPos));
player.displayClientMessage(new TranslatableComponent(Constants.CONNECTOR_ERROR_TOO_FAR), true);
player.displayClientMessage(Component.translatable(Constants.CONNECTOR_ERROR_TOO_FAR), true);
break;
case FAILURE_OBSTRUCTED:
persistentData.put(LINK_START_TAG_NAME, NbtUtils.writeBlockPos(startPos));
player.displayClientMessage(new TranslatableComponent(Constants.CONNECTOR_ERROR_OBSTRUCTED), true);
player.displayClientMessage(Component.translatable(Constants.CONNECTOR_ERROR_OBSTRUCTED), true);
break;
}
}

View File

@@ -9,7 +9,7 @@ import net.minecraft.ChatFormatting;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.contents.TranslatableContents;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.util.StringUtil;
import net.minecraft.world.InteractionHand;
@@ -59,7 +59,7 @@ public final class NetworkTunnelItem extends ModItem {
getTunnelId(stack).ifPresent(id -> {
final String idString = StringUtil.truncateStringIfNecessary(id.toString(), 8 + 3, true);
final MutableComponent idComponent = TextFormatUtils.withFormat(idString, ChatFormatting.GREEN);
tooltip.add(new TranslatableComponent(TUNNEL_ID_TEXT, idComponent).withStyle(ChatFormatting.GRAY));
tooltip.add(Component.translatable(TUNNEL_ID_TEXT, idComponent).withStyle(ChatFormatting.GRAY));
});
}

View File

@@ -30,7 +30,7 @@ import net.minecraft.world.item.context.UseOnContext;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.phys.Vec3;
import net.minecraftforge.client.IItemRenderProperties;
import net.minecraftforge.client.extensions.common.IClientItemExtensions;
import net.minecraftforge.common.capabilities.ICapabilityProvider;
import javax.annotation.Nullable;
@@ -42,12 +42,6 @@ import static li.cil.oc2.common.util.NBTUtils.makeInventoryTag;
import static li.cil.oc2.common.util.RegistryUtils.key;
public final class RobotItem extends ModItem {
@Override
public void fillItemCategory(final CreativeModeTab tab, final NonNullList<ItemStack> items) {
if (allowdedIn(tab)) {
items.add(getRobotWithFlash());
}
}
@Override
public void appendHoverText(final ItemStack stack, @Nullable final Level level, final List<Component> tooltip, final TooltipFlag flag) {
@@ -116,18 +110,6 @@ public final class RobotItem extends ModItem {
///////////////////////////////////////////////////////////////////
@Override
public void initializeClient(final Consumer<IItemRenderProperties> consumer) {
consumer.accept(new IItemRenderProperties() {
@Override
public BlockEntityWithoutLevelRenderer getItemStackRenderer() {
return new RobotWithoutLevelRenderer(Minecraft.getInstance().getBlockEntityRenderDispatcher(), Minecraft.getInstance().getEntityModels());
}
});
}
///////////////////////////////////////////////////////////////////
private ItemStack getRobotWithFlash() {
final ItemStack robot = new ItemStack(this);

View File

@@ -2,14 +2,16 @@
package li.cil.oc2.common.item.crafting;
import li.cil.oc2.api.API;
import li.cil.oc2.common.util.RegistryUtils;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public final class RecipeSerializers {
private static final DeferredRegister<RecipeSerializer<?>> RECIPE_SERIALIZERS = RegistryUtils.getInitializerFor(ForgeRegistries.RECIPE_SERIALIZERS);
private static final DeferredRegister<RecipeSerializer<?>> RECIPE_SERIALIZERS = DeferredRegister.create(ForgeRegistries.RECIPE_SERIALIZERS, API.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -18,5 +20,6 @@ public final class RecipeSerializers {
///////////////////////////////////////////////////////////////////
public static void initialize() {
RECIPE_SERIALIZERS.register(FMLJavaModLoadingContext.get().getModEventBus());
}
}

View File

@@ -11,7 +11,7 @@ import net.minecraft.world.inventory.CraftingContainer;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.crafting.RecipeSerializer;
import net.minecraft.world.item.crafting.ShapelessRecipe;
import net.minecraftforge.registries.ForgeRegistryEntry;
import net.minecraftforge.common.capabilities.Capability;
import org.jetbrains.annotations.Nullable;
public final class WrenchRecipe extends ShapelessRecipe {
@@ -25,8 +25,8 @@ public final class WrenchRecipe extends ShapelessRecipe {
for (int slot = 0; slot < inventory.getContainerSize(); slot++) {
final ItemStack stack = inventory.getItem(slot);
if (stack.hasContainerItem()) {
result.set(slot, stack.getContainerItem());
if (stack.hasCraftingRemainingItem()) {
result.set(slot, stack.getCraftingRemainingItem());
} else if (Wrenches.isWrench(stack)) {
final ItemStack copy = stack.copy();
copy.setCount(1);
@@ -42,7 +42,7 @@ public final class WrenchRecipe extends ShapelessRecipe {
return Serializer.INSTANCE;
}
public static final class Serializer extends ForgeRegistryEntry<RecipeSerializer<?>> implements RecipeSerializer<WrenchRecipe> {
public static final class Serializer implements RecipeSerializer<WrenchRecipe> {
public static final Serializer INSTANCE = new Serializer();
@Override

View File

@@ -8,7 +8,7 @@ import li.cil.oc2.common.network.Network;
import net.minecraft.client.Minecraft;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.chat.TextColor;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.MutableComponent;
import net.minecraftforge.network.NetworkEvent;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@@ -21,7 +21,7 @@ import static li.cil.oc2.common.util.TranslationUtils.text;
public final class RequestImportedFileMessage extends AbstractMessage {
private static final Logger LOGGER = LogManager.getLogger();
private static final TranslatableComponent FILE_TOO_LARGE_TEXT = text("message.{mod}.import_file.file_too_large");
private static final MutableComponent FILE_TOO_LARGE_TEXT = text("message.{mod}.import_file.file_too_large");
///////////////////////////////////////////////////////////////////

View File

@@ -123,16 +123,6 @@ public record ChainableVertexConsumer(VertexConsumer inner) implements VertexCon
return this;
}
@Override
public void putBulkData(final PoseStack.Pose matrixStack, final BakedQuad bakedQuad, final float red, final float green, final float blue, final int lightmapCoord, final int overlayColor, final boolean readExistingColor) {
inner.putBulkData(matrixStack, bakedQuad, red, green, blue, lightmapCoord, overlayColor, readExistingColor);
}
@Override
public void putBulkData(final PoseStack.Pose matrixEntry, final BakedQuad bakedQuad, final float red, final float green, final float blue, final float alpha, final int lightmapCoord, final int overlayColor) {
inner.putBulkData(matrixEntry, bakedQuad, red, green, blue, alpha, lightmapCoord, overlayColor);
}
@Override
public void putBulkData(final PoseStack.Pose matrixEntry, final BakedQuad bakedQuad, final float red, final float green, final float blue, final float alpha, final int lightmapCoord, final int overlayColor, final boolean readExistingColor) {
inner.putBulkData(matrixEntry, bakedQuad, red, green, blue, alpha, lightmapCoord, overlayColor, readExistingColor);

View File

@@ -9,7 +9,7 @@ import net.minecraft.core.SectionPos;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;

View File

@@ -5,6 +5,7 @@ package li.cil.oc2.common.util;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
@@ -51,7 +52,7 @@ public final class ItemStackUtils {
return Optional.empty();
}
final Random rng = level.random;
final RandomSource rng = level.random;
final float tx = 0.5f * (rng.nextFloat() - 1.0f);
final float ty = 0.5f * (rng.nextFloat() - 1.0f);
@@ -80,7 +81,7 @@ public final class ItemStackUtils {
return Optional.empty();
}
final Random rng = level.random;
final RandomSource rng = level.random;
final float ox = direction.getStepX();
final float oy = direction.getStepY();

View File

@@ -11,6 +11,7 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.registries.ForgeRegistries;
import javax.annotation.Nullable;
import java.util.function.Function;
@@ -35,7 +36,7 @@ public final class LevelUtils {
final BlockEntity blockEntity = level.getBlockEntity(pos);
if (blockEntity != null) {
final ResourceLocation registryName = blockEntity.getType().getRegistryName();
final ResourceLocation registryName = ForgeRegistries.BLOCK_ENTITY_TYPES.getKey(blockEntity.getType());
if (registryName != null) {
return registryName.toString();
}
@@ -43,7 +44,7 @@ public final class LevelUtils {
final Block block = level.getBlockState(pos).getBlock();
{
final ResourceLocation registryName = block.getRegistryName();
final ResourceLocation registryName = ForgeRegistries.BLOCKS.getKey(block);
if (registryName != null) {
return registryName.toString();
}

View File

@@ -3,13 +3,17 @@
package li.cil.oc2.common.util;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.device.DeviceType;
import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider;
import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import li.cil.oc2.common.bus.device.provider.ProviderRegistry;
import li.cil.oc2.common.bus.device.util.BlockDeviceInfo;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.IForgeRegistry;
import net.minecraftforge.registries.IForgeRegistryEntry;
import javax.annotation.Nullable;
import java.util.ArrayList;
@@ -27,7 +31,7 @@ public abstract class RegistryUtils {
private static final List<DeferredRegister<?>> ENTRIES = new ArrayList<>();
private static Phase phase = Phase.PRE_INIT;
public static <T extends IForgeRegistryEntry<T>> DeferredRegister<T> getInitializerFor(final ResourceKey<Registry<T>> key) {
public static <T extends IForgeRegistry<T>> DeferredRegister<T> getInitializerFor(final ResourceKey<Registry<T>> key) {
if (phase != Phase.INIT) throw new IllegalStateException();
final DeferredRegister<T> entry = DeferredRegister.create(key, API.MOD_ID);
@@ -35,7 +39,7 @@ public abstract class RegistryUtils {
return entry;
}
public static <T extends IForgeRegistryEntry<T>> DeferredRegister<T> getInitializerFor(final IForgeRegistry<T> registry) {
public static <T extends IForgeRegistry<T>> DeferredRegister<T> getInitializerFor(final IForgeRegistry<T> registry) {
if (phase != Phase.INIT) throw new IllegalStateException();
final DeferredRegister<T> entry = DeferredRegister.create(registry, API.MOD_ID);
@@ -59,21 +63,26 @@ public abstract class RegistryUtils {
ENTRIES.clear();
}
public static <T> String key(final IForgeRegistryEntry<T> registryEntry) {
return Objects.requireNonNull(registryEntry.getRegistryName()).toString();
public static <T> String key(final DeviceType registryEntry) {
return Objects.requireNonNull(registryEntry.getName()).toString();
}
public static <T> Optional<String> optionalKey(@Nullable final IForgeRegistryEntry<T> registryEntry) {
if (registryEntry == null) {
public static <T> Optional<String> optionalKey(@Nullable final T registryEntry) {
if(registryEntry == null) {
return Optional.empty();
}
String providerName = null;
if (registryEntry.getClass() == BlockDeviceProvider.class) {
providerName = ProviderRegistry.BLOCK_DEVICE_PROVIDER_REGISTRY.get().getKey((BlockDeviceProvider) registryEntry).toString();
} else if (registryEntry.getClass() == ItemDeviceProvider.class) {
providerName = ProviderRegistry.ITEM_DEVICE_PROVIDER_REGISTRY.get().getKey((ItemDeviceProvider) registryEntry).toString();
}
if(providerName == null) {
return Optional.empty();
}
final ResourceLocation providerName = registryEntry.getRegistryName();
if (providerName == null) {
return Optional.empty();
}
return Optional.of(providerName.toString());
return Optional.of(providerName);
}
private RegistryUtils() {

View File

@@ -7,8 +7,8 @@ import net.minecraft.world.level.LevelAccessor;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.TickEvent;
import net.minecraftforge.event.server.ServerStoppedEvent;
import net.minecraftforge.event.world.ChunkEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.event.level.ChunkEvent;
import net.minecraftforge.event.level.LevelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import javax.annotation.Nullable;
@@ -126,8 +126,8 @@ public final class ServerScheduler {
}
@SubscribeEvent
public static void handleLevelUnload(final WorldEvent.Unload event) {
final LevelAccessor level = event.getWorld();
public static void handleLevelUnload(final LevelEvent.Unload event) {
final LevelAccessor level = event.getLevel();
levelTickSchedulers.remove(level);
chunkLoadSchedulers.remove(level);
@@ -141,7 +141,7 @@ public final class ServerScheduler {
@SubscribeEvent
public static void handleChunkLoad(final ChunkEvent.Load event) {
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkLoadSchedulers.get(event.getWorld());
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkLoadSchedulers.get(event.getLevel());
if (chunkMap == null) {
return;
}
@@ -154,7 +154,7 @@ public final class ServerScheduler {
@SubscribeEvent
public static void handleChunkUnload(final ChunkEvent.Unload event) {
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkUnloadSchedulers.get(event.getWorld());
final HashMap<ChunkPos, ListenerCollection> chunkMap = chunkUnloadSchedulers.get(event.getLevel());
if (chunkMap == null) {
return;
}
@@ -177,14 +177,14 @@ public final class ServerScheduler {
}
@SubscribeEvent
public static void handleLevelTick(final TickEvent.WorldTickEvent event) {
public static void handleLevelTick(final TickEvent.LevelTickEvent event) {
if (event.phase != TickEvent.Phase.START) {
return;
}
globalTickScheduler.processQueue();
final TickScheduler scheduler = levelTickSchedulers.get(event.world);
final TickScheduler scheduler = levelTickSchedulers.get(event.level);
if (scheduler != null) {
scheduler.processQueue();
}

View File

@@ -5,12 +5,13 @@ package li.cil.oc2.common.util;
import li.cil.oc2.api.API;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.RegistryObject;
public final class SoundEvents {
private static final DeferredRegister<SoundEvent> SOUNDS = RegistryUtils.getInitializerFor(ForgeRegistries.SOUND_EVENTS);
private static final DeferredRegister<SoundEvent> SOUNDS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, API.MOD_ID);
///////////////////////////////////////////////////////////////////
@@ -23,6 +24,7 @@ public final class SoundEvents {
///////////////////////////////////////////////////////////////////
public static void initialize() {
SOUNDS.register(FMLJavaModLoadingContext.get().getModEventBus());
}
///////////////////////////////////////////////////////////////////

View File

@@ -6,7 +6,6 @@ import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
import net.minecraft.network.chat.TextColor;
import net.minecraft.network.chat.TextComponent;
public final class TextFormatUtils {
private static final int SIZE_STEP = 1024;
@@ -22,7 +21,7 @@ public final class TextFormatUtils {
}
public static MutableComponent withFormat(final String value, final ChatFormatting formatting) {
return withFormat(new TextComponent(value), formatting);
return withFormat(Component.literal(value), formatting);
}
public static MutableComponent withFormat(final MutableComponent text, final ChatFormatting formatting) {
@@ -30,6 +29,6 @@ public final class TextFormatUtils {
}
public static Component withFormat(final Component text, final ChatFormatting formatting) {
return new TextComponent("").withStyle(formatting).append(text);
return Component.literal("").withStyle(formatting).append(text);
}
}

View File

@@ -5,6 +5,7 @@ package li.cil.oc2.common.util;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.util.Mth;
import net.minecraft.util.RandomSource;
import java.time.Duration;
import java.util.Optional;
@@ -78,11 +79,11 @@ public final class ThrottledSoundEmitter {
///////////////////////////////////////////////////////////////////
private float sampleVolume(final Random random) {
private float sampleVolume(final RandomSource random) {
return Mth.clamp(volume + volumeVariance * (random.nextFloat() - 0.5f), 0, 1);
}
private float samplePitch(final Random random) {
private float samplePitch(final RandomSource random) {
return Mth.clamp(pitch + pitchVariance * (random.nextFloat() - 0.5f), 0, 1);
}
}

View File

@@ -36,7 +36,7 @@ import static li.cil.oc2.common.util.TextFormatUtils.withFormat;
public final class TooltipUtils {
private static final MutableComponent DEVICE_NEEDS_REBOOT =
new TranslatableComponent(Constants.TOOLTIP_DEVICE_NEEDS_REBOOT)
Component.translatable(Constants.TOOLTIP_DEVICE_NEEDS_REBOOT)
.withStyle(s -> s.withColor(TextColor.fromLegacyFormat(ChatFormatting.YELLOW)));
private static final ThreadLocal<List<ItemStack>> ITEM_STACKS = ThreadLocal.withInitial(ArrayList::new);
@@ -82,7 +82,7 @@ public final class TooltipUtils {
final String translationKey = stack.getDescriptionId() + Constants.TOOLTIP_DESCRIPTION_SUFFIX;
final Language language = Language.getInstance();
if (language.has(translationKey)) {
final TranslatableComponent description = new TranslatableComponent(translationKey);
final MutableComponent description = Component.translatable(translationKey);
tooltip.add(withFormat(description, ChatFormatting.GRAY));
}
@@ -101,7 +101,7 @@ public final class TooltipUtils {
if (energyConsumption > 0) {
final MutableComponent energy = withFormat(String.valueOf(energyConsumption), ChatFormatting.GREEN);
tooltip.add(withFormat(new TranslatableComponent(Constants.TOOLTIP_ENERGY_CONSUMPTION, energy), ChatFormatting.GRAY));
tooltip.add(withFormat(Component.translatable(Constants.TOOLTIP_ENERGY_CONSUMPTION, energy), ChatFormatting.GRAY));
}
}
@@ -133,10 +133,10 @@ public final class TooltipUtils {
for (int i = 0; i < itemStacks.size(); i++) {
final ItemStack itemStack = itemStacks.get(i);
tooltip.add(new TextComponent("- ")
tooltip.add(Component.literal("- ")
.append(itemStack.getDisplayName())
.withStyle(style -> style.withColor(TextColor.fromLegacyFormat(ChatFormatting.GRAY)))
.append(new TextComponent(" x")
.append(Component.literal(" x")
.append(String.valueOf(itemStackSizes.getInt(i)))
.withStyle(style -> style.withColor(TextColor.fromLegacyFormat(ChatFormatting.DARK_GRAY))))
);
@@ -150,13 +150,13 @@ public final class TooltipUtils {
}
final MutableComponent value = withFormat(energy.getEnergyStored() + "/" + energy.getMaxEnergyStored(), ChatFormatting.GREEN);
tooltip.add(withFormat(new TranslatableComponent(Constants.TOOLTIP_ENERGY, value), ChatFormatting.GRAY));
tooltip.add(withFormat(Component.translatable(Constants.TOOLTIP_ENERGY, value), ChatFormatting.GRAY));
});
}
public static void addEnergyConsumption(final double value, final List<Component> tooltip) {
if (value > 0) {
tooltip.add(withFormat(new TranslatableComponent(Constants.TOOLTIP_ENERGY_CONSUMPTION, withFormat(new DecimalFormat("#.##").format(value), ChatFormatting.GREEN)), ChatFormatting.GRAY));
tooltip.add(withFormat(Component.translatable(Constants.TOOLTIP_ENERGY_CONSUMPTION, withFormat(new DecimalFormat("#.##").format(value), ChatFormatting.GREEN)), ChatFormatting.GRAY));
}
}

View File

@@ -3,15 +3,16 @@
package li.cil.oc2.common.util;
import li.cil.oc2.api.API;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
public final class TranslationUtils {
public static String key(final String pattern) {
return pattern.replaceAll("\\{mod}", API.MOD_ID);
}
public static TranslatableComponent text(final String pattern) {
return new TranslatableComponent(key(pattern));
public static MutableComponent text(final String pattern) {
return Component.translatable(key(pattern));
}
private TranslationUtils() {

View File

@@ -105,7 +105,7 @@ public abstract class AbstractVMItemStackHandlers implements VMItemStackHandlers
public void saveItems(final CompoundTag tag) {
itemHandlers.forEach((deviceType, handler) -> {
if (!handler.isEmpty()) {
tag.put(key(deviceType), handler.saveItems());
tag.put(deviceType.getName().toString(), handler.saveItems());
}
});
}
@@ -118,12 +118,12 @@ public abstract class AbstractVMItemStackHandlers implements VMItemStackHandlers
public void loadItems(final CompoundTag tag) {
itemHandlers.forEach((deviceType, handler) ->
handler.loadItems(tag.getCompound(key(deviceType))));
handler.loadItems(tag.getCompound(deviceType.getName().toString())));
}
public void saveDevices(final CompoundTag tag) {
itemHandlers.forEach((deviceType, handler) ->
tag.put(key(deviceType), handler.saveDevices()));
tag.put(deviceType.getName().toString(), handler.saveDevices()));
}
public CompoundTag saveDevices() {
@@ -134,7 +134,7 @@ public abstract class AbstractVMItemStackHandlers implements VMItemStackHandlers
public void loadDevices(final CompoundTag tag) {
itemHandlers.forEach((deviceType, handler) ->
handler.loadDevices(tag.getCompound(key(deviceType))));
handler.loadDevices(tag.getCompound(deviceType.getName().toString())));
}
///////////////////////////////////////////////////////////////////

View File

@@ -17,7 +17,6 @@ import li.cil.sedna.api.memory.MemoryAccessException;
import li.cil.sedna.riscv.R5Board;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import org.apache.logging.log4j.LogManager;
@@ -141,11 +140,11 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
switch (busState) {
case SCAN_PENDING:
case INCOMPLETE:
return new TranslatableComponent(Constants.COMPUTER_BUS_STATE_INCOMPLETE);
return Component.translatable(Constants.COMPUTER_BUS_STATE_INCOMPLETE);
case TOO_COMPLEX:
return new TranslatableComponent(Constants.COMPUTER_BUS_STATE_TOO_COMPLEX);
return Component.translatable(Constants.COMPUTER_BUS_STATE_TOO_COMPLEX);
case MULTIPLE_CONTROLLERS:
return new TranslatableComponent(Constants.COMPUTER_BUS_STATE_MULTIPLE_CONTROLLERS);
return Component.translatable(Constants.COMPUTER_BUS_STATE_MULTIPLE_CONTROLLERS);
case READY:
switch (runState) {
case STOPPED:
@@ -283,12 +282,12 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
if (!consumeEnergy(busController.getEnergyConsumption(), true)) {
// Don't even start running if we couldn't keep running.
error(new TranslatableComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
error(Component.translatable(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}
if (busController.getDevices().stream().noneMatch(device -> device instanceof FirmwareLoader)) {
error(new TranslatableComponent(Constants.COMPUTER_ERROR_MISSING_FIRMWARE));
error(Component.translatable(Constants.COMPUTER_ERROR_MISSING_FIRMWARE));
return;
}
@@ -299,7 +298,7 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
if (loadResult.getErrorMessage() != null) {
error(loadResult.getErrorMessage(), false);
} else {
error(new TranslatableComponent(Constants.COMPUTER_ERROR_UNKNOWN), false);
error(Component.translatable(Constants.COMPUTER_ERROR_UNKNOWN), false);
}
loadDevicesDelay = DEVICE_LOAD_RETRY_INTERVAL;
return;
@@ -317,11 +316,11 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
// a program that only uses registers. But not supporting that esoteric
// use-case loses out against avoiding people getting confused for having
// forgotten to add some RAM modules.
error(new TranslatableComponent(Constants.COMPUTER_ERROR_INSUFFICIENT_MEMORY));
error(Component.translatable(Constants.COMPUTER_ERROR_INSUFFICIENT_MEMORY));
return;
} catch (final MemoryAccessException e) {
LOGGER.error(e);
error(new TranslatableComponent(Constants.COMPUTER_ERROR_UNKNOWN));
error(Component.translatable(Constants.COMPUTER_ERROR_UNKNOWN));
return;
}
@@ -349,7 +348,7 @@ public abstract class AbstractVirtualMachine implements VirtualMachine {
}
if (!consumeEnergy(busController.getEnergyConsumption(), false)) {
error(new TranslatableComponent(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
error(Component.translatable(Constants.COMPUTER_ERROR_NOT_ENOUGH_ENERGY));
return;
}

View File

@@ -791,13 +791,15 @@ public final class Terminal {
renderBackground(matrix, builder, row);
renderForeground(matrix, builder, row);
builder.end();
BufferBuilder.RenderedBuffer rb = builder.end();
if (lines[row] == null) {
lines[row] = new VertexBuffer();
}
lines[row].upload(builder);
lines[row].upload(rb);
}
}
@@ -910,6 +912,7 @@ public final class Terminal {
}
private void renderCursor(final PoseStack stack) {
BufferUploader.reset();
if (terminal.x < 0 || terminal.x >= WIDTH || terminal.y < 0 || terminal.y >= HEIGHT) {
return;
}
@@ -934,8 +937,8 @@ public final class Terminal {
buffer.vertex(matrix, CHAR_WIDTH, 0, 0).color(r, g, b, 1).endVertex();
buffer.vertex(matrix, 0, 0, 0).color(r, g, b, 1).endVertex();
buffer.end();
BufferUploader.end(buffer);
BufferBuilder.RenderedBuffer rb = buffer.end();
BufferUploader.draw(rb);
stack.popPose();

View File

@@ -12,7 +12,6 @@ import li.cil.oc2.common.bus.RPCDeviceBusAdapter;
import li.cil.oc2.common.vm.context.global.GlobalVMContext;
import li.cil.sedna.riscv.R5Board;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import javax.annotation.Nullable;
import java.util.concurrent.ExecutionException;
@@ -131,7 +130,7 @@ public class VMRunner implements Runnable {
context.postEvent(new VMInitializingEvent(board.getDefaultProgramStart()));
} catch (final VMInitializationException e) {
board.setRunning(false);
runtimeError = e.getErrorMessage().orElse(new TranslatableComponent(Constants.COMPUTER_ERROR_UNKNOWN));
runtimeError = e.getErrorMessage().orElse(Component.translatable(Constants.COMPUTER_ERROR_UNKNOWN));
return;
}
}

View File

@@ -5,9 +5,9 @@ package li.cil.oc2.data;
import net.minecraft.data.DataGenerator;
import net.minecraft.data.tags.BlockTagsProvider;
import net.minecraftforge.common.data.ExistingFileHelper;
import net.minecraftforge.data.event.GatherDataEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.forge.event.lifecycle.GatherDataEvent;
@Mod.EventBusSubscriber(bus = Mod.EventBusSubscriber.Bus.MOD)
public final class DataGenerators {
@@ -17,15 +17,15 @@ public final class DataGenerators {
final ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
if (event.includeServer()) {
generator.addProvider(new ModLootTableProvider(generator));
generator.addProvider(true, new ModLootTableProvider(generator));
final BlockTagsProvider blockTagProvider = new ModBlockTagsProvider(generator, existingFileHelper);
generator.addProvider(blockTagProvider);
generator.addProvider(new ModItemTagsProvider(generator, blockTagProvider, existingFileHelper));
generator.addProvider(new ModRecipesProvider(generator));
generator.addProvider(true, blockTagProvider);
generator.addProvider(true, new ModItemTagsProvider(generator, blockTagProvider, existingFileHelper));
generator.addProvider(true, new ModRecipesProvider(generator));
}
if (event.includeClient()) {
generator.addProvider(new ModBlockStateProvider(generator, existingFileHelper));
generator.addProvider(new ModItemModelProvider(generator, existingFileHelper));
generator.addProvider(true, new ModBlockStateProvider(generator, existingFileHelper));
generator.addProvider(true, new ModItemModelProvider(generator, existingFileHelper));
}
}
}

View File

@@ -20,6 +20,8 @@ import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.level.storage.loot.providers.nbt.ContextNbtProvider;
import net.minecraft.world.level.storage.loot.providers.number.ConstantValue;
import net.minecraftforge.registries.ForgeRegistries;
import net.minecraftforge.registries.ForgeRegistry;
import java.util.List;
import java.util.Map;
@@ -64,7 +66,7 @@ public final class ModLootTableProvider extends LootTableProvider {
@Override
protected Iterable<Block> getKnownBlocks() {
return StreamSupport.stream(super.getKnownBlocks().spliterator(), false)
.filter(block -> requireNonNull(block.getRegistryName()).getNamespace().equals(API.MOD_ID))
.filter(block -> requireNonNull(ForgeRegistries.BLOCKS.getKey(block)).getNamespace().equals(API.MOD_ID))
.filter(block -> block != Blocks.BUS_CABLE.get()) // All bus drops depend on block state.
.collect(Collectors.toList());
}

View File

@@ -23,7 +23,7 @@ side = "BOTH"
[[dependencies.oc2]]
modId = "minecraft"
mandatory = true
versionRange = "[1.18.2,1.19)"
versionRange = "1.19.2"
ordering = "NONE"
side = "BOTH"
[[dependencies.oc2]]

View File

@@ -1,51 +0,0 @@
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.device.rpc.AbstractRPCMethod;
import li.cil.oc2.api.bus.device.rpc.RPCParameter;
import javax.annotation.Nullable;
import java.util.Optional;
abstract class AbstractTestMethod extends AbstractRPCMethod {
protected AbstractTestMethod(final Class<?> returnType, final Class<?>... parameterTypes) {
super("", returnType, wrapParameters(parameterTypes));
}
@Override
public String getName() {
return getClass().getSimpleName();
}
@Override
public boolean isSynchronized() {
return false;
}
private static RPCParameter[] wrapParameters(final Class<?>... parameterTypes) {
final RPCParameter[] parameters = new RPCParameter[parameterTypes.length];
for (int i = 0; i < parameterTypes.length; i++) {
parameters[i] = new TestParameter("arg" + i, parameterTypes[i]);
}
return parameters;
}
private static final class TestParameter implements RPCParameter {
@Nullable private final String name;
private final Class<?> type;
public TestParameter(@Nullable final String name, final Class<?> type) {
this.name = name;
this.type = type;
}
@Override
public Optional<String> getName() {
return Optional.ofNullable(name);
}
@Override
public Class<?> getType() {
return type;
}
}
}

View File

@@ -1,735 +0,0 @@
/* SPDX-License-Identifier: MIT */
package li.cil.oc2.common.bus;
import li.cil.oc2.api.API;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.ItemDevice;
import li.cil.oc2.api.bus.device.object.Callback;
import li.cil.oc2.api.bus.device.object.ObjectDevice;
import li.cil.oc2.api.bus.device.provider.BlockDeviceProvider;
import li.cil.oc2.api.bus.device.provider.BlockDeviceQuery;
import li.cil.oc2.api.bus.device.provider.ItemDeviceProvider;
import li.cil.oc2.api.bus.device.provider.ItemDeviceQuery;
import li.cil.oc2.api.util.Invalidatable;
import li.cil.oc2.common.Constants;
import li.cil.oc2.common.bus.device.provider.Providers;
import li.cil.oc2.common.capabilities.Capabilities;
import li.cil.oc2.common.util.LevelUtils;
import li.cil.sedna.api.device.serial.SerialDevice;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.LevelAccessor;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraftforge.common.capabilities.Capability;
import net.minecraftforge.common.util.LazyOptional;
import net.minecraftforge.registries.IForgeRegistry;
import org.jetbrains.annotations.Nullable;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.MockedStatic;
import org.mockito.stubbing.OngoingStubbing;
import java.util.*;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.*;
public class BlockDeviceBusControllerTests {
public static final ResourceLocation TEST_PROVIDER_REGISTRY_NAME = new ResourceLocation(API.MOD_ID, "test");
private static MockedStatic<Capabilities> capabilitiesMock;
private static MockedStatic<Providers> providersMock;
private static MockedStatic<LevelUtils> levelUtilsMock;
private FakeLevel fakeLevel;
private LevelAccessor level;
///////////////////////////////////////////////////////////////////
@SuppressWarnings("ResultOfMethodCallIgnored")
@BeforeEach
public void setupEach() {
capabilitiesMock = mockStatic(Capabilities.class);
registerCapability(capabilitiesMock.when(Capabilities::energyStorage));
registerCapability(capabilitiesMock.when(Capabilities::fluidHandler));
registerCapability(capabilitiesMock.when(Capabilities::itemHandler));
registerCapability(capabilitiesMock.when(Capabilities::deviceBusElement));
registerCapability(capabilitiesMock.when(Capabilities::device));
registerCapability(capabilitiesMock.when(Capabilities::redstoneEmitter));
registerCapability(capabilitiesMock.when(Capabilities::networkInterface));
registerCapability(capabilitiesMock.when(Capabilities::terminalUserProvider));
registerCapability(capabilitiesMock.when(Capabilities::robot));
providersMock = mockStatic(Providers.class);
final IForgeRegistry<BlockDeviceProvider> blockDeviceProviderRegistry = createBlockDeviceProviderRegistry();
providersMock.when(Providers::blockDeviceProviderRegistry).thenReturn(blockDeviceProviderRegistry);
final IForgeRegistry<ItemDeviceProvider> itemDeviceProviderRegistry = createItemDeviceProviderRegistry();
providersMock.when(Providers::itemDeviceProviderRegistry).thenReturn(itemDeviceProviderRegistry);
levelUtilsMock = mockStatic(LevelUtils.class);
levelUtilsMock.when(() -> LevelUtils.getBlockName(any(), any())).thenReturn("test_block");
fakeLevel = new FakeLevel();
level = fakeLevel.getLevel();
}
@SuppressWarnings("unchecked")
private static <T> void registerCapability(final OngoingStubbing<Capability<T>> stubbing) {
final Capability<T> capability = mock(Capability.class);
stubbing.thenReturn(capability);
}
@AfterEach
public void teardownEach() {
capabilitiesMock.close();
providersMock.close();
levelUtilsMock.close();
}
@Test
public void busTouchingUnloadedChunkStaysIncomplete() {
final BlockPos posAtChunkEdge = new BlockPos(0, 0, 0);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(posAtChunkEdge).getBusController();
busController.scan();
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
}
@Test
public void busNotTouchingUnloadedChunkCompletes() {
final BlockPos posInsideChunk = new BlockPos(8, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(posInsideChunk).getBusController();
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
}
@Test
public void busControllerIgnoresNonAccessibleBusElements() {
final BlockPos controllerPos = new BlockPos(8, 0, 8);
final TestBusControllerBlockEntity busController = new TestBusControllerBlockEntity(controllerPos);
final BlockPos elementPos = controllerPos.east();
final TestBusElementBlockEntity busElement = new TestBusElementBlockEntity(elementPos);
busElement.setSideEnabled(Direction.WEST, false);
busController.getBusController().scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getBusController().getState());
assertFalse(busElement.getBusElement().getControllers().contains(busController.getBusController()));
assertFalse(busController.getBusController().getElements().contains(busElement.getBusElement()));
}
@Test
public void busControllerDetectsBusElements() {
final BlockPos controllerPos = new BlockPos(8, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(controllerPos).getBusController();
final BlockPos elementPos = controllerPos.east();
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final DeviceBusElement busElement = busElementInfo.getBusElement();
busController.scan();
assertTrue(busElement.getControllers().contains(busController));
assertTrue(busController.getElements().contains(busElement));
}
@Test
public void devicesInUnloadedChunksAreMarkedAsUnloaded() {
final BlockPos elementPos = new BlockPos(0, 0, 0);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final TestBlockDeviceBusElement busElement = busElementInfo.getBusElement();
busElement.updateDevicesForNeighbor(Direction.WEST);
verify(busElement, atLeastOnce()).setEntriesForGroupUnloaded(Direction.WEST.get3DDataValue());
}
@Test
public void unloadedDeviceIsRemovedFromElement() {
final BlockPos elementPos = new BlockPos(0, 0, 8);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final BlockPos devicePos = elementPos.west();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertTrue(busElementInfo.getBusElement().getDevices().contains(deviceBlockEntity.getObjectDevice()));
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), false);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertFalse(busElementInfo.getBusElement().getDevices().contains(deviceBlockEntity.getObjectDevice()));
}
@Test
public void devicesInLoadedChunksAreCollected() {
final BlockPos elementPos = new BlockPos(0, 0, 0);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final TestBlockDeviceBusElement busElement = busElementInfo.getBusElement();
final BlockPos devicePos = elementPos.east();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
busElement.updateDevicesForNeighbor(Direction.EAST);
verify(busElement, atLeastOnce()).setEntriesForGroup(eq(Direction.EAST.get3DDataValue()), any());
assertTrue(busElement.getDevices().contains(deviceBlockEntity.getObjectDevice()));
}
@Test
public void equalDevicesAreIgnored() {
final BlockPos elementPos = new BlockPos(0, 0, 0);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final TestBlockDeviceBusElement busElement = busElementInfo.getBusElement();
final BlockPos devicePos = elementPos.east();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
busElement.updateDevicesForNeighbor(Direction.EAST);
assertTrue(busElement.getDevices().contains(deviceBlockEntity.getObjectDevice()));
final ObjectDevice equalDevice = new ObjectDevice(deviceBlockEntity.getTestDevice());
deviceBlockEntity.setObjectDevice(equalDevice);
busElement.updateDevicesForNeighbor(Direction.EAST);
assertTrue(busElement.getDevices().contains(deviceBlockEntity.getObjectDevice()));
assertNotSame(busElement.getDevices().stream().findFirst().orElseThrow(), equalDevice);
}
@Test
public void busControllerDetectsDevices() {
final BlockPos controllerPos = new BlockPos(8, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(controllerPos).getBusController();
final BlockPos elementPos = controllerPos.east();
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
when(busElementInfo.getBlockEntity().getCapability(eq(Capabilities.deviceBusElement()), any())).thenReturn(LazyOptional.of(busElementInfo::getBusElement));
final BlockPos devicePos = elementPos.east();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.EAST);
busController.scan();
assertTrue(busController.getDevices().contains(deviceBlockEntity.getObjectDevice()));
}
@Test
public void devicesGetSerializedWhenUnloadedAndDeserializedWhenLoaded() {
final BlockPos controllerPos = new BlockPos(1, 0, 8);
final BlockDeviceBusController busController = new TestBusControllerBlockEntity(controllerPos).getBusController();
final BlockPos elementPos = controllerPos.west();
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
when(busElementInfo.getBlockEntity().getCapability(eq(Capabilities.deviceBusElement()), any())).thenReturn(LazyOptional.of(busElementInfo::getBusElement));
final BlockPos devicePos = elementPos.west();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), false);
busController.scheduleBusScan();
final RPCDeviceBusAdapter rpcDeviceBusAdapter = new RPCDeviceBusAdapter(mock(SerialDevice.class));
busController.onBeforeDeviceScan.add(rpcDeviceBusAdapter::pause);
busController.onAfterDeviceScan.add(event -> rpcDeviceBusAdapter.resume(busController, event.didDevicesChange()));
busController.scan();
// Reminder: missing chunk -> bus scan cannot complete.
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
final ObjectDevice objectDevice = spy(deviceBlockEntity.getObjectDevice());
deviceBlockEntity.setObjectDevice(objectDevice);
// Initialize with unloaded chunk.
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertFalse(busController.getDevices().contains(objectDevice));
verify(objectDevice, never()).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
// Load device chunk.
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), true);
busController.scheduleBusScan();
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
assertTrue(busController.getDevices().contains(objectDevice));
rpcDeviceBusAdapter.mountDevices();
verify(objectDevice, times(1)).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any()); // no state to deserialize
// Unload device chunk.
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), false);
busController.scheduleBusScan();
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
busController.scan();
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
assertFalse(busController.getDevices().contains(objectDevice));
verify(objectDevice, times(1)).mount();
verify(objectDevice, times(1)).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, times(1)).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
}
// Different load states and how removals effect state. Adds are uninteresting,
// because we need a fully loaded state before anything happens here.
// Loaded: [ ] Controller, [ ] Element, [ ] Device
// -> No interaction possible.
// Loaded: [ ] Controller, [ ] Element, [x] Device
// -> Removing Device:
// -> Provider#dispose() when Element is loaded.
@Test
public void providerDisposeIsCalledWhenDeviceIsRemovedWhileElementIsUnloaded() {
final BlockPos elementPos = new BlockPos(0, 0, 8);
TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final BlockPos devicePos = elementPos.west();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
final ObjectDevice objectDevice = spy(deviceBlockEntity.getObjectDevice());
deviceBlockEntity.setObjectDevice(objectDevice);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertTrue(busElementInfo.getBusElement().getDevices().contains(deviceBlockEntity.getObjectDevice()));
verify(objectDevice, never()).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
final CompoundTag data = busElementInfo.getBusElement().save();
verify(objectDevice, times(1)).serializeNBT();
fakeLevel.setChunkLoaded(new ChunkPos(elementPos), false);
fakeLevel.removeBlockEntity(elementPos);
fakeLevel.removeBlockEntity(devicePos);
fakeLevel.setChunkLoaded(new ChunkPos(elementPos), true);
busElementInfo = new TestBusElementBlockEntity(elementPos);
busElementInfo.getBusElement().load(data);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
final BlockDeviceProvider provider = Providers.blockDeviceProviderRegistry().getValue(TEST_PROVIDER_REGISTRY_NAME);
verify(provider, times(1)).unmount(any(), any());
}
// Loaded: [ ] Controller, [x] Element, [ ] Device
// -> Removing Element:
// -> Provider#dispose()
@Test
public void providerDisposeIsCalledWhenElementIsRemovedWhileDeviceIsUnloaded() {
final BlockPos elementPos = new BlockPos(0, 0, 8);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final BlockPos devicePos = elementPos.west();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
final ObjectDevice objectDevice = spy(deviceBlockEntity.getObjectDevice());
deviceBlockEntity.setObjectDevice(objectDevice);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertTrue(busElementInfo.getBusElement().getDevices().contains(deviceBlockEntity.getObjectDevice()));
verify(objectDevice, never()).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
fakeLevel.setChunkLoaded(new ChunkPos(devicePos), false);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertFalse(busElementInfo.getBusElement().getDevices().contains(deviceBlockEntity.getObjectDevice()));
verify(objectDevice, never()).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, times(1)).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
fakeLevel.removeBlockEntity(elementPos);
busElementInfo.getBusElement().setRemoved();
final BlockDeviceProvider provider = Providers.blockDeviceProviderRegistry().getValue(TEST_PROVIDER_REGISTRY_NAME);
verify(provider, times(1)).unmount(any(), any());
}
// Loaded: [ ] Controller, [x] Element, [x] Device
// -> Removing Element:
// -> Device#dispose()
@Test
public void deviceIsDisposedWhenElementIsRemoved() {
final BlockPos elementPos = new BlockPos(8, 0, 8);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final BlockPos devicePos = elementPos.west();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
final ObjectDevice objectDevice = spy(deviceBlockEntity.getObjectDevice());
deviceBlockEntity.setObjectDevice(objectDevice);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertTrue(busElementInfo.getBusElement().getDevices().contains(deviceBlockEntity.getObjectDevice()));
verify(objectDevice, never()).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
fakeLevel.removeBlockEntity(elementPos);
busElementInfo.getBusElement().setRemoved();
verify(objectDevice, times(1)).dispose();
final BlockDeviceProvider provider = Providers.blockDeviceProviderRegistry().getValue(TEST_PROVIDER_REGISTRY_NAME);
verify(provider, never()).unmount(any(), any());
}
// -> Removing Device:
// -> Device#dispose()
@Test
public void deviceIsDisposedWhenDeviceIsRemoved() {
final BlockPos elementPos = new BlockPos(8, 0, 8);
final TestBusElementBlockEntity busElementInfo = new TestBusElementBlockEntity(elementPos);
final BlockPos devicePos = elementPos.west();
final TestDeviceBlockEntity deviceBlockEntity = new TestDeviceBlockEntity(devicePos);
final ObjectDevice objectDevice = spy(deviceBlockEntity.getObjectDevice());
deviceBlockEntity.setObjectDevice(objectDevice);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
assertTrue(busElementInfo.getBusElement().getDevices().contains(deviceBlockEntity.getObjectDevice()));
verify(objectDevice, never()).mount();
verify(objectDevice, never()).unmount();
verify(objectDevice, never()).dispose();
verify(objectDevice, never()).serializeNBT();
verify(objectDevice, never()).deserializeNBT(any());
fakeLevel.removeBlockEntity(devicePos);
busElementInfo.getBusElement().updateDevicesForNeighbor(Direction.WEST);
verify(objectDevice, times(1)).dispose();
final BlockDeviceProvider provider = Providers.blockDeviceProviderRegistry().getValue(TEST_PROVIDER_REGISTRY_NAME);
verify(provider, never()).unmount(any(), any());
}
// Loaded: [x] Controller, [ ] Element, [ ] Device
// -> Removing Controller:
// -> Edge-case: suspended Devices will *not* be disposed. If a new controller
// picks them up, they will resume under the assumption that they're managed
// by the same controller as before their previous unmount.
// Loaded: [x] Controller, [ ] Element, [x] Device
// -> Removing Controller:
// -> Edge-case: suspended Devices will *not* be disposed. If a new controller
// picks them up, they will resume under the assumption that they're managed
// by the same controller as before their previous unmount.
// -> Removing Device:
// -> Provider#dispose() when Element is loaded.
// Same as providerDisposeIsCalledWhenDeviceIsRemovedWhileElementIsUnloaded()
// Loaded: [x] Controller, [x] Element, [ ] Device
// -> Removing Controller:
// -> Edge-case: suspended Devices will *not* be disposed. If a new controller
// picks them up, they will resume under the assumption that they're managed
// by the same controller as before their previous unmount.
// -> Removing Element:
// -> Provider#dispose()
// Same as providerDisposeIsCalledWhenElementIsRemovedWhileDeviceIsUnloaded()
// Loaded: [x] Controller, [x] Element, [x] Device
// -> Removing Controller:
// -> Stop VM if running.
// -> Stopping VM:
// -> Device#unmount(), Device#dispose()
// Handled in Computer/Robot, too much pain to try to mock this.
// -> Removing Element:
// -> Device#unmount() if mounted, Device#dispose()
// -> Removing Device:
// -> Device#unmount() if mounted, Device#dispose()
// -> Unloading Controller, Element or Device:
// -> Device#unmount() if mounted.
// TODO
// Last case (all loaded) is the only case where the bus can be complete, so
// also the only case where Devices can possibly be mounted.
// In all but the last case (all loaded) it makes no difference if there's more
// loaded/unloaded elements in the chain. However, in the last case it does:
// -> Removing intermediate element:
// -> Edge-case: suspended Devices will *not* be disposed. If a new controller
// picks them up, they will resume under the assumption that they're managed
// by the same controller as before their previous unmount.
///////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked")
private static IForgeRegistry<BlockDeviceProvider> createBlockDeviceProviderRegistry() {
final IForgeRegistry<BlockDeviceProvider> registry = mock(IForgeRegistry.class);
final Map<ResourceLocation, BlockDeviceProvider> blockDeviceProviders = new HashMap<>();
blockDeviceProviders.put(TEST_PROVIDER_REGISTRY_NAME, spy(new TestBlockDeviceProvider()));
when(registry.getValues()).thenReturn(blockDeviceProviders.values());
when(registry.getValue(notNull())).then(a -> blockDeviceProviders.get(a.<ResourceLocation>getArgument(0)));
return registry;
}
@SuppressWarnings("unchecked")
private static IForgeRegistry<ItemDeviceProvider> createItemDeviceProviderRegistry() {
final IForgeRegistry<ItemDeviceProvider> registry = mock(IForgeRegistry.class);
final Map<ResourceLocation, ItemDeviceProvider> itemDeviceProviders = new HashMap<>();
itemDeviceProviders.put(TEST_PROVIDER_REGISTRY_NAME, spy(new TestItemDeviceProvider()));
when(registry.getValues()).thenReturn(itemDeviceProviders.values());
when(registry.getValue(notNull())).then(a -> itemDeviceProviders.get(a.<ResourceLocation>getArgument(0)));
return registry;
}
///////////////////////////////////////////////////////////////////
private static final class FakeLevel {
private final LevelAccessor level = mock(LevelAccessor.class);
private final HashMap<BlockPos, BlockEntity> blockEntities = new HashMap<>();
private final HashSet<ChunkPos> loadedChunks = new HashSet<>();
public FakeLevel() {
when(level.getBlockEntity(any())).then(a -> blockEntities.get(a.<BlockPos>getArgument(0)));
when(level.hasChunk(anyInt(), anyInt())).then(a -> {
final int chunkX = a.getArgument(0);
final int chunkZ = a.getArgument(1);
return loadedChunks.contains(new ChunkPos(chunkX, chunkZ));
});
}
public LevelAccessor getLevel() {
return level;
}
public void addBlockEntity(final BlockEntity blockEntity) {
blockEntities.put(blockEntity.getBlockPos(), blockEntity);
}
public void removeBlockEntity(final BlockPos pos) {
blockEntities.remove(pos);
}
public void setChunkLoaded(final ChunkPos chunkPos, final boolean loaded) {
if (loaded) {
loadedChunks.add(chunkPos);
} else {
loadedChunks.remove(chunkPos);
}
}
}
private class TestBlockEntity {
private final BlockEntity blockEntity;
public TestBlockEntity(final BlockPos pos) {
blockEntity = mock(BlockEntity.class);
when(blockEntity.getBlockPos()).thenReturn(pos);
when(blockEntity.getCapability(any(), any())).thenReturn(LazyOptional.empty());
when(blockEntity.getCapability(any())).thenCallRealMethod();
fakeLevel.addBlockEntity(blockEntity);
fakeLevel.setChunkLoaded(new ChunkPos(pos), true);
}
public BlockEntity getBlockEntity() {
return blockEntity;
}
}
private class TestBusElementBlockEntity extends TestBlockEntity {
private final TestBlockDeviceBusElement busElement;
private final boolean[] enabledSides = new boolean[Constants.BLOCK_FACE_COUNT];
public TestBusElementBlockEntity(final BlockPos pos) {
super(pos);
busElement = spy(new TestBlockDeviceBusElement(level, pos));
when(getBlockEntity().getCapability(eq(Capabilities.deviceBusElement()), any())).then(a -> {
if (enabledSides[a.<Direction>getArgument(1).get3DDataValue()]) {
return LazyOptional.of(() -> busElement);
} else {
return LazyOptional.empty();
}
});
Arrays.fill(enabledSides, true);
}
public TestBlockDeviceBusElement getBusElement() {
return busElement;
}
public void setSideEnabled(final Direction side, final boolean value) {
enabledSides[side.get3DDataValue()] = value;
}
}
private class TestBusControllerBlockEntity extends TestBusElementBlockEntity {
private final BlockDeviceBusController busController;
public TestBusControllerBlockEntity(final BlockPos pos) {
super(pos);
busController = new BlockDeviceBusController(getBusElement(), 0, getBlockEntity());
}
public BlockDeviceBusController getBusController() {
return busController;
}
}
private class TestDeviceBlockEntity extends TestBlockEntity {
private final TestDevice testDevice;
private ObjectDevice objectDevice;
public TestDeviceBlockEntity(final BlockPos pos) {
super(pos);
testDevice = new TestDevice();
objectDevice = new ObjectDevice(testDevice);
when(getBlockEntity().getCapability(eq(Capabilities.device()), any())).thenReturn(LazyOptional.of(() -> objectDevice));
}
public TestDevice getTestDevice() {
return testDevice;
}
public ObjectDevice getObjectDevice() {
return objectDevice;
}
public void setObjectDevice(final ObjectDevice device) {
this.objectDevice = device;
}
}
private static final class TestBlockDeviceBusElement extends AbstractBlockDeviceBusElement {
private final LevelAccessor level;
private final BlockPos blockPos;
public TestBlockDeviceBusElement(final LevelAccessor level, final BlockPos blockPos) {
this.level = level;
this.blockPos = blockPos;
}
@Override
public LevelAccessor getLevel() {
return level;
}
@Override
public BlockPos getPosition() {
return blockPos;
}
}
private static class TestBlockDeviceProvider implements BlockDeviceProvider {
@Override
public BlockDeviceProvider setRegistryName(final ResourceLocation name) {
return this;
}
@Nullable
@Override
public ResourceLocation getRegistryName() {
return TEST_PROVIDER_REGISTRY_NAME;
}
@Override
public Class<BlockDeviceProvider> getRegistryType() {
return BlockDeviceProvider.class;
}
@Override
public Invalidatable<Device> getDevice(final BlockDeviceQuery query) {
final LevelAccessor level = query.getLevel();
final BlockEntity blockEntity = level.getBlockEntity(query.getQueryPosition());
if (blockEntity != null) {
final Optional<Device> optional = blockEntity.getCapability(Capabilities.device()).resolve();
return optional.map(Invalidatable::of).orElseGet(Invalidatable::empty);
}
return Invalidatable.empty();
}
}
private static class TestItemDeviceProvider implements ItemDeviceProvider {
@Override
public ItemDeviceProvider setRegistryName(final ResourceLocation name) {
return this;
}
@Nullable
@Override
public ResourceLocation getRegistryName() {
return TEST_PROVIDER_REGISTRY_NAME;
}
@Override
public Class<ItemDeviceProvider> getRegistryType() {
return ItemDeviceProvider.class;
}
@Override
public Optional<ItemDevice> getDevice(final ItemDeviceQuery query) {
return Optional.empty();
}
}
public static class TestDevice {
@Callback
public int test() {
return 42;
}
}
}

View File

@@ -1,78 +0,0 @@
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.DeviceBusElement;
import li.cil.oc2.api.bus.device.rpc.RPCDevice;
import net.minecraftforge.common.util.LazyOptional;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.Optional;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.*;
public class CommonDeviceBusControllerTests {
private CommonDeviceBusController busController;
private DeviceBusElement busControllerBusElement;
@BeforeEach
public void setupEach() {
busControllerBusElement = mock(DeviceBusElement.class);
when(busControllerBusElement.getLocalDevices()).thenReturn(emptyList());
when(busControllerBusElement.getNeighbors()).thenReturn(Optional.empty());
busController = new CommonDeviceBusController(busControllerBusElement, 0);
}
@Test
public void scanPendingWhenBlockEntityNotLoaded() {
busController.scan();
assertEquals(CommonDeviceBusController.BusState.INCOMPLETE, busController.getState());
}
@Test
public void scanCompletesWhenNoNeighbors() {
when(busControllerBusElement.getNeighbors()).thenReturn(Optional.of(Collections.emptyList()));
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
}
@Test
public void scanSuccessfulWithLocalElement() {
when(busControllerBusElement.getNeighbors()).thenReturn(Optional.of(Collections.emptyList()));
final RPCDevice device = mock(RPCDevice.class);
when(busControllerBusElement.getLocalDevices()).thenReturn(singletonList(device));
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
verify(busControllerBusElement).addController(busController);
assertTrue(busController.getDevices().contains(device));
}
@Test
public void scanSuccessfulWithMultipleElements() {
// topology: controller <-> element 1 <-> element 2
final DeviceBusElement busElement1 = mock(DeviceBusElement.class);
final DeviceBusElement busElement2 = mock(DeviceBusElement.class);
when(busControllerBusElement.getNeighbors()).thenReturn(Optional.of(Collections.singleton(LazyOptional.of(() -> busElement1))));
when(busElement1.getNeighbors()).thenReturn(Optional.of(Collections.singleton(LazyOptional.of(() -> busControllerBusElement))));
when(busElement1.getNeighbors()).thenReturn(Optional.of(Collections.singleton(LazyOptional.of(() -> busElement2))));
when(busElement2.getNeighbors()).thenReturn(Optional.of(Collections.singleton(LazyOptional.of(() -> busElement1))));
busController.scan();
assertEquals(CommonDeviceBusController.BusState.READY, busController.getState());
verify(busElement1).addController(busController);
verify(busElement2).addController(busController);
}
}

View File

@@ -1,187 +0,0 @@
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.DeviceBusController;
import li.cil.oc2.api.bus.device.Device;
import li.cil.oc2.api.bus.device.rpc.RPCDevice;
import li.cil.oc2.api.bus.device.rpc.RPCMethod;
import li.cil.oc2.common.bus.device.rpc.RPCDeviceList;
import li.cil.sedna.api.device.serial.SerialDevice;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.*;
import static org.mockito.Mockito.*;
public final class RPCDeviceBusAdapterTests {
private RPCDeviceBusAdapter adapter;
private Set<Device> busDevices;
private Map<Device, Set<UUID>> deviceIdentifiers;
private DeviceBusController controller;
@BeforeEach
public void setupEach() {
adapter = new RPCDeviceBusAdapter(mock(SerialDevice.class));
busDevices = new HashSet<>();
deviceIdentifiers = new HashMap<>();
controller = mock(DeviceBusController.class);
when(controller.getDevices()).thenReturn(busDevices);
when(controller.getDeviceIdentifiers(any())).then(invocation -> deviceIdentifiers.get((Device) invocation.getArgument(0)));
}
@Test
public void resumeDoesNotMountDirectly() {
final RPCDevice device1 = addDevice();
adapter.resume(controller, true);
verify(device1, never()).mount();
}
@Test
public void emptyDevicesAreNotMounted() {
final RPCDevice device = addEmptyDevice();
adapter.resume(controller, true);
adapter.mountDevices();
verify(device, never()).mount();
}
@Test
public void addedDevicesHaveMountCalled() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.mountDevices();
verify(device).mount();
}
@Test
public void mountedDevicesAreUnmountedWhenRemoved() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.mountDevices();
removeDevice(device);
adapter.resume(controller, true);
verify(device).unmount();
verify(device, never()).dispose();
}
@Test
public void unmountedDevicesAreSilentlyRemoved() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
removeDevice(device);
adapter.resume(controller, true);
verify(device, never()).unmount();
verify(device, never()).dispose();
}
@Test
public void mountedDevicesAreUnmountedButNotDisposedOnGlobalUnmount() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.mountDevices();
adapter.unmountDevices();
verify(device).unmount();
verify(device, never()).dispose();
}
@Test
public void unmountedDevicesAreNotUnmountedAndNotDisposedOnGlobalUnmount() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.unmountDevices();
verify(device, never()).unmount();
verify(device, never()).dispose();
}
@Test
public void mountedDevicesAreUnmountedAndDisposedOnGlobalDispose() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.mountDevices();
adapter.disposeDevices();
verify(device).unmount();
verify(device).dispose();
}
@Test
public void unmountedDevicesAreNotUnmountedButDisposedOnGlobalDispose() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.disposeDevices();
verify(device, never()).unmount();
verify(device).dispose();
}
@Test
public void devicesHaveMountCalledAfterGlobalUnmount() {
final RPCDevice device = addDevice();
adapter.resume(controller, true);
adapter.mountDevices();
adapter.unmountDevices();
adapter.mountDevices();
verify(device, times(2)).mount();
}
@Test
public void deviceListIsStable() {
final RPCDevice device1 = mock(RPCDevice.class);
final RPCDevice device2 = mock(RPCDevice.class);
final RPCDevice listDevice = new RPCDeviceList(new ArrayList<>(Arrays.asList(device1, device2)));
when(device1.getMethodGroups()).thenReturn(Collections.singletonList(mock(RPCMethod.class)));
when(device2.getMethodGroups()).thenReturn(Collections.singletonList(mock(RPCMethod.class)));
addDevice(listDevice);
adapter.resume(controller, true);
verify(device1, never()).mount();
verify(device2, never()).mount();
adapter.mountDevices();
verify(device1).mount();
verify(device2).mount();
adapter.resume(controller, true);
verify(device1, never()).unmount();
verify(device2, never()).unmount();
adapter.mountDevices();
verify(device1, atMostOnce()).mount();
verify(device2, atMostOnce()).mount();
}
private RPCDevice addEmptyDevice() {
final RPCDevice device = mock(RPCDevice.class);
addDevice(device);
return device;
}
private RPCDevice addDevice() {
final RPCDevice device = mock(RPCDevice.class);
when(device.getMethodGroups()).thenReturn(Collections.singletonList(mock(RPCMethod.class)));
addDevice(device);
return device;
}
private void addDevice(final Device device, UUID... identifiers) {
if (identifiers.length == 0) {
identifiers = new UUID[]{UUID.randomUUID()};
}
busDevices.add(device);
deviceIdentifiers.put(device, new HashSet<>(Arrays.asList(identifiers)));
}
private void removeDevice(final Device device) {
busDevices.remove(device);
deviceIdentifiers.remove(device);
}
}

View File

@@ -1,289 +0,0 @@
package li.cil.oc2.common.bus;
import com.google.gson.*;
import it.unimi.dsi.fastutil.bytes.ByteArrayFIFOQueue;
import li.cil.oc2.api.bus.DeviceBusController;
import li.cil.oc2.api.bus.device.object.Callback;
import li.cil.oc2.api.bus.device.object.ObjectDevice;
import li.cil.oc2.api.bus.device.object.Parameter;
import li.cil.oc2.api.bus.device.rpc.*;
import li.cil.sedna.api.device.serial.SerialDevice;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import javax.annotation.Nullable;
import java.io.ByteArrayOutputStream;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import static java.util.Collections.singleton;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class RPCMethodTests {
private static final UUID DEVICE_UUID = java.util.UUID.randomUUID();
private TestSerialDevice serialDevice;
private DeviceBusController busController;
private RPCDeviceBusAdapter rpcAdapter;
@BeforeEach
public void setupEach() {
serialDevice = new TestSerialDevice();
busController = mock(DeviceBusController.class);
rpcAdapter = new RPCDeviceBusAdapter(serialDevice);
}
@Test
public void resetAndReadDescriptor() {
final VoidIntMethod method = new VoidIntMethod();
final TestRPCDevice device = new TestRPCDevice(method);
setDevice(device, DEVICE_UUID);
final JsonObject request = new JsonObject();
request.addProperty("type", "list");
serialDevice.putAsVM(request.toString());
rpcAdapter.step(0); // process message
final String message = serialDevice.readMessageAsVM();
assertNotNull(message);
final JsonObject json = JsonParser.parseString(message).getAsJsonObject();
final JsonArray devicesJson = json.getAsJsonArray("data");
assertEquals(1, devicesJson.size());
final JsonObject deviceJson = devicesJson.get(0).getAsJsonObject();
assertNotNull(deviceJson.get("deviceId"));
assertNotNull(deviceJson.get("typeNames"));
}
@Test
public void simpleMethod() {
final VoidIntMethod method = new VoidIntMethod();
final TestRPCDevice device = new TestRPCDevice(method);
setDevice(device, DEVICE_UUID);
invokeMethod(DEVICE_UUID, method.getName(), 0xdeadbeef);
assertEquals(0xdeadbeef, method.passedValue);
}
@Test
public void returningMethod() {
final IntLongMethod method = new IntLongMethod();
final TestRPCDevice device = new TestRPCDevice(method);
setDevice(device, DEVICE_UUID);
final JsonElement result = invokeMethod(DEVICE_UUID, method.getName(), 0xdeadbeefcafebabeL);
assertNotNull(result);
assertTrue(result.isJsonPrimitive());
assertEquals(0xcafebabe, result.getAsInt());
}
@Test
public void annotatedObject() {
final SimpleObject object = new SimpleObject();
final ObjectDevice device = new ObjectDevice(object);
setDevice(device, DEVICE_UUID);
assertEquals(42 + 23, invokeMethod(DEVICE_UUID, "add", 42, 23).getAsInt());
}
@Test
public void customDeviceGroupRejectsInvalidParameters() {
final RPCDevice device = mock(RPCDevice.class);
when(device.getTypeNames()).thenReturn(Collections.singletonList("test"));
when(device.getMethodGroups()).thenReturn(Collections.singletonList(new CustomMethodGroup()));
setDevice(device, DEVICE_UUID);
assertEquals("error", invokeMethodRaw(DEVICE_UUID, "test", "invalid", 123).get("type").getAsString());
}
@Test
public void customDeviceGroupAcceptsValidParameters() {
final RPCDevice device = mock(RPCDevice.class);
when(device.getTypeNames()).thenReturn(Collections.singletonList("test"));
when(device.getMethodGroups()).thenReturn(Collections.singletonList(new CustomMethodGroup()));
setDevice(device, DEVICE_UUID);
assertEquals(42, invokeMethod(DEVICE_UUID, "test", 123, "valid").getAsInt());
}
private void setDevice(final RPCDevice device, final UUID deviceId) {
when(busController.getDevices()).thenReturn(singleton(device));
when(busController.getDeviceIdentifiers(device)).thenReturn(singleton(deviceId));
// trigger device cache rebuild
rpcAdapter.resume(busController, true);
}
private JsonObject invokeMethodRaw(final UUID deviceId, final String name, final Object... parameters) {
final JsonObject request = new JsonObject();
request.addProperty("type", "invoke");
final JsonObject methodInvocation = new JsonObject();
methodInvocation.addProperty("deviceId", deviceId.toString());
methodInvocation.addProperty("name", name);
final JsonArray parametersJson = new JsonArray();
methodInvocation.add("parameters", parametersJson);
for (final Object parameter : parameters) {
parametersJson.add(new Gson().toJsonTree(parameter));
}
request.add("data", methodInvocation);
serialDevice.putAsVM(request.toString());
rpcAdapter.step(0);
final String result = serialDevice.readMessageAsVM();
assertNotNull(result);
return JsonParser.parseString(result).getAsJsonObject();
}
private JsonElement invokeMethod(final UUID deviceId, final String name, final Object... parameters) {
final JsonObject resultJson = invokeMethodRaw(deviceId, name, parameters);
assertEquals("result", resultJson.get("type").getAsString());
return resultJson.get("data");
}
private static final class VoidIntMethod extends AbstractTestMethod {
public int passedValue;
VoidIntMethod() {
super(void.class, int.class);
}
@Override
public Object invoke(final Object... parameters) {
passedValue = (int) parameters[0];
return 0;
}
}
private static final class IntLongMethod extends AbstractTestMethod {
public long passedValue;
IntLongMethod() {
super(int.class, long.class);
}
@Override
public Object invoke(final Object... parameters) {
passedValue = (long) parameters[0];
return (int) passedValue;
}
}
private static final class CustomMethodGroup implements RPCMethodGroup {
@Override
public String getName() {
return "test";
}
@Override
public Optional<RPCMethod> findOverload(final RPCInvocation invocation) {
final JsonArray parameters = invocation.getParameters();
if (parameters.size() != 2)
return Optional.empty();
if (!parameters.get(0).isJsonPrimitive() || !parameters.get(0).getAsJsonPrimitive().isNumber())
return Optional.empty();
if (!parameters.get(1).isJsonPrimitive() || !parameters.get(1).getAsJsonPrimitive().isString())
return Optional.empty();
return Optional.of(new AbstractRPCMethod("test", int.class, () -> int.class, () -> String.class) {
@Override
protected Object invoke(final Object... parameters) {
return 42;
}
});
}
}
public static final class SimpleObject {
@Callback(synchronize = false)
public int add(@Parameter("a") final int a,
@Parameter("b") final int b) {
return a + b;
}
@Callback(synchronize = false)
public int div(@Parameter("a") final long a,
@Parameter("b") final long b) {
return (int) (a / b);
}
}
private static final class TestSerialDevice implements SerialDevice {
private final ByteArrayFIFOQueue transmit = new ByteArrayFIFOQueue();
private final ByteArrayFIFOQueue receive = new ByteArrayFIFOQueue();
public void putAsVM(final String data) {
final byte[] bytes = data.getBytes();
for (int i = 0; i < bytes.length; i++) {
transmit.enqueue(bytes[i]);
}
transmit.enqueue((byte) 0);
}
@Nullable
public String readMessageAsVM() {
final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
while (!receive.isEmpty()) {
final byte value = receive.dequeueByte();
if (value == 0) {
if (bytes.size() == 0) {
continue;
} else {
break;
}
}
bytes.write(value);
}
if (bytes.size() > 0) {
return bytes.toString();
} else {
return null;
}
}
@Override
public int read() {
return transmit.isEmpty() ? -1 : transmit.dequeueByte();
}
@Override
public boolean canPutByte() {
return true;
}
@Override
public void putByte(final byte value) {
receive.enqueue(value);
}
}
private static final class TestRPCDevice implements RPCDevice {
private final RPCMethod method;
public TestRPCDevice(final RPCMethod method) {
this.method = method;
}
@Override
public List<String> getTypeNames() {
return singletonList(getClass().getSimpleName());
}
@Override
public List<RPCMethodGroup> getMethodGroups() {
return singletonList(method);
}
}
}

View File

@@ -1,386 +0,0 @@
package li.cil.oc2.common.bus;
import li.cil.oc2.api.bus.device.vm.VMDevice;
import li.cil.oc2.api.bus.device.vm.VMDeviceLoadResult;
import li.cil.oc2.api.bus.device.vm.context.VMContext;
import li.cil.oc2.common.vm.VMDeviceBusAdapter;
import li.cil.oc2.common.vm.context.global.GlobalVMContext;
import li.cil.sedna.api.Board;
import li.cil.sedna.api.device.InterruptController;
import li.cil.sedna.api.device.MemoryMappedDevice;
import li.cil.sedna.api.memory.MemoryMap;
import li.cil.sedna.api.memory.MemoryRangeAllocationStrategy;
import li.cil.sedna.memory.SimpleMemoryMap;
import li.cil.sedna.riscv.R5MemoryRangeAllocationStrategy;
import li.cil.sedna.riscv.device.R5PlatformLevelInterruptController;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.util.Collections;
import java.util.OptionalInt;
import java.util.OptionalLong;
import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.*;
public final class VMDeviceBusAdapterTests {
private MemoryMap memoryMap;
private InterruptController interruptController;
private R5MemoryRangeAllocationStrategy allocationStrategy;
private GlobalVMContext context;
private VMDeviceBusAdapter adapter;
@BeforeEach
public void setupEach() {
memoryMap = new SimpleMemoryMap();
interruptController = new R5PlatformLevelInterruptController();
allocationStrategy = new R5MemoryRangeAllocationStrategy();
final Board board = mock(Board.class);
when(board.getMemoryMap()).thenReturn(memoryMap);
when(board.getInterruptController()).thenReturn(interruptController);
when(board.getInterruptCount()).thenReturn(16);
when(board.addDevice(any())).then(invocation -> {
final MemoryMappedDevice device = invocation.getArgument(0);
final OptionalLong address = allocationStrategy.findMemoryRange(device, MemoryRangeAllocationStrategy.getMemoryMapIntersectionProvider(memoryMap));
if (address.isPresent() && memoryMap.addDevice(address.getAsLong(), device)) {
return address;
}
return OptionalLong.empty();
});
doAnswer(invocation -> {
memoryMap.removeDevice(invocation.getArgument(0));
return null;
}).when(board).removeDevice(any());
context = new GlobalVMContext(board);
adapter = new VMDeviceBusAdapter(context);
}
@Test
public void addingDeviceDoesNotMountDirectly() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
verify(device, never()).mount(any());
}
@Test
public void addedDevicesHaveMountCalled() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
verify(device).mount(any());
}
@Test
public void existingDevicesDoNotHaveMountCalledAgain() {
final VMDevice device1 = mock(VMDevice.class);
final VMDevice device2 = mock(VMDevice.class);
when(device1.mount(any())).thenReturn(VMDeviceLoadResult.success());
when(device2.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device1));
adapter.mountDevices();
verify(device1).mount(any());
adapter.addDevices(Collections.singleton(device2));
adapter.mountDevices();
verifyNoMoreInteractions(device1);
}
@Test
public void deviceFailingMountDoesNotHaveUnmountOrDisposeCalled() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.fail());
adapter.addDevices(Collections.singleton(device));
assertFalse(adapter.mountDevices().wasSuccessful());
verify(device).mount(any());
verify(device, never()).unmount();
verify(device, never()).dispose();
}
@Test
public void mountedDevicesAreUnmountedIfOtherMountFails() {
final VMDevice device1 = mock(VMDevice.class);
final VMDevice device2 = mock(VMDevice.class);
when(device1.mount(any())).thenReturn(VMDeviceLoadResult.success());
when(device2.mount(any())).thenReturn(VMDeviceLoadResult.fail());
adapter.addDevices(Collections.singleton(device1));
adapter.addDevices(Collections.singleton(device2));
adapter.mountDevices();
verify(device1).mount(any());
verify(device2).mount(any());
verify(device1).unmount();
verify(device1, never()).dispose();
}
@Test
public void mountedDevicesAreUnmountedWhenRemoved() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
adapter.removeDevices(Collections.singleton(device));
verify(device).unmount();
verify(device, never()).dispose();
}
@Test
public void unmountedDevicesAreSilentlyRemoved() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
adapter.mountDevices();
verify(device).mount(any());
adapter.unmountDevices();
verify(device).unmount();
adapter.removeDevices(Collections.singleton(device));
verify(device, never()).dispose();
}
@Test
public void mountedDevicesAreUnmountedButNotDisposedOnGlobalUnmount() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
adapter.unmountDevices();
verify(device).unmount();
verify(device, never()).dispose();
}
@Test
public void unmountedDevicesAreNotUnmountedAndNotDisposedOnGlobalUnmount() {
final VMDevice device = mock(VMDevice.class);
adapter.addDevices(Collections.singleton(device));
adapter.unmountDevices();
verify(device, never()).unmount();
verify(device, never()).dispose();
}
@Test
public void mountedDevicesAreUnmountedAndDisposedOnGlobalDispose() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
adapter.mountDevices();
adapter.disposeDevices();
verify(device).unmount();
verify(device).dispose();
}
@Test
public void unmountedDevicesAreNotUnmountedButDisposedOnGlobalDispose() {
final VMDevice device = mock(VMDevice.class);
adapter.addDevices(Collections.singleton(device));
adapter.disposeDevices();
verify(device, never()).unmount();
verify(device).dispose();
}
@Test
public void devicesHaveMountCalledAfterGlobalUnmount() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenReturn(VMDeviceLoadResult.success());
adapter.addDevices(Collections.singleton(device));
adapter.mountDevices();
adapter.unmountDevices();
assertTrue(adapter.mountDevices().wasSuccessful());
verify(device, times(2)).mount(any());
}
@Test
public void deviceCanClaimInterrupts() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
final VMContext context = invocation.getArgument(0);
final OptionalInt interrupt = context.getInterruptAllocator().claimInterrupt();
assertTrue(interrupt.isPresent());
return VMDeviceLoadResult.success();
});
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
verify(device).mount(any());
}
@Test
public void deviceCannotClaimClaimedInterrupts() {
final int claimedInterrupt = 1;
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
final VMContext context = invocation.getArgument(0);
final boolean result = context.getInterruptAllocator().claimInterrupt(claimedInterrupt);
assertFalse(result);
return VMDeviceLoadResult.success();
});
context.getInterruptAllocator().claimInterrupt(claimedInterrupt);
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
}
@Test
public void deviceCanRaiseClaimedInterrupts() {
final DeviceData deviceData = new DeviceData();
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
final VMContext context = invocation.getArgument(0);
final OptionalInt interrupt = context.getInterruptAllocator().claimInterrupt();
assertTrue(interrupt.isPresent());
deviceData.context = context;
deviceData.interrupt = interrupt.getAsInt();
return VMDeviceLoadResult.success();
});
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
final int claimedInterruptMask = 1 << deviceData.interrupt;
deviceData.context.getInterruptController().raiseInterrupts(claimedInterruptMask);
assertTrue((interruptController.getRaisedInterrupts() & claimedInterruptMask) != 0);
}
@Test
public void devicesCannotRaiseUnclaimedInterrupts() {
final DeviceData deviceData = new DeviceData();
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
deviceData.context = invocation.getArgument(0);
return VMDeviceLoadResult.success();
});
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
final int someInterruptMask = 0x1;
assertThrows(IllegalArgumentException.class, () ->
deviceData.context.getInterruptController().raiseInterrupts(someInterruptMask));
}
@Test
public void unmountLowersClaimedInterrupts() {
final DeviceData deviceData = new DeviceData();
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
final VMContext context = invocation.getArgument(0);
final OptionalInt interrupt = context.getInterruptAllocator().claimInterrupt();
assertTrue(interrupt.isPresent());
deviceData.context = context;
deviceData.interrupt = interrupt.getAsInt();
return VMDeviceLoadResult.success();
});
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
final int claimedInterruptMask = 1 << deviceData.interrupt;
deviceData.context.getInterruptController().raiseInterrupts(claimedInterruptMask);
assertTrue((interruptController.getRaisedInterrupts() & claimedInterruptMask) != 0);
adapter.unmountDevices();
assertFalse((interruptController.getRaisedInterrupts() & claimedInterruptMask) != 0);
}
@Test
public void devicesCannotAddToMemoryMapDirectly() {
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
final VMContext context = invocation.getArgument(0);
assertThrows(UnsupportedOperationException.class, () ->
context.getMemoryMap().addDevice(0, mock(MemoryMappedDevice.class)));
return VMDeviceLoadResult.success();
});
adapter.addDevices(Collections.singleton(device));
adapter.mountDevices();
}
@Test
public void devicesCanAddMemoryMappedDevices() {
final DeviceData deviceData = new DeviceData();
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
final VMContext context = invocation.getArgument(0);
deviceData.context = context;
deviceData.device = mock(MemoryMappedDevice.class);
when(deviceData.device.getLength()).thenReturn(0x1000);
assertTrue(context.getMemoryRangeAllocator().claimMemoryRange(deviceData.device).isPresent());
return VMDeviceLoadResult.success();
});
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
assertTrue(deviceData.context.getMemoryMap().getMemoryRange(deviceData.device).isPresent());
}
@Test
public void addedDevicesGetRemovedOnUnmount() {
final DeviceData deviceData = new DeviceData();
final VMDevice device = mock(VMDevice.class);
when(device.mount(any())).thenAnswer(invocation -> {
final VMContext context = invocation.getArgument(0);
deviceData.context = context;
deviceData.device = mock(MemoryMappedDevice.class);
when(deviceData.device.getLength()).thenReturn(0x1000);
assertTrue(context.getMemoryRangeAllocator().claimMemoryRange(deviceData.device).isPresent());
return VMDeviceLoadResult.success();
});
adapter.addDevices(Collections.singleton(device));
assertTrue(adapter.mountDevices().wasSuccessful());
assertTrue(deviceData.context.getMemoryMap().getMemoryRange(deviceData.device).isPresent());
adapter.unmountDevices();
assertFalse(deviceData.context.getMemoryMap().getMemoryRange(deviceData.device).isPresent());
}
private static final class DeviceData {
public VMContext context;
public int interrupt;
public MemoryMappedDevice device;
}
}

View File

@@ -1,7 +0,0 @@
@ParametersAreNonnullByDefault
@MethodsReturnNonnullByDefault
package li.cil.oc2.common.bus;
import net.minecraft.MethodsReturnNonnullByDefault;
import javax.annotation.ParametersAreNonnullByDefault;

View File

@@ -1,200 +0,0 @@
package li.cil.oc2.common.serialization;
import li.cil.ceres.api.Serialized;
import net.minecraft.nbt.CompoundTag;
import org.junit.jupiter.api.Test;
import java.util.UUID;
import static org.junit.jupiter.api.Assertions.*;
public final class SerializationTests {
@Test
public void testSerializeFlat() {
final Flat value = new Flat();
final UUID uuid = UUID.randomUUID();
value.byteValue = 123;
value.shortValue = 234;
value.intValue = 456;
value.longValue = 567;
value.floatValue = 678.9f;
value.doubleValue = 789.0;
value.byteArrayValue = new byte[]{1, 2, 3};
value.intArrayValue = new int[]{4, 5, 6};
value.longArrayValue = new long[]{7, 8, 9};
value.stringValue = "test string";
value.uuidValue = uuid;
final CompoundTag nbt = assertDoesNotThrow(() -> NBTSerialization.serialize(value));
assertEquals(123, nbt.getByte("byteValue"));
assertEquals(234, nbt.getShort("shortValue"));
assertEquals(456, nbt.getInt("intValue"));
assertEquals(567, nbt.getLong("longValue"));
assertEquals(678.9f, nbt.getFloat("floatValue"));
assertEquals(789.0, nbt.getDouble("doubleValue"));
assertArrayEquals(new byte[]{1, 2, 3}, nbt.getByteArray("byteArrayValue"));
assertArrayEquals(new int[]{4, 5, 6}, nbt.getIntArray("intArrayValue"));
assertArrayEquals(new long[]{7, 8, 9}, nbt.getLongArray("longArrayValue"));
assertEquals("test string", nbt.getString("stringValue"));
assertEquals(uuid, nbt.getCompound("uuidValue").getUUID("uuidValue"));
}
@Test
public void testDeserializeFlatInto() {
final CompoundTag nbt = new CompoundTag();
nbt.putByte("byteValue", (byte) 98);
nbt.putShort("shortValue", (short) 876);
nbt.putInt("intValue", 765);
nbt.putLong("longValue", 654);
nbt.putFloat("floatValue", 543.2f);
nbt.putDouble("doubleValue", 432.1);
nbt.putByteArray("byteArrayValue", new byte[]{9, 8, 7});
nbt.putIntArray("intArrayValue", new int[]{8, 7, 6});
nbt.putLongArray("longArrayValue", new long[]{7, 6, 5});
nbt.putString("stringValue", "another test");
final UUID uuid = UUID.randomUUID();
final CompoundTag uuidNBT = new CompoundTag();
uuidNBT.putUUID("uuidValue", uuid);
nbt.put("uuidValue", uuidNBT);
final Flat value = assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Flat.class, new Flat()));
assertEquals(98, value.byteValue);
assertEquals(876, value.shortValue);
assertEquals(765, value.intValue);
assertEquals(654, value.longValue);
assertEquals(543.2f, value.floatValue);
assertEquals(432, .1, value.doubleValue);
assertArrayEquals(new byte[]{9, 8, 7}, value.byteArrayValue);
assertArrayEquals(new int[]{8, 7, 6}, value.intArrayValue);
assertArrayEquals(new long[]{7, 6, 5}, value.longArrayValue);
assertEquals("another test", value.stringValue);
assertEquals(uuid, value.uuidValue);
}
@Test
public void testDeserializeFlatNew() {
final CompoundTag nbt = new CompoundTag();
nbt.putByte("byteValue", (byte) 98);
nbt.putShort("shortValue", (short) 876);
nbt.putInt("intValue", 765);
nbt.putLong("longValue", 654);
nbt.putFloat("floatValue", 543.2f);
nbt.putDouble("doubleValue", 432.1);
nbt.putByteArray("byteArrayValue", new byte[]{9, 8, 7});
nbt.putIntArray("intArrayValue", new int[]{8, 7, 6});
nbt.putLongArray("longArrayValue", new long[]{7, 6, 5});
nbt.putString("stringValue", "another test");
final UUID uuid = UUID.randomUUID();
final CompoundTag uuidNBT = new CompoundTag();
uuidNBT.putUUID("uuidValue", uuid);
nbt.put("uuidValue", uuidNBT);
final Flat value = assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Flat.class, null));
assertEquals(98, value.byteValue);
assertEquals(876, value.shortValue);
assertEquals(765, value.intValue);
assertEquals(654, value.longValue);
assertEquals(543.2f, value.floatValue);
assertEquals(432, .1, value.doubleValue);
assertArrayEquals(new byte[]{9, 8, 7}, value.byteArrayValue);
assertArrayEquals(new int[]{8, 7, 6}, value.intArrayValue);
assertArrayEquals(new long[]{7, 6, 5}, value.longArrayValue);
assertEquals("another test", value.stringValue);
assertEquals(uuid, value.uuidValue);
}
@Test
public void testModifiers() {
final WithModifiers value = new WithModifiers();
final CompoundTag nbt = assertDoesNotThrow(() -> NBTSerialization.serialize(value));
assertTrue(nbt.contains("nonTransientInt"));
assertEquals(123, nbt.getInt("nonTransientInt"));
assertFalse(nbt.contains("transientInt"));
assertFalse(nbt.contains("finalInt"));
nbt.putIntArray("finalIntArray", new int[]{8, 7, 6});
assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, value));
assertArrayEquals(new int[]{8, 7, 6}, value.finalIntArray);
}
@Test
public void testSerializeNested() {
final Nested root = new Nested();
root.value = 123;
root.child = new Nested();
root.child.value = 234;
final CompoundTag nbt = assertDoesNotThrow(() -> NBTSerialization.serialize(root));
assertEquals(123, nbt.getInt("value"));
assertTrue(nbt.contains("child"));
assertEquals(234, nbt.getCompound("child").getInt("value"));
}
@Test
public void testDeserializeNestedInto() {
final CompoundTag nbt = new CompoundTag();
nbt.putInt("value", 123);
final CompoundTag child = new CompoundTag();
nbt.put("child", child);
child.putInt("value", 234);
final Nested value = assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Nested.class, new Nested()));
assertEquals(123, value.value);
assertEquals(234, value.child.value);
assertNull(value.child.child);
}
@Test
public void testDeserializeNestedNew() {
final CompoundTag nbt = new CompoundTag();
nbt.putInt("value", 123);
final CompoundTag child = new CompoundTag();
nbt.put("child", child);
child.putInt("value", 234);
final Nested value = assertDoesNotThrow(() -> NBTSerialization.deserialize(nbt, Nested.class, null));
assertEquals(123, value.value);
assertEquals(234, value.child.value);
assertNull(value.child.child);
}
@Serialized
private static final class Flat {
private byte byteValue;
private short shortValue;
private int intValue;
private long longValue;
private float floatValue;
private double doubleValue;
private byte[] byteArrayValue;
private int[] intArrayValue;
private long[] longArrayValue;
private String stringValue;
private UUID uuidValue;
}
@Serialized
private static final class WithModifiers {
private int nonTransientInt = 123;
private transient int transientInt = 345;
private final int finalInt = 678;
private final int[] finalIntArray = {4, 5, 6};
}
@Serialized
private static final class Nested {
private int value;
private Nested child;
}
}