mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-08-30 17:17:55 +00:00
Update to Minecraft 1.21
API Changes: - Minecraft had updated ModelResourceLocation to no longer inherit from ResourceLocation. To allow referencing both already baked models (ModelResourceLocation) and loading new models (via ResourceLocation) in turtle model loadders, we add a new "ModelLocation" class, that acts as a union between the two. I'm not entirely convinced by the design here, so might end up changing again before a stable release.o - Merge IMedia.getAudioTitle and IMedia.getAudio into a single IMedia.getAudio method, which now returns a JukeboxSong rather than a SoundEvent. Other update notes: - Minecraft had rewritten how buffers are managed again. This is a fairly minor change for us (vertex -> addVertex, normal -> setNormal, etc...), with the exception that you can no longer use MultiBufferSource.immediate with the tesselator. I've replaced this with GuiGraphics.bufferSource, which appears to be fine, but worth keeping an eye on in case there's any odd render state issues. - Crafting now uses a CraftingInput (a list of items) rather than a CraftingContainer, which allows us to simplify turtle crafting code.
This commit is contained in:
@@ -0,0 +1,84 @@
|
||||
// SPDX-FileCopyrightText: 2024 The CC: Tweaked Developers
|
||||
//
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package dan200.computercraft.api.client;
|
||||
|
||||
import dan200.computercraft.api.client.turtle.TurtleUpgradeModeller;
|
||||
import dan200.computercraft.impl.client.ClientPlatformHelper;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.ModelManager;
|
||||
import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* The location of a model to load. This may either be:
|
||||
*
|
||||
* <ul>
|
||||
* <li>A {@link ModelResourceLocation}, referencing an already baked model (such as {@code minecraft:dirt#inventory}).</li>
|
||||
* <li>
|
||||
* A {@link ResourceLocation}, referencing a path to a model resource (such as {@code minecraft:item/dirt}.
|
||||
* These models will be baked and stored in the {@link ModelManager} in a loader-specific way.
|
||||
* </li>
|
||||
* </ul>
|
||||
*/
|
||||
public final class ModelLocation {
|
||||
/**
|
||||
* The location of the model.
|
||||
* <p>
|
||||
* When {@link #resourceLocation} is null, this is the location of the model to load. When {@link #resourceLocation}
|
||||
* is non-null, this is the "standalone" variant of the model resource — this is used by NeoForge's implementation
|
||||
* of {@link ClientPlatformHelper#getModel(ModelManager, ModelResourceLocation, ResourceLocation)} to fetch the
|
||||
* model from the model manger. It is not used on Fabric.
|
||||
*/
|
||||
private final ModelResourceLocation modelLocation;
|
||||
private final @Nullable ResourceLocation resourceLocation;
|
||||
|
||||
private ModelLocation(ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation) {
|
||||
this.modelLocation = modelLocation;
|
||||
this.resourceLocation = resourceLocation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ModelLocation} from model in the model manager.
|
||||
*
|
||||
* @param location The name of the model to load.
|
||||
* @return The new {@link ModelLocation} instance.
|
||||
*/
|
||||
public static ModelLocation ofModel(ModelResourceLocation location) {
|
||||
return new ModelLocation(location, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link ModelLocation} from a resource.
|
||||
*
|
||||
* @param location The location of the model resource, such as {@code minecraft:item/dirt}.
|
||||
* @return The new {@link ModelLocation} instance.
|
||||
*/
|
||||
public static ModelLocation ofResource(ResourceLocation location) {
|
||||
return new ModelLocation(new ModelResourceLocation(location, "standalone"), location);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get this model from the provided model manager.
|
||||
*
|
||||
* @param manager The model manger.
|
||||
* @return This model, or the missing model if it could not be found.
|
||||
*/
|
||||
public BakedModel getModel(ModelManager manager) {
|
||||
return ClientPlatformHelper.get().getModel(manager, modelLocation, resourceLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the models this model location depends on.
|
||||
*
|
||||
* @return A list of models that this model location depends on.
|
||||
* @see TurtleUpgradeModeller#getDependencies()
|
||||
*/
|
||||
public Stream<ResourceLocation> getDependencies() {
|
||||
return resourceLocation == null ? Stream.empty() : Stream.of(resourceLocation);
|
||||
}
|
||||
}
|
@@ -13,30 +13,47 @@ import net.minecraft.client.resources.model.ModelResourceLocation;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* A model to render, combined with a transformation matrix to apply.
|
||||
*
|
||||
* @param model The model.
|
||||
* @param matrix The transformation matrix.
|
||||
*/
|
||||
public final class TransformedModel {
|
||||
private final BakedModel model;
|
||||
private final Transformation matrix;
|
||||
|
||||
public TransformedModel(BakedModel model, Transformation matrix) {
|
||||
this.model = Objects.requireNonNull(model);
|
||||
this.matrix = Objects.requireNonNull(matrix);
|
||||
}
|
||||
|
||||
public record TransformedModel(BakedModel model, Transformation matrix) {
|
||||
public TransformedModel(BakedModel model) {
|
||||
this.model = Objects.requireNonNull(model);
|
||||
matrix = Transformation.identity();
|
||||
this(model, Transformation.identity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||
*
|
||||
* @param location The location of the model to load.
|
||||
* @return The new {@link TransformedModel} instance.
|
||||
*/
|
||||
public static TransformedModel of(ModelLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(location.getModel(modelManager));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||
*
|
||||
* @param location The location of the model to load.
|
||||
* @return The new {@link TransformedModel} instance.
|
||||
* @see ModelLocation#ofModel(ModelResourceLocation)
|
||||
*/
|
||||
public static TransformedModel of(ModelResourceLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(modelManager.getModel(location));
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a model in the model bakery and construct a {@link TransformedModel} with no transformation.
|
||||
*
|
||||
* @param location The location of the model to load.
|
||||
* @return The new {@link TransformedModel} instance.
|
||||
* @see ModelLocation#ofResource(ResourceLocation)
|
||||
*/
|
||||
public static TransformedModel of(ResourceLocation location) {
|
||||
var modelManager = Minecraft.getInstance().getModelManager();
|
||||
return new TransformedModel(ClientPlatformHelper.get().getModel(modelManager, location));
|
||||
@@ -46,12 +63,4 @@ public final class TransformedModel {
|
||||
var model = Minecraft.getInstance().getItemRenderer().getItemModelShaper().getItemModel(item);
|
||||
return new TransformedModel(model, transform);
|
||||
}
|
||||
|
||||
public BakedModel getModel() {
|
||||
return model;
|
||||
}
|
||||
|
||||
public Transformation getMatrix() {
|
||||
return matrix;
|
||||
}
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
package dan200.computercraft.api.client.turtle;
|
||||
|
||||
import dan200.computercraft.api.client.ModelLocation;
|
||||
import dan200.computercraft.api.client.TransformedModel;
|
||||
import dan200.computercraft.api.turtle.ITurtleAccess;
|
||||
import dan200.computercraft.api.turtle.ITurtleUpgrade;
|
||||
@@ -77,6 +78,18 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ResourceLocation left, ResourceLocation right) {
|
||||
return sided(ModelLocation.ofResource(left), ModelLocation.ofResource(right));
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link TurtleUpgradeModeller} which has a single model for the left and right side.
|
||||
*
|
||||
* @param left The model to use on the left.
|
||||
* @param right The model to use on the right.
|
||||
* @param <T> The type of the turtle upgrade.
|
||||
* @return The constructed modeller.
|
||||
*/
|
||||
static <T extends ITurtleUpgrade> TurtleUpgradeModeller<T> sided(ModelLocation left, ModelLocation right) {
|
||||
return new TurtleUpgradeModeller<>() {
|
||||
@Override
|
||||
public TransformedModel getModel(T upgrade, @Nullable ITurtleAccess turtle, TurtleSide side, DataComponentPatch data) {
|
||||
@@ -85,7 +98,7 @@ public interface TurtleUpgradeModeller<T extends ITurtleUpgrade> {
|
||||
|
||||
@Override
|
||||
public Stream<ResourceLocation> getDependencies() {
|
||||
return Stream.of(left, right);
|
||||
return Stream.of(left, right).flatMap(ModelLocation::getDependencies);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
|
||||
package dan200.computercraft.impl.client;
|
||||
|
||||
import dan200.computercraft.api.client.ModelLocation;
|
||||
import dan200.computercraft.impl.Services;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
@@ -17,13 +18,28 @@ import javax.annotation.Nullable;
|
||||
@ApiStatus.Internal
|
||||
public interface ClientPlatformHelper {
|
||||
/**
|
||||
* Equivalent to {@link ModelManager#getModel(ModelResourceLocation)} but for arbitrary {@link ResourceLocation}s.
|
||||
* Get a model from a resource.
|
||||
*
|
||||
* @param manager The model manager.
|
||||
* @param location The model location.
|
||||
* @param manager The model manager.
|
||||
* @param resourceLocation The model resourceLocation.
|
||||
* @return The baked model.
|
||||
* @see ModelLocation
|
||||
*/
|
||||
BakedModel getModel(ModelManager manager, ResourceLocation location);
|
||||
BakedModel getModel(ModelManager manager, ResourceLocation resourceLocation);
|
||||
|
||||
/**
|
||||
* Set a model from a {@link ModelResourceLocation} or {@link ResourceLocation}.
|
||||
* <p>
|
||||
* This is largely equivalent to {@code resourceLocation == null ? manager.getModel(modelLocation) : getModel(manager, resourceLocation)},
|
||||
* but allows pre-computing {@code modelLocation} (if needed).
|
||||
*
|
||||
* @param manager The model manager.
|
||||
* @param modelLocation The location of the model to load.
|
||||
* @param resourceLocation The location of the resource, if trying to load from a resource.
|
||||
* @return The baked model.
|
||||
* @see ModelLocation
|
||||
*/
|
||||
BakedModel getModel(ModelManager manager, ModelResourceLocation modelLocation, @Nullable ResourceLocation resourceLocation);
|
||||
|
||||
/**
|
||||
* Wrap this model in a version which renders a foil/enchantment glint.
|
||||
|
@@ -46,7 +46,7 @@ public class ComputerCraftTags {
|
||||
public static final TagKey<Item> DYEABLE = make("dyeable");
|
||||
|
||||
private static TagKey<Item> make(String name) {
|
||||
return TagKey.create(Registries.ITEM, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||
return TagKey.create(Registries.ITEM, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ public class ComputerCraftTags {
|
||||
public static final TagKey<Block> TURTLE_CAN_USE = make("turtle_can_use");
|
||||
|
||||
private static TagKey<Block> make(String name) {
|
||||
return TagKey.create(Registries.BLOCK, new ResourceLocation(ComputerCraftAPI.MOD_ID, name));
|
||||
return TagKey.create(Registries.BLOCK, ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -7,11 +7,13 @@ package dan200.computercraft.api.media;
|
||||
import dan200.computercraft.api.ComputerCraftAPI;
|
||||
import dan200.computercraft.api.filesystem.Mount;
|
||||
import dan200.computercraft.api.filesystem.WritableMount;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.JukeboxSong;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
@@ -25,11 +27,12 @@ public interface IMedia {
|
||||
/**
|
||||
* Get a string representing the label of this item. Will be called via {@code disk.getLabel()} in lua.
|
||||
*
|
||||
* @param stack The {@link ItemStack} to inspect.
|
||||
* @param registries The currently loaded registries.
|
||||
* @param stack The {@link ItemStack} to inspect.
|
||||
* @return The label. ie: "Dan's Programs".
|
||||
*/
|
||||
@Nullable
|
||||
String getLabel(ItemStack stack);
|
||||
String getLabel(HolderLookup.Provider registries, ItemStack stack);
|
||||
|
||||
/**
|
||||
* Set a string representing the label of this item. Will be called vi {@code disk.setLabel()} in lua.
|
||||
@@ -43,26 +46,15 @@ public interface IMedia {
|
||||
}
|
||||
|
||||
/**
|
||||
* If this disk represents an item with audio (like a record), get the readable name of the audio track. ie:
|
||||
* "Jonathan Coulton - Still Alive"
|
||||
* If this disk represents an item with audio (like a record), get the corresponding {@link JukeboxSong}.
|
||||
*
|
||||
* @param stack The {@link ItemStack} to modify.
|
||||
* @return The name, or null if this item does not represent an item with audio.
|
||||
* @param registries The currently loaded registries.
|
||||
* @param stack The {@link ItemStack} to query.
|
||||
* @return The song, or null if this item does not represent an item with audio.
|
||||
*/
|
||||
@Nullable
|
||||
default String getAudioTitle(ItemStack stack) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* If this disk represents an item with audio (like a record), get the resource name of the audio track to play.
|
||||
*
|
||||
* @param stack The {@link ItemStack} to modify.
|
||||
* @return The name, or null if this item does not represent an item with audio.
|
||||
*/
|
||||
@Nullable
|
||||
default SoundEvent getAudio(ItemStack stack) {
|
||||
return null;
|
||||
default Holder<JukeboxSong> getAudio(HolderLookup.Provider registries, ItemStack stack) {
|
||||
return JukeboxSong.fromStack(registries, stack).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -48,7 +48,7 @@ import javax.annotation.Nullable;
|
||||
* }
|
||||
*/
|
||||
public interface IPocketUpgrade extends UpgradeBase {
|
||||
ResourceKey<Registry<IPocketUpgrade>> REGISTRY = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "pocket_upgrade"));
|
||||
ResourceKey<Registry<IPocketUpgrade>> REGISTRY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "pocket_upgrade"));
|
||||
|
||||
/**
|
||||
* The registry key for pocket upgrade types.
|
||||
|
@@ -57,7 +57,7 @@ public interface ITurtleUpgrade extends UpgradeBase {
|
||||
/**
|
||||
* The registry in which turtle upgrades are stored.
|
||||
*/
|
||||
ResourceKey<Registry<ITurtleUpgrade>> REGISTRY = ResourceKey.createRegistryKey(new ResourceLocation(ComputerCraftAPI.MOD_ID, "turtle_upgrade"));
|
||||
ResourceKey<Registry<ITurtleUpgrade>> REGISTRY = ResourceKey.createRegistryKey(ResourceLocation.fromNamespaceAndPath(ComputerCraftAPI.MOD_ID, "turtle_upgrade"));
|
||||
|
||||
/**
|
||||
* Create a {@link ResourceKey} for a turtle upgrade given a {@link ResourceLocation}.
|
||||
|
@@ -35,7 +35,7 @@ import java.util.Optional;
|
||||
* import net.minecraft.world.item.Items;
|
||||
*
|
||||
* public void registerTool(BootstrapContext<ITurtleUpgrade> upgrades) {
|
||||
* TurtleToolBuilder.tool(new ResourceLocation("my_mod", "wooden_pickaxe"), Items.WOODEN_PICKAXE).register(upgrades);
|
||||
* TurtleToolBuilder.tool(ResourceLocation.fromNamespaceAndPath("my_mod", "wooden_pickaxe"), Items.WOODEN_PICKAXE).register(upgrades);
|
||||
* }
|
||||
*}
|
||||
*/
|
||||
|
@@ -55,7 +55,7 @@ import java.util.function.Function;
|
||||
* public void generate(DataGenerator.PackGenerator output, CompletableFuture<HolderLookup.Provider> registries) {
|
||||
* var newRegistries = RegistryPatchGenerator.createLookup(registries, Util.make(new RegistrySetBuilder(), builder -> {
|
||||
* builder.add(ITurtleUpgrade.REGISTRY, upgrades -> {
|
||||
* upgrades.register(ITurtleUpgrade.createKey(new ResourceLocation("my_mod", "my_upgrade")), new MyUpgrade());
|
||||
* upgrades.register(ITurtleUpgrade.createKey(ResourceLocation.fromNamespaceAndPath("my_mod", "my_upgrade")), new MyUpgrade());
|
||||
* });
|
||||
* }));
|
||||
* output.addProvider(o -> new DatapackBuiltinEntriesProvider(o, newRegistries, Set.of("my_mod")));
|
||||
|
Reference in New Issue
Block a user