1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-10-31 21:52:59 +00:00

Update to MC 1.20.6

- Update EMI and REI integration, and fix some issues with the upgrade
   crafting hooks.
 - Just use smooth stone for recipes, not #c:stone. We're mirroring
   redstone's crafting recipes here.
 - Some cleanup to printouts.
 - Remote upgrade data generators - these can be replaced with the
   standard registry data generators.
 - Remove the API's PlatformHelper - we no longer have any
   platform-specific code in the API.
This commit is contained in:
Jonathan Coates
2024-05-07 22:58:25 +01:00
parent 94c864759d
commit 2c0d8263d3
70 changed files with 513 additions and 822 deletions

View File

@@ -6,12 +6,15 @@ package dan200.computercraft.client.integration.emi;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.integration.RecipeModHelpers;
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
import dan200.computercraft.shared.turtle.items.TurtleItem;
import dev.emi.emi.api.EmiEntrypoint;
import dev.emi.emi.api.EmiPlugin;
import dev.emi.emi.api.EmiRegistry;
import dev.emi.emi.api.stack.Comparison;
import dev.emi.emi.api.stack.EmiStack;
import net.minecraft.client.Minecraft;
import net.minecraft.world.item.ItemStack;
import java.util.function.BiPredicate;
@@ -25,6 +28,10 @@ public class EMIComputerCraft implements EmiPlugin {
registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_NORMAL.get(), pocketComparison);
registry.setDefaultComparison(ModRegistry.Items.POCKET_COMPUTER_ADVANCED.get(), pocketComparison);
for (var stack : RecipeModHelpers.getExtraStacks(Minecraft.getInstance().level.registryAccess())) {
registry.addEmiStack(EmiStack.of(stack));
}
}
private static final Comparison turtleComparison = compareStacks((left, right)

View File

@@ -11,14 +11,12 @@ import dan200.computercraft.api.turtle.ITurtleAccess;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleSide;
import dan200.computercraft.api.upgrades.UpgradeType;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.impl.UpgradeManager;
import dan200.computercraft.shared.util.RegistryHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.core.component.DataComponentPatch;
import net.minecraft.resources.ResourceLocation;
import java.util.Map;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Stream;
@@ -32,14 +30,6 @@ public final class TurtleUpgradeModellers {
private static final Map<UpgradeType<? extends ITurtleUpgrade>, TurtleUpgradeModeller<?>> turtleModels = new ConcurrentHashMap<>();
private static volatile boolean fetchedModels;
/**
* In order to avoid a double lookup of {@link ITurtleUpgrade} to {@link UpgradeManager.UpgradeWrapper} to
* {@link TurtleUpgradeModeller}, we maintain a cache here.
* <p>
* Turtle upgrades may be removed as part of datapack reloads, so we use a weak map to avoid the memory leak.
*/
private static final WeakHashMap<ITurtleUpgrade, TurtleUpgradeModeller<?>> modelCache = new WeakHashMap<>();
private TurtleUpgradeModellers() {
}
@@ -57,20 +47,17 @@ public final class TurtleUpgradeModellers {
}
public static TransformedModel getModel(ITurtleUpgrade upgrade, ITurtleAccess access, TurtleSide side) {
@SuppressWarnings("unchecked")
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
return modeller.getModel(upgrade, access, side, access.getUpgradeData(side));
return getModeller(upgrade).getModel(upgrade, access, side, access.getUpgradeData(side));
}
public static TransformedModel getModel(ITurtleUpgrade upgrade, DataComponentPatch data, TurtleSide side) {
@SuppressWarnings("unchecked")
var modeller = (TurtleUpgradeModeller<ITurtleUpgrade>) modelCache.computeIfAbsent(upgrade, TurtleUpgradeModellers::getModeller);
return modeller.getModel(upgrade, null, side, data);
return getModeller(upgrade).getModel(upgrade, null, side, data);
}
private static TurtleUpgradeModeller<?> getModeller(ITurtleUpgrade upgrade) {
@SuppressWarnings("unchecked")
private static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> getModeller(T upgrade) {
var modeller = turtleModels.get(upgrade.getType());
return modeller == null ? NULL_TURTLE_MODELLER : modeller;
return (TurtleUpgradeModeller<T>) (modeller == null ? NULL_TURTLE_MODELLER : modeller);
}
public static Stream<ResourceLocation> getDependencies() {

View File

@@ -1,7 +1,7 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "R": {"tag": "c:dusts/redstone"}},
"key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}},
"pattern": [" # ", "#R#", " # "],
"result": {"count": 6, "id": "computercraft:cable"}
}

View File

@@ -1,7 +1,7 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "G": {"tag": "c:glass_panes"}, "R": {"tag": "c:dusts/redstone"}},
"key": {"#": {"item": "minecraft:stone"}, "G": {"tag": "c:glass_panes"}, "R": {"tag": "c:dusts/redstone"}},
"pattern": ["###", "#R#", "#G#"],
"result": {"count": 1, "id": "computercraft:computer_normal"}
}

View File

@@ -1,7 +1,7 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "R": {"tag": "c:dusts/redstone"}},
"key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}},
"pattern": ["###", "#R#", "#R#"],
"result": {"count": 1, "id": "computercraft:disk_drive"}
}

View File

@@ -1,7 +1,7 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "G": {"tag": "c:glass_panes"}},
"key": {"#": {"item": "minecraft:stone"}, "G": {"tag": "c:glass_panes"}},
"pattern": ["###", "#G#", "###"],
"result": {"count": 1, "id": "computercraft:monitor_normal"}
}

View File

@@ -1,7 +1,11 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "A": {"item": "minecraft:golden_apple"}, "G": {"tag": "c:glass_panes"}},
"key": {
"#": {"item": "minecraft:stone"},
"A": {"item": "minecraft:golden_apple"},
"G": {"tag": "c:glass_panes"}
},
"pattern": ["###", "#A#", "#G#"],
"result": {"count": 1, "id": "computercraft:pocket_computer_normal"}
}

View File

@@ -1,7 +1,7 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "D": {"tag": "c:dyes"}, "R": {"tag": "c:dusts/redstone"}},
"key": {"#": {"item": "minecraft:stone"}, "D": {"tag": "c:dyes"}, "R": {"tag": "c:dusts/redstone"}},
"pattern": ["###", "#R#", "#D#"],
"result": {"count": 1, "id": "computercraft:printer"}
}

View File

@@ -1,7 +1,11 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "N": {"item": "minecraft:note_block"}, "R": {"tag": "c:dusts/redstone"}},
"key": {
"#": {"item": "minecraft:stone"},
"N": {"item": "minecraft:note_block"},
"R": {"tag": "c:dusts/redstone"}
},
"pattern": ["###", "#N#", "#R#"],
"result": {"count": 1, "id": "computercraft:speaker"}
}

View File

@@ -1,7 +1,7 @@
{
"type": "minecraft:crafting_shaped",
"category": "redstone",
"key": {"#": {"tag": "c:stones"}, "R": {"tag": "c:dusts/redstone"}},
"key": {"#": {"item": "minecraft:stone"}, "R": {"tag": "c:dusts/redstone"}},
"pattern": ["###", "#R#", "###"],
"result": {"count": 1, "id": "computercraft:wired_modem"}
}

View File

@@ -5,7 +5,9 @@
package dan200.computercraft.data;
import com.mojang.serialization.Codec;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import net.minecraft.Util;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.RegistrySetBuilder;
import net.minecraft.data.DataProvider;
@@ -20,7 +22,6 @@ import net.minecraft.world.level.block.Block;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Consumer;
/**
@@ -32,25 +33,25 @@ public final class DataProviders {
}
public static void add(GeneratorSink generator) {
var turtleUpgrades = generator.add(TurtleUpgradeProvider::new);
var pocketUpgrades = generator.add(PocketUpgradeProvider::new);
var fullRegistryPatch = RegistryPatchGenerator.createLookup(
generator.registries(),
Util.make(new RegistrySetBuilder(), builder -> {
builder.add(ITurtleUpgrade.REGISTRY, TurtleUpgradeProvider::addUpgrades);
builder.add(IPocketUpgrade.REGISTRY, PocketUpgradeProvider::addUpgrades);
}));
var fullRegistries = fullRegistryPatch.thenApply(RegistrySetBuilder.PatchedRegistries::full);
generator.add((out, registries) -> {
var builder = new RegistrySetBuilder();
builder.add(ModRegistry.TURTLE_UPGRADE, bs -> turtleUpgrades.getGeneratedUpgrades().forEach(bs::register));
builder.add(ModRegistry.POCKET_UPGRADE, bs -> pocketUpgrades.getGeneratedUpgrades().forEach(bs::register));
return new RecipeProvider(out, generator.createPatchedRegistries(registries, builder).thenApply(RegistrySetBuilder.PatchedRegistries::full));
});
generator.registries(fullRegistryPatch);
generator.add(out -> new RecipeProvider(out, fullRegistries));
var blockTags = generator.blockTags(TagProvider::blockTags);
generator.itemTags(TagProvider::itemTags, blockTags);
generator.add((out, registries) -> new net.minecraft.data.loot.LootTableProvider(out, Set.of(), LootTableProvider.getTables(), registries));
generator.add(out -> new net.minecraft.data.loot.LootTableProvider(out, Set.of(), LootTableProvider.getTables(), fullRegistries));
generator.add(out -> new ModelProvider(out, BlockModelProvider::addBlockModels, ItemModelProvider::addItemModels));
generator.add(out -> new LanguageProvider(out, turtleUpgrades, pocketUpgrades));
generator.add(out -> new LanguageProvider(out, fullRegistries));
// Unfortunately we rely on some client-side classes in this code. We just load in the client side data provider
// and invoke that.
@@ -63,9 +64,9 @@ public final class DataProviders {
}
public interface GeneratorSink {
<T extends DataProvider> T add(DataProvider.Factory<T> factory);
CompletableFuture<HolderLookup.Provider> registries();
<T extends DataProvider> T add(BiFunction<PackOutput, CompletableFuture<HolderLookup.Provider>, T> factory);
<T extends DataProvider> T add(DataProvider.Factory<T> factory);
<T> void addFromCodec(String name, PackType type, String directory, Codec<T> codec, Consumer<BiConsumer<ResourceLocation, T>> output);
@@ -74,16 +75,10 @@ public final class DataProviders {
TagsProvider<Item> itemTags(Consumer<TagProvider.ItemTagConsumer> tags, TagsProvider<Block> blocks);
/**
* Extend our registries with additional entries.
* Build new dynamic registries and save them to a pack.
*
* @param registries The existing registries.
* @param patch The new registries to apply.
* @return The built registries.
* @param registries The patched registries to write.
*/
default CompletableFuture<RegistrySetBuilder.PatchedRegistries> createPatchedRegistries(
CompletableFuture<HolderLookup.Provider> registries, RegistrySetBuilder patch
) {
return RegistryPatchGenerator.createLookup(registries, patch);
}
void registries(CompletableFuture<RegistrySetBuilder.PatchedRegistries> registries);
}
}

View File

@@ -7,8 +7,8 @@ package dan200.computercraft.data;
import com.google.gson.JsonObject;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.ComputerCraftTags;
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.core.metrics.Metric;
import dan200.computercraft.core.metrics.Metrics;
import dan200.computercraft.shared.ModRegistry;
@@ -17,6 +17,7 @@ import dan200.computercraft.shared.computer.metrics.basic.Aggregate;
import dan200.computercraft.shared.computer.metrics.basic.AggregatedMetric;
import dan200.computercraft.shared.config.ConfigFile;
import dan200.computercraft.shared.config.ConfigSpec;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.data.CachedOutput;
import net.minecraft.data.DataProvider;
@@ -34,27 +35,28 @@ import java.util.stream.Stream;
public final class LanguageProvider implements DataProvider {
private final PackOutput output;
private final TurtleUpgradeDataProvider turtleUpgrades;
private final PocketUpgradeDataProvider pocketUpgrades;
private final CompletableFuture<HolderLookup.Provider> registries;
private final Map<String, String> translations = new HashMap<>();
public LanguageProvider(PackOutput output, TurtleUpgradeDataProvider turtleUpgrades, PocketUpgradeDataProvider pocketUpgrades) {
public LanguageProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> registries) {
this.output = output;
this.turtleUpgrades = turtleUpgrades;
this.pocketUpgrades = pocketUpgrades;
this.registries = registries;
}
@Override
public CompletableFuture<?> run(CachedOutput cachedOutput) {
addTranslations();
getExpectedKeys().forEach(x -> {
if (!translations.containsKey(x)) throw new IllegalStateException("No translation for " + x);
});
var json = new JsonObject();
for (var pair : translations.entrySet()) json.addProperty(pair.getKey(), pair.getValue());
return DataProvider.saveStable(cachedOutput, json, output.getOutputFolder().resolve("assets/" + ComputerCraftAPI.MOD_ID + "/lang/en_us.json"));
return registries.thenCompose(registries -> {
getExpectedKeys(registries).forEach(x -> {
if (!translations.containsKey(x)) throw new IllegalStateException("No translation for " + x);
});
var json = new JsonObject();
for (var pair : translations.entrySet()) json.addProperty(pair.getKey(), pair.getValue());
return DataProvider.saveStable(cachedOutput, json, output.getOutputFolder().resolve("assets/" + ComputerCraftAPI.MOD_ID + "/lang/en_us.json"));
});
}
@Override
@@ -280,7 +282,7 @@ public final class LanguageProvider implements DataProvider {
addConfigEntry(ConfigSpec.uploadNagDelay, "Upload nag delay");
}
private Stream<String> getExpectedKeys() {
private Stream<String> getExpectedKeys(HolderLookup.Provider registries) {
return Stream.of(
BuiltInRegistries.BLOCK.holders()
.filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID))
@@ -288,8 +290,8 @@ public final class LanguageProvider implements DataProvider {
BuiltInRegistries.ITEM.holders()
.filter(x -> x.key().location().getNamespace().equals(ComputerCraftAPI.MOD_ID))
.map(x -> x.value().getDescriptionId()),
turtleUpgrades.getGeneratedUpgrades().values().stream().flatMap(x -> getTranslationKeys(x.getAdjective())),
pocketUpgrades.getGeneratedUpgrades().values().stream().flatMap(x -> getTranslationKeys(x.getAdjective())),
registries.lookupOrThrow(ITurtleUpgrade.REGISTRY).listElements().flatMap(x -> getTranslationKeys(x.value().getAdjective())),
registries.lookupOrThrow(IPocketUpgrade.REGISTRY).listElements().flatMap(x -> getTranslationKeys(x.value().getAdjective())),
Metric.metrics().values().stream().map(x -> AggregatedMetric.TRANSLATION_PREFIX + x.name() + ".name"),
ConfigSpec.serverSpec.entries().map(ConfigFile.Entry::translationKey),
ConfigSpec.clientSpec.entries().map(ConfigFile.Entry::translationKey),

View File

@@ -5,7 +5,7 @@
package dan200.computercraft.data;
import com.google.gson.JsonElement;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import net.minecraft.Util;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.data.CachedOutput;

View File

@@ -6,30 +6,23 @@ package dan200.computercraft.data;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.pocket.PocketUpgradeDataProvider;
import dan200.computercraft.shared.pocket.peripherals.PocketModem;
import dan200.computercraft.shared.pocket.peripherals.PocketSpeaker;
import net.minecraft.data.PackOutput;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import java.util.function.Consumer;
import static dan200.computercraft.shared.ModRegistry.Items;
class PocketUpgradeProvider extends PocketUpgradeDataProvider {
PocketUpgradeProvider(PackOutput output) {
super(output);
class PocketUpgradeProvider {
public static void addUpgrades(BootstrapContext<IPocketUpgrade> upgrades) {
upgrades.register(id("speaker"), new PocketSpeaker(new ItemStack(Items.SPEAKER.get())));
upgrades.register(id("wireless_modem_normal"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_NORMAL.get()), false));
upgrades.register(id("wireless_modem_advanced"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_ADVANCED.get()), true));
}
@Override
protected void addUpgrades(Consumer<Upgrade<IPocketUpgrade>> addUpgrade) {
upgrade(id("speaker"), new PocketSpeaker(new ItemStack(Items.SPEAKER.get()))).add(addUpgrade);
upgrade(id("wireless_modem_normal"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_NORMAL.get()), false)).add(addUpgrade);
upgrade(id("wireless_modem_advanced"), new PocketModem(new ItemStack(Items.WIRELESS_MODEM_ADVANCED.get()), true)).add(addUpgrade);
}
private static ResourceLocation id(String id) {
return new ResourceLocation(ComputerCraftAPI.MOD_ID, id);
private static ResourceKey<IPocketUpgrade> id(String id) {
return ResourceKey.create(IPocketUpgrade.REGISTRY, new ResourceLocation(ComputerCraftAPI.MOD_ID, id));
}
}

View File

@@ -8,11 +8,13 @@ import com.google.gson.JsonObject;
import com.mojang.authlib.GameProfile;
import com.mojang.serialization.JsonOps;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.upgrades.UpgradeData;
import dan200.computercraft.core.util.Colour;
import dan200.computercraft.data.recipe.ShapedSpecBuilder;
import dan200.computercraft.data.recipe.ShapelessSpecBuilder;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.common.ClearColourRecipe;
import dan200.computercraft.shared.common.ColourableRecipe;
@@ -54,14 +56,12 @@ import net.minecraft.world.item.crafting.CraftingBookCategory;
import net.minecraft.world.item.crafting.Ingredient;
import net.minecraft.world.item.crafting.Recipe;
import net.minecraft.world.level.ItemLike;
import net.minecraft.world.level.block.Blocks;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.function.Consumer;
import java.util.stream.Stream;
import static dan200.computercraft.api.ComputerCraftTags.Items.COMPUTER;
import static dan200.computercraft.api.ComputerCraftTags.Items.WIRED_MODEM;
@@ -119,7 +119,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.requires(Items.PAPER)
.requires(DyeItem.byColor(ofColour(colour)))
.group("computercraft:disk")
.unlockedBy("has_drive", inventoryChange(ModRegistry.Blocks.DISK_DRIVE.get()))
.unlockedBy("has_drive", inventoryChange(ModRegistry.Items.DISK_DRIVE.get()))
.build(ImpostorShapelessRecipe::new)
.save(output, new ResourceLocation(ComputerCraftAPI.MOD_ID, "disk_" + (colour.ordinal() + 1)));
}
@@ -139,7 +139,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
for (var turtleItem : turtleItems()) {
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, turtleItem);
registries.lookup(ModRegistry.TURTLE_UPGRADE).map(HolderLookup::listElements).orElse(Stream.empty()).forEach(upgradeHolder -> {
registries.lookupOrThrow(ITurtleUpgrade.REGISTRY).listElements().forEach(upgradeHolder -> {
var upgrade = upgradeHolder.value();
ShapedSpecBuilder
.shaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(turtleItem, ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(upgradeHolder)))
@@ -171,7 +171,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
for (var pocket : pocketComputerItems()) {
var name = RegistryHelper.getKeyOrThrow(BuiltInRegistries.ITEM, pocket).withPath(x -> x.replace("pocket_computer_", "pocket_"));
registries.lookup(ModRegistry.POCKET_UPGRADE).map(HolderLookup::listElements).orElse(Stream.empty()).forEach(upgradeHolder -> {
registries.lookupOrThrow(IPocketUpgrade.REGISTRY).listElements().forEach(upgradeHolder -> {
var upgrade = upgradeHolder.value();
ShapedSpecBuilder
.shaped(RecipeCategory.REDSTONE, DataComponentUtil.createStack(pocket, ModRegistry.DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(upgradeHolder)))
@@ -238,25 +238,25 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.pattern(" # ")
.pattern("#R#")
.pattern(" # ")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('R', ingredients.redstone())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.unlockedBy("has_modem", inventoryChange(WIRED_MODEM))
.save(add);
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_NORMAL.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_NORMAL.get())
.pattern("###")
.pattern("#R#")
.pattern("#G#")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('R', ingredients.redstone())
.define('G', ingredients.glassPane())
.unlockedBy("has_redstone", inventoryChange(itemPredicate(ingredients.redstone())))
.save(add);
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_ADVANCED.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_ADVANCED.get())
.pattern("###")
.pattern("#R#")
.pattern("#G#")
@@ -278,18 +278,18 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "computer_advanced_upgrade"));
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.COMPUTER_COMMAND.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.COMPUTER_COMMAND.get())
.pattern("###")
.pattern("#R#")
.pattern("#G#")
.define('#', ingredients.goldIngot())
.define('R', Blocks.COMMAND_BLOCK)
.define('R', Items.COMMAND_BLOCK)
.define('G', ingredients.glassPane())
.unlockedBy("has_components", inventoryChange(Blocks.COMMAND_BLOCK))
.unlockedBy("has_components", inventoryChange(Items.COMMAND_BLOCK))
.save(add);
ShapedSpecBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_NORMAL.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_NORMAL.get())
.pattern("###")
.pattern("#C#")
.pattern("#I#")
@@ -301,7 +301,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.save(add);
ShapedSpecBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get())
.pattern("###")
.pattern("#C#")
.pattern("#I#")
@@ -313,7 +313,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.save(add);
ShapedSpecBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.TURTLE_ADVANCED.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.TURTLE_ADVANCED.get())
.pattern("###")
.pattern("#C#")
.pattern(" B ")
@@ -325,27 +325,27 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_advanced_upgrade"));
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.DISK_DRIVE.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.DISK_DRIVE.get())
.pattern("###")
.pattern("#R#")
.pattern("#R#")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('R', ingredients.redstone())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.save(add);
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.MONITOR_NORMAL.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_NORMAL.get())
.pattern("###")
.pattern("#G#")
.pattern("###")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('G', ingredients.glassPane())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.save(add);
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.MONITOR_ADVANCED.get(), 4)
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.MONITOR_ADVANCED.get(), 4)
.pattern("###")
.pattern("#G#")
.pattern("###")
@@ -359,7 +359,7 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.pattern("###")
.pattern("#A#")
.pattern("#G#")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('A', Items.GOLDEN_APPLE)
.define('G', ingredients.glassPane())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
@@ -390,23 +390,23 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_computer_advanced_upgrade"));
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.PRINTER.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.PRINTER.get())
.pattern("###")
.pattern("#R#")
.pattern("#D#")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('R', ingredients.redstone())
.define('D', ingredients.dye())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.save(add);
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.SPEAKER.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.SPEAKER.get())
.pattern("###")
.pattern("#N#")
.pattern("#R#")
.define('#', ingredients.stone())
.define('N', Blocks.NOTE_BLOCK)
.define('#', Items.STONE)
.define('N', Items.NOTE_BLOCK)
.define('R', ingredients.redstone())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.save(add);
@@ -416,42 +416,42 @@ final class RecipeProvider extends net.minecraft.data.recipes.RecipeProvider {
.pattern("###")
.pattern("#R#")
.pattern("###")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('R', ingredients.redstone())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.unlockedBy("has_cable", inventoryChange(ModRegistry.Items.CABLE.get()))
.save(add);
ShapelessRecipeBuilder
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRED_MODEM_FULL.get())
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM_FULL.get())
.requires(ModRegistry.Items.WIRED_MODEM.get())
.unlockedBy("has_modem", inventoryChange(WIRED_MODEM))
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "wired_modem_full_from"));
ShapelessRecipeBuilder
.shapeless(RecipeCategory.REDSTONE, ModRegistry.Items.WIRED_MODEM.get())
.requires(ModRegistry.Blocks.WIRED_MODEM_FULL.get())
.requires(ModRegistry.Items.WIRED_MODEM_FULL.get())
.unlockedBy("has_modem", inventoryChange(WIRED_MODEM))
.save(add, new ResourceLocation(ComputerCraftAPI.MOD_ID, "wired_modem_full_to"));
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRELESS_MODEM_NORMAL.get())
.pattern("###")
.pattern("#E#")
.pattern("###")
.define('#', ingredients.stone())
.define('#', Items.STONE)
.define('E', ingredients.enderPearl())
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.save(add);
ShapedRecipeBuilder
.shaped(RecipeCategory.REDSTONE, ModRegistry.Blocks.WIRELESS_MODEM_ADVANCED.get())
.shaped(RecipeCategory.REDSTONE, ModRegistry.Items.WIRELESS_MODEM_ADVANCED.get())
.pattern("###")
.pattern("#E#")
.pattern("###")
.define('#', ingredients.goldIngot())
.define('E', Items.ENDER_EYE)
.unlockedBy("has_computer", inventoryChange(COMPUTER))
.unlockedBy("has_wireless", inventoryChange(ModRegistry.Blocks.WIRELESS_MODEM_NORMAL.get()))
.unlockedBy("has_wireless", inventoryChange(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()))
.save(add);
ShapelessSpecBuilder

View File

@@ -5,7 +5,7 @@
package dan200.computercraft.data;
import dan200.computercraft.api.ComputerCraftTags;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.integration.ExternalModTags;
import net.minecraft.core.Registry;

View File

@@ -5,45 +5,40 @@
package dan200.computercraft.data;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.ComputerCraftTags.Blocks;
import dan200.computercraft.api.ComputerCraftTags;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.turtle.TurtleUpgradeDataProvider;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.turtle.upgrades.TurtleCraftingTable;
import dan200.computercraft.shared.turtle.upgrades.TurtleModem;
import dan200.computercraft.shared.turtle.upgrades.TurtleSpeaker;
import net.minecraft.data.PackOutput;
import net.minecraft.data.worldgen.BootstrapContext;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import java.util.function.Consumer;
import static dan200.computercraft.api.turtle.TurtleToolBuilder.tool;
class TurtleUpgradeProvider extends TurtleUpgradeDataProvider {
TurtleUpgradeProvider(PackOutput output) {
super(output);
class TurtleUpgradeProvider {
public static void addUpgrades(BootstrapContext<ITurtleUpgrade> upgrades) {
upgrades.register(id("speaker"), new TurtleSpeaker(new ItemStack(ModRegistry.Items.SPEAKER.get())));
upgrades.register(vanilla("crafting_table"), new TurtleCraftingTable(new ItemStack(Items.CRAFTING_TABLE)));
upgrades.register(id("wireless_modem_normal"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()), false));
upgrades.register(id("wireless_modem_advanced"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_ADVANCED.get()), true));
tool(vanilla("diamond_axe").location(), Items.DIAMOND_AXE).damageMultiplier(6.0f).register(upgrades);
tool(vanilla("diamond_pickaxe"), Items.DIAMOND_PICKAXE).register(upgrades);
tool(vanilla("diamond_hoe"), Items.DIAMOND_HOE).breakable(ComputerCraftTags.Blocks.TURTLE_HOE_BREAKABLE).register(upgrades);
tool(vanilla("diamond_shovel"), Items.DIAMOND_SHOVEL).breakable(ComputerCraftTags.Blocks.TURTLE_SHOVEL_BREAKABLE).register(upgrades);
tool(vanilla("diamond_sword"), Items.DIAMOND_SWORD).breakable(ComputerCraftTags.Blocks.TURTLE_SWORD_BREAKABLE).damageMultiplier(9.0f).register(upgrades);
}
@Override
protected void addUpgrades(Consumer<Upgrade<ITurtleUpgrade>> addUpgrade) {
upgrade(id("speaker"), new TurtleSpeaker(new ItemStack(ModRegistry.Items.SPEAKER.get()))).add(addUpgrade);
upgrade(vanilla("crafting_table"), new TurtleCraftingTable(new ItemStack(Items.CRAFTING_TABLE))).add(addUpgrade);
upgrade(id("wireless_modem_normal"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_NORMAL.get()), false)).add(addUpgrade);
upgrade(id("wireless_modem_advanced"), new TurtleModem(new ItemStack(ModRegistry.Items.WIRELESS_MODEM_ADVANCED.get()), true)).add(addUpgrade);
tool(vanilla("diamond_axe"), Items.DIAMOND_AXE).damageMultiplier(6.0f).add(addUpgrade);
tool(vanilla("diamond_pickaxe"), Items.DIAMOND_PICKAXE).add(addUpgrade);
tool(vanilla("diamond_hoe"), Items.DIAMOND_HOE).breakable(Blocks.TURTLE_HOE_BREAKABLE).add(addUpgrade);
tool(vanilla("diamond_shovel"), Items.DIAMOND_SHOVEL).breakable(Blocks.TURTLE_SHOVEL_BREAKABLE).add(addUpgrade);
tool(vanilla("diamond_sword"), Items.DIAMOND_SWORD).breakable(Blocks.TURTLE_SWORD_BREAKABLE).damageMultiplier(9.0f).add(addUpgrade);
private static ResourceKey<ITurtleUpgrade> id(String id) {
return ITurtleUpgrade.createKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, id));
}
private static ResourceLocation id(String id) {
return new ResourceLocation(ComputerCraftAPI.MOD_ID, id);
}
private static ResourceLocation vanilla(String id) {
private static ResourceKey<ITurtleUpgrade> vanilla(String id) {
// Naughty, please don't do this. Mostly here for some semblance of backwards compatibility.
return new ResourceLocation("minecraft", id);
return ITurtleUpgrade.createKey(new ResourceLocation("minecraft", id));
}
}

View File

@@ -5,11 +5,10 @@
package dan200.computercraft.impl;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.shared.ModRegistry;
public final class PocketUpgrades {
private static final UpgradeManager<IPocketUpgrade> registry = new UpgradeManager<>(
IPocketUpgrade.typeRegistry(), ModRegistry.POCKET_UPGRADE, IPocketUpgrade::getType
IPocketUpgrade.typeRegistry(), IPocketUpgrade.REGISTRY, IPocketUpgrade::getType
);
private PocketUpgrades() {

View File

@@ -5,11 +5,10 @@
package dan200.computercraft.impl;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.shared.ModRegistry;
public final class TurtleUpgrades {
private static final UpgradeManager<ITurtleUpgrade> registry = new UpgradeManager<>(
ITurtleUpgrade.typeRegistry(), ModRegistry.TURTLE_UPGRADE, ITurtleUpgrade::getType
ITurtleUpgrade.typeRegistry(), ITurtleUpgrade.REGISTRY, ITurtleUpgrade::getType
);
private TurtleUpgrades() {

View File

@@ -18,7 +18,6 @@ import dan200.computercraft.api.upgrades.UpgradeData;
import dan200.computercraft.api.upgrades.UpgradeType;
import dan200.computercraft.core.util.Colour;
import dan200.computercraft.impl.PocketUpgrades;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.command.UserLevel;
import dan200.computercraft.shared.command.arguments.ComputerArgumentType;
import dan200.computercraft.shared.command.arguments.RepeatArgumentType;
@@ -91,7 +90,6 @@ import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
import net.minecraft.core.Holder;
import net.minecraft.core.HolderLookup;
import net.minecraft.core.Registry;
import net.minecraft.core.cauldron.CauldronInteraction;
import net.minecraft.core.component.DataComponentType;
import net.minecraft.core.registries.Registries;
@@ -99,7 +97,6 @@ import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.chat.Component;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.flag.FeatureFlags;
import net.minecraft.world.inventory.MenuType;
@@ -130,9 +127,6 @@ public final class ModRegistry {
private ModRegistry() {
}
public static final ResourceKey<Registry<ITurtleUpgrade>> TURTLE_UPGRADE = RegistryHelper.TURTLE_UPGRADE;
public static final ResourceKey<Registry<IPocketUpgrade>> POCKET_UPGRADE = RegistryHelper.POCKET_UPGRADE;
public static final class Blocks {
static final RegistrationHelper<Block> REGISTRY = PlatformHelper.get().createRegistrationHelper(Registries.BLOCK);
@@ -602,7 +596,7 @@ public final class ModRegistry {
private static void addTurtle(CreativeModeTab.Output out, TurtleItem turtle, HolderLookup.Provider registries) {
out.accept(new ItemStack(turtle));
registries.lookupOrThrow(TURTLE_UPGRADE).listElements()
registries.lookupOrThrow(ITurtleUpgrade.REGISTRY).listElements()
.filter(ModRegistry::isOurUpgrade)
.map(x -> DataComponentUtil.createStack(turtle, DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(x)))
.forEach(out::accept);
@@ -610,7 +604,7 @@ public final class ModRegistry {
private static void addPocket(CreativeModeTab.Output out, PocketComputerItem pocket, HolderLookup.Provider registries) {
out.accept(new ItemStack(pocket));
registries.lookupOrThrow(POCKET_UPGRADE).listElements()
registries.lookupOrThrow(IPocketUpgrade.REGISTRY).listElements()
.filter(ModRegistry::isOurUpgrade)
.map(x -> DataComponentUtil.createStack(pocket, DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(x))).forEach(out::accept);
}

View File

@@ -8,7 +8,7 @@ import com.google.gson.JsonObject;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.arguments.ArgumentType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import net.minecraft.commands.synchronization.ArgumentTypeInfo;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.FriendlyByteBuf;

View File

@@ -4,7 +4,7 @@
package dan200.computercraft.shared.details;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import net.minecraft.core.Holder;
import net.minecraft.core.Registry;
import net.minecraft.tags.TagKey;

View File

@@ -5,6 +5,8 @@
package dan200.computercraft.shared.integration;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.api.pocket.IPocketUpgrade;
import dan200.computercraft.api.turtle.ITurtleUpgrade;
import dan200.computercraft.api.upgrades.UpgradeData;
import dan200.computercraft.shared.ModRegistry;
import dan200.computercraft.shared.pocket.items.PocketComputerItem;
@@ -60,14 +62,14 @@ public final class RecipeModHelpers {
List<ItemStack> upgradeItems = new ArrayList<>();
for (var turtleSupplier : TURTLES) {
var turtle = turtleSupplier.get();
forEachRegistry(registries, ModRegistry.TURTLE_UPGRADE, upgrade ->
forEachRegistry(registries, ITurtleUpgrade.REGISTRY, upgrade ->
upgradeItems.add(DataComponentUtil.createStack(turtle, ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), UpgradeData.ofDefault(upgrade)))
);
}
for (var pocketSupplier : POCKET_COMPUTERS) {
var pocket = pocketSupplier.get();
forEachRegistry(registries, ModRegistry.POCKET_UPGRADE, upgrade ->
forEachRegistry(registries, IPocketUpgrade.REGISTRY, upgrade ->
upgradeItems.add(DataComponentUtil.createStack(pocket, ModRegistry.DataComponents.POCKET_UPGRADE.get(), UpgradeData.ofDefault(upgrade)))
);
}

View File

@@ -57,7 +57,7 @@ public class UpgradeRecipeGenerator<T> {
if (initialised) return;
initialised = true;
forEachRegistry(registries, ModRegistry.TURTLE_UPGRADE, holder -> {
forEachRegistry(registries, ITurtleUpgrade.REGISTRY, holder -> {
var upgrade = holder.value();
var stack = upgrade.getCraftingItem();
if (stack.isEmpty()) return;
@@ -67,7 +67,7 @@ public class UpgradeRecipeGenerator<T> {
turtleUpgrades.add(info);
});
forEachRegistry(registries, ModRegistry.POCKET_UPGRADE, holder -> {
forEachRegistry(registries, IPocketUpgrade.REGISTRY, holder -> {
var upgrade = holder.value();
var stack = upgrade.getCraftingItem();
if (stack.isEmpty()) return;
@@ -223,13 +223,13 @@ public class UpgradeRecipeGenerator<T> {
var newStack = stack.copyWithCount(1);
newStack.set(ModRegistry.DataComponents.LEFT_TURTLE_UPGRADE.get(), left);
newStack.set(ModRegistry.DataComponents.RIGHT_TURTLE_UPGRADE.get(), right);
return stack;
return newStack;
}
private static ItemStack pocketWith(ItemStack stack, @Nullable UpgradeData<IPocketUpgrade> back) {
var newStack = stack.copyWithCount(1);
newStack.set(ModRegistry.DataComponents.POCKET_UPGRADE.get(), back);
return stack;
return newStack;
}
private T pocket(Ingredient upgrade, Ingredient pocketComputer, ItemStack result) {

View File

@@ -8,7 +8,9 @@ import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.ModRegistry;
import io.netty.buffer.ByteBuf;
import net.minecraft.core.component.DataComponentHolder;
import net.minecraft.network.codec.ByteBufCodecs;
import net.minecraft.network.codec.StreamCodec;
@@ -93,6 +95,10 @@ public record PrintoutData(String title, List<Line> lines) {
return DataResult.success(lines);
}
public static PrintoutData getOrEmpty(DataComponentHolder holder) {
return holder.getOrDefault(ModRegistry.DataComponents.PRINTOUT.get(), EMPTY);
}
/**
* Get the number of pages in this printout.
*

View File

@@ -35,7 +35,7 @@ public class PrintoutItem extends Item {
@Override
public void appendHoverText(ItemStack stack, TooltipContext context, List<Component> list, TooltipFlag options) {
var title = getTitle(stack);
var title = PrintoutData.getOrEmpty(stack).title();
if (!title.isEmpty()) list.add(Component.literal(title));
}
@@ -51,14 +51,4 @@ public class PrintoutItem extends Item {
public Type getType() {
return type;
}
public static String getTitle(ItemStack stack) {
var nbt = stack.get(ModRegistry.DataComponents.PRINTOUT.get());
return nbt == null ? "" : nbt.title();
}
public static int getPageCount(ItemStack stack) {
var nbt = stack.get(ModRegistry.DataComponents.PRINTOUT.get());
return nbt == null ? 1 : nbt.pages();
}
}

View File

@@ -64,7 +64,7 @@ public final class PrintoutRecipe extends CustomRecipe {
if (stack.getItem() instanceof PrintoutItem printout && printout.getType() != PrintoutItem.Type.BOOK) {
if (printouts == null) printouts = new ItemStack[9];
printouts[numPrintouts] = stack;
numPages += PrintoutItem.getPageCount(stack);
numPages += PrintoutData.getOrEmpty(stack).pages();
numPrintouts++;
printoutFound = true;
} else if (stack.getItem() == Items.PAPER) {
@@ -104,7 +104,7 @@ public final class PrintoutRecipe extends CustomRecipe {
}
}
var title = PrintoutItem.getTitle(printouts[0]);
var title = PrintoutData.getOrEmpty(printouts[0]).title();
return DataComponentUtil.createStack(
leatherFound ? ModRegistry.Items.PRINTED_BOOK.get() : ModRegistry.Items.PRINTED_PAGES.get(),

View File

@@ -4,7 +4,7 @@
package dan200.computercraft.shared.peripheral.modem.wired;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import dan200.computercraft.shared.ModRegistry;
import net.minecraft.Util;
import net.minecraft.core.BlockPos;

View File

@@ -11,7 +11,6 @@ import dan200.computercraft.shared.computer.terminal.NetworkedTerminal;
import dan200.computercraft.shared.container.BasicContainer;
import dan200.computercraft.shared.container.BasicWorldlyContainer;
import dan200.computercraft.shared.media.items.PrintoutData;
import dan200.computercraft.shared.media.items.PrintoutItem;
import dan200.computercraft.shared.util.ColourUtils;
import dan200.computercraft.shared.util.DataComponentUtil;
import net.minecraft.core.BlockPos;
@@ -172,8 +171,7 @@ public final class PrinterBlockEntity extends AbstractContainerBlockEntity imple
static boolean isPaper(ItemStack stack) {
var item = stack.getItem();
return item == Items.PAPER
|| (item instanceof PrintoutItem printout && printout.getType() == PrintoutItem.Type.PAGE);
return item == Items.PAPER || item == ModRegistry.Items.PRINTED_PAGE.get();
}
private boolean canInputPage() {

View File

@@ -4,11 +4,11 @@
package dan200.computercraft.shared.platform;
import com.google.gson.JsonObject;
import com.mojang.authlib.GameProfile;
import com.mojang.brigadier.arguments.ArgumentType;
import dan200.computercraft.api.network.wired.WiredElement;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.impl.Services;
import dan200.computercraft.shared.config.ConfigFile;
import dan200.computercraft.shared.network.container.ContainerData;
import dan200.computercraft.shared.util.InventoryUtil;
@@ -47,26 +47,19 @@ import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* This extends {@linkplain dan200.computercraft.impl.PlatformHelper the API's loader abstraction layer}, adding
* additional methods used by the actual mod.
* Abstraction layer for Forge and Fabric. See implementations for more details.
*/
public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper {
public interface PlatformHelper {
/**
* Get the current {@link PlatformHelper} instance.
*
* @return The current instance.
*/
static PlatformHelper get() {
return (PlatformHelper) dan200.computercraft.impl.PlatformHelper.get();
var instance = Instance.INSTANCE;
return instance == null ? Services.raise(PlatformHelper.class, Instance.ERROR) : instance;
}
/**
* Check if we're running in a development environment.
*
* @return If we're running in a development environment.
*/
boolean isDevelopmentEnvironment();
/**
* Create a new config builder.
*
@@ -83,16 +76,6 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
*/
<T> RegistrationHelper<T> createRegistrationHelper(ResourceKey<Registry<T>> registry);
/**
* Determine if this resource should be loaded, based on platform-specific loot conditions.
* <p>
* This should only be called from the {@code apply} stage of a reload listener.
*
* @param object The root JSON object of this resource.
* @return If this resource should be loaded.
*/
boolean shouldLoadResource(JsonObject object);
/**
* Register a new argument type.
*
@@ -328,4 +311,21 @@ public interface PlatformHelper extends dan200.computercraft.impl.PlatformHelper
* @see ServerPlayerGameMode#useItemOn(ServerPlayer, Level, ItemStack, InteractionHand, BlockHitResult)
*/
InteractionResult useOn(ServerPlayer player, ItemStack stack, BlockHitResult hit, Predicate<BlockState> canUseBlock);
final class Instance {
static final @Nullable PlatformHelper INSTANCE;
static final @Nullable Throwable ERROR;
static {
// We don't want class initialisation to fail here (as that results in confusing errors). Instead, capture
// the error and rethrow it when accessing. This should be JITted away in the common case.
var helper = Services.tryLoad(PlatformHelper.class);
INSTANCE = helper.instance();
ERROR = helper.error();
}
private Instance() {
}
}
}

View File

@@ -13,7 +13,6 @@ import net.minecraft.world.item.crafting.Ingredient;
* @param redstone All {@link Items#REDSTONE} items.
* @param string All {@link Items#STRING} items.
* @param leather All {@link Items#LEATHER} items.
* @param stone All {@link Items#STONE} items.
* @param glassPane All {@link Items#GLASS_PANE} items.
* @param goldIngot All {@link Items#GOLD_INGOT} items.
* @param goldBlock All {@link Items#GOLD_BLOCK} items.
@@ -26,7 +25,6 @@ public record RecipeIngredients(
Ingredient redstone,
Ingredient string,
Ingredient leather,
Ingredient stone,
Ingredient glassPane,
Ingredient goldIngot,
Ingredient goldBlock,

View File

@@ -6,7 +6,7 @@ package dan200.computercraft.shared.recipe;
import com.mojang.serialization.DataResult;
import com.mojang.serialization.MapCodec;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.RegistryFriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;

View File

@@ -0,0 +1,49 @@
// SPDX-FileCopyrightText: 2023 The CC: Tweaked Developers
//
// SPDX-License-Identifier: MPL-2.0
package dan200.computercraft.shared.util;
import net.minecraft.core.Registry;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceKey;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.ApiStatus;
/**
* Additioanl functions for working with {@linkplain Registry registries}.
*/
@ApiStatus.Internal
public final class RegistryHelper {
private RegistryHelper() {
}
/**
* Find a registry from a {@link ResourceKey}, throwing if it does not exist.
*
* @param id The id of the registry.
* @param <T> The contents of the registry
* @return The associated registry.
*/
@SuppressWarnings("unchecked")
public static <T> Registry<T> getRegistry(ResourceKey<Registry<T>> id) {
var registry = (Registry<T>) BuiltInRegistries.REGISTRY.get(id.location());
if (registry == null) throw new IllegalArgumentException("Unknown registry " + id);
return registry;
}
/**
* Get the key of a registry entry, throwing if it is not registered.
*
* @param registry The registry to look up in.
* @param object The object to look up.
* @param <T> The type of this registry.
* @return The ID of this object
* @see Registry#getResourceKey(Object)
*/
public static <T> ResourceLocation getKeyOrThrow(Registry<T> registry, T object) {
var key = registry.getResourceKey(object);
if (key.isEmpty()) throw new IllegalArgumentException(object + " was not registered in " + registry.key());
return key.get().location();
}
}

View File

@@ -6,7 +6,6 @@ package dan200.computercraft.shared.util;
import com.mojang.serialization.*;
import com.mojang.serialization.codecs.KeyDispatchCodec;
import dan200.computercraft.impl.RegistryHelper;
import net.minecraft.core.Registry;
import net.minecraft.resources.ResourceKey;

View File

@@ -6,7 +6,6 @@
"uniforms": [
{ "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "IViewRotMat", "type": "matrix3x3", "count": 9, "values": [ 1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0 ] },
{ "name": "ColorModulator", "type": "float", "count": 4, "values": [ 1.0, 1.0, 1.0, 1.0 ] },
{ "name": "FogStart", "type": "float", "count": 1, "values": [ 0.0 ] },
{ "name": "FogEnd", "type": "float", "count": 1, "values": [ 1.0 ] },

View File

@@ -5,7 +5,6 @@
package dan200.computercraft;
import com.google.auto.service.AutoService;
import com.google.gson.JsonObject;
import com.mojang.authlib.GameProfile;
import com.mojang.brigadier.arguments.ArgumentType;
import dan200.computercraft.api.network.wired.WiredElement;
@@ -48,13 +47,8 @@ import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
@AutoService({ PlatformHelper.class, dan200.computercraft.impl.PlatformHelper.class, ComputerCraftAPIService.class })
@AutoService({ PlatformHelper.class, ComputerCraftAPIService.class })
public class TestPlatformHelper extends AbstractComputerCraftAPI implements PlatformHelper {
@Override
public boolean isDevelopmentEnvironment() {
return true;
}
@Override
public ConfigFile.Builder createConfigBuilder() {
throw new UnsupportedOperationException("Cannot create config file inside tests");
@@ -65,16 +59,6 @@ public class TestPlatformHelper extends AbstractComputerCraftAPI implements Plat
throw new UnsupportedOperationException("Cannot query registry inside tests");
}
@Override
public boolean shouldLoadResource(JsonObject object) {
throw new UnsupportedOperationException("Cannot use resource conditions");
}
@Override
public void addRequiredModCondition(JsonObject object, String modId) {
throw new UnsupportedOperationException("Cannot use resource conditions");
}
@Override
public <A extends ArgumentType<?>, T extends ArgumentTypeInfo.Template<A>, I extends ArgumentTypeInfo<A, T>> I registerArgumentTypeInfo(Class<A> klass, I info) {
throw new UnsupportedOperationException("Cannot register ArgumentTypeInfo inside tests");

View File

@@ -17,7 +17,7 @@ import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import dan200.computercraft.api.ComputerCraftAPI;
import dan200.computercraft.data.PrettyJsonWriter;
import dan200.computercraft.gametest.core.TestHooks;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import net.minecraft.client.Minecraft;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.network.chat.Component;

View File

@@ -4,7 +4,7 @@
package dan200.computercraft.export;
import dan200.computercraft.impl.RegistryHelper;
import dan200.computercraft.shared.util.RegistryHelper;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;

View File

@@ -233,7 +233,7 @@ class Turtle_Test {
val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access
val upgrade = turtle.getUpgrade(TurtleSide.LEFT)
assertEquals(
helper.level.registryAccess().registryOrThrow(ModRegistry.TURTLE_UPGRADE)
helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY)
.get(ResourceLocation("cctest", "wooden_pickaxe")),
upgrade,
"Upgrade is a wooden pickaxe",
@@ -262,7 +262,7 @@ class Turtle_Test {
helper.assertUpgradeItem(
ItemStack(Items.WOODEN_PICKAXE),
UpgradeData.ofDefault(
helper.level.registryAccess().registryOrThrow(ModRegistry.TURTLE_UPGRADE)
helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY)
.getHolder(ResourceLocation("cctest", "wooden_pickaxe")).orElseThrow(),
),
)
@@ -283,7 +283,7 @@ class Turtle_Test {
val turtle = helper.getBlockEntity(BlockPos(2, 2, 2), ModRegistry.BlockEntities.TURTLE_NORMAL.get()).access
val upgrade = turtle.getUpgrade(TurtleSide.LEFT)
assertEquals(
helper.level.registryAccess().registryOrThrow(ModRegistry.TURTLE_UPGRADE)
helper.level.registryAccess().registryOrThrow(ITurtleUpgrade.REGISTRY)
.get(ResourceLocation("cctest", "netherite_pickaxe")),
upgrade,
"Upgrade is a netherite pickaxe",

View File

@@ -5,8 +5,8 @@
package dan200.computercraft.gametest.api
import dan200.computercraft.gametest.core.MinecraftExtensions
import dan200.computercraft.impl.RegistryHelper
import dan200.computercraft.mixin.gametest.GameTestSequenceAccessor
import dan200.computercraft.shared.util.RegistryHelper
import net.minecraft.client.Minecraft
import net.minecraft.client.Screenshot
import net.minecraft.client.gui.screens.inventory.MenuAccess

View File

@@ -6,10 +6,10 @@ package dan200.computercraft.gametest.api
import dan200.computercraft.api.peripheral.IPeripheral
import dan200.computercraft.gametest.core.ManagedComputers
import dan200.computercraft.impl.RegistryHelper
import dan200.computercraft.mixin.gametest.GameTestInfoAccessor
import dan200.computercraft.mixin.gametest.GameTestSequenceAccessor
import dan200.computercraft.shared.platform.PlatformHelper
import dan200.computercraft.shared.util.RegistryHelper
import dan200.computercraft.test.core.computer.LuaTaskContext
import dan200.computercraft.test.shared.ItemStackMatcher.isStack
import net.minecraft.commands.arguments.blocks.BlockInput