mirror of
https://github.com/MinecraftForge/MinecraftForge.git
synced 2026-11-13 16:54:22 +00:00
Forge 1.19.3
Created a CreativeModeTabEvent to register creative mode tabs and populate entries per tab Moved datapack registries to DataPackRegistryEvent.NewRegistry event instead of tying them to ForgeRegistry Made it easier for mods to datagen datapack builtin entries with DatapackBuiltinEntriesProvider Provided access to lookupProvider for datagen Updated dependencies to match versions used by vanilla and update JarJar to 0.3.18 Added a test mod for the new CreativeModeTabEvent Throws better error message for Forge registries in tag datagen Deleted ForgeRegistryTagsProvider Updated ClientChatReceivedEvent and ServerChatEvent for Mojang changes Added patches for both sign related methods in ModelLayers Changed RegisterShadersEvent to use ResourceProvider Migrated old Mojang math types to JOML Co-authored-by: Marc Hermans <marc.hermans@ldtteam.com> Co-authored-by: LexManos <LexManos@gmail.com> Co-authored-by: sciwhiz12 <arnoldnunag12@gmail.com> Co-authored-by: coehlrich <coehlrich@users.noreply.github.com>
This commit is contained in:
1 parent
617ecb7ad3
commit
8255d7aed3
726 files changed
+7615
-6653
No files matched your search
@@ -29,6 +29,7 @@ import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.server.command.CommandHelper;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
@@ -45,13 +46,10 @@ public class ClientCommandHandler
|
||||
|
||||
private static void handleClientPlayerLogin(ClientPlayerNetworkEvent.LoggingIn event)
|
||||
{
|
||||
// some custom server implementations do not send ClientboundCommandsPacket, provide a fallback
|
||||
var suggestionDispatcher = mergeServerCommands(new CommandDispatcher<>(), new CommandBuildContext(event.getPlayer().connection.registryAccess()));
|
||||
if (event.getConnection().getPacketListener() instanceof ClientPacketListener listener)
|
||||
{
|
||||
// Must set this, so that suggestions for client-only commands work, if server never sends commands packet
|
||||
listener.commands = suggestionDispatcher;
|
||||
}
|
||||
final ClientPacketListener connection = event.getPlayer().connection;
|
||||
// Some custom server implementations do not send ClientboundCommandsPacket, so we provide a fallback:
|
||||
// Must set this, so that suggestions for client-only commands work, if server never sends commands packet
|
||||
connection.commands = mergeServerCommands(new CommandDispatcher<>(), CommandBuildContext.simple(connection.registryAccess(), connection.enabledFeatures()));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -60,6 +58,7 @@ public class ClientCommandHandler
|
||||
* Merges command dispatcher use for suggestions to the command dispatcher used for client commands so they can be sent to the server, and vice versa so client commands appear
|
||||
* with server commands in suggestions
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static CommandDispatcher<SharedSuggestionProvider> mergeServerCommands(CommandDispatcher<SharedSuggestionProvider> serverCommands, CommandBuildContext buildContext)
|
||||
{
|
||||
CommandDispatcher<CommandSourceStack> commandsTemp = new CommandDispatcher<>();
|
||||
@@ -143,10 +142,10 @@ public class ClientCommandHandler
|
||||
}
|
||||
|
||||
/**
|
||||
* Always try to execute the cached parsing of a typed command as a clientside command. Requires that the execute field of the commands to be set to send to server so that they aren't\
|
||||
* Always try to execute the cached parsing of a typed command as a clientside command. Requires that the execute field of the commands to be set to send to server so that they aren't
|
||||
* treated as client command's that do nothing.
|
||||
*
|
||||
* {@link net.minecraft.commands.Commands#performCommand(CommandSourceStack, String)} for reference
|
||||
* {@link net.minecraft.commands.Commands#performCommand(ParseResults, String)} for reference
|
||||
*
|
||||
* @param command the full command to execute, no preceding slash
|
||||
* @return {@code false} leaves the message to be sent to the server, while {@code true} means it should be caught before LocalPlayer#sendCommand
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.Map;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.searchtree.SearchRegistry;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.CreativeModeTabs;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraftforge.common.CreativeModeTabRegistry;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class CreativeModeTabSearchRegistry
|
||||
{
|
||||
private static final Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> NAME_SEARCH_KEYS = new IdentityHashMap<>();
|
||||
private static final Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> TAG_SEARCH_KEYS = new IdentityHashMap<>();
|
||||
|
||||
public static Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> getNameSearchKeys() {
|
||||
Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> nameSearchKeys = new IdentityHashMap<>();
|
||||
|
||||
nameSearchKeys.put(CreativeModeTabs.searchTab(), getNameSearchKey(CreativeModeTabs.searchTab()));
|
||||
|
||||
for (CreativeModeTab tab : CreativeModeTabRegistry.getSortedCreativeModeTabs())
|
||||
{
|
||||
SearchRegistry.Key<ItemStack> nameSearchKey = getNameSearchKey(tab);
|
||||
if (nameSearchKey != null)
|
||||
nameSearchKeys.put(tab, nameSearchKey);
|
||||
}
|
||||
|
||||
return nameSearchKeys;
|
||||
}
|
||||
|
||||
public static Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> getTagSearchKeys() {
|
||||
Map<CreativeModeTab, SearchRegistry.Key<ItemStack>> tagSearchKeys = new IdentityHashMap<>();
|
||||
|
||||
tagSearchKeys.put(CreativeModeTabs.searchTab(), getTagSearchKey(CreativeModeTabs.searchTab()));
|
||||
|
||||
for (CreativeModeTab tab : CreativeModeTabRegistry.getSortedCreativeModeTabs())
|
||||
{
|
||||
SearchRegistry.Key<ItemStack> tagSearchKey = getTagSearchKey(tab);
|
||||
if (tagSearchKey != null)
|
||||
tagSearchKeys.put(tab, tagSearchKey);
|
||||
}
|
||||
|
||||
return tagSearchKeys;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SearchRegistry.Key<ItemStack> getNameSearchKey(CreativeModeTab tab)
|
||||
{
|
||||
if (tab == CreativeModeTabs.searchTab())
|
||||
return SearchRegistry.CREATIVE_NAMES;
|
||||
|
||||
if (!tab.hasSearchBar())
|
||||
return null;
|
||||
|
||||
return NAME_SEARCH_KEYS.computeIfAbsent(tab, k -> new SearchRegistry.Key<>());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static SearchRegistry.Key<ItemStack> getTagSearchKey(CreativeModeTab tab)
|
||||
{
|
||||
if (tab == CreativeModeTabs.searchTab())
|
||||
return SearchRegistry.CREATIVE_TAGS;
|
||||
|
||||
if (!tab.hasSearchBar())
|
||||
return null;
|
||||
|
||||
return TAG_SEARCH_KEYS.computeIfAbsent(tab, k -> new SearchRegistry.Key<>());
|
||||
}
|
||||
|
||||
// We do it this way to prevent unwanted classloading
|
||||
@ApiStatus.Internal
|
||||
public static void createSearchTrees() {
|
||||
Minecraft.getInstance().createSearchTrees();
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,10 @@
|
||||
package net.minecraftforge.client;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.graph.ElementOrder;
|
||||
import com.google.common.graph.GraphBuilder;
|
||||
import com.google.common.graph.MutableGraph;
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
@@ -14,8 +18,6 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.FileUtil;
|
||||
import net.minecraft.client.Camera;
|
||||
@@ -53,14 +55,16 @@ import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.client.renderer.Sheets;
|
||||
import net.minecraft.client.renderer.block.BlockRenderDispatcher;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.culling.Frustum;
|
||||
import net.minecraft.client.renderer.texture.SpriteContents;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.language.I18n;
|
||||
import net.minecraft.client.resources.metadata.animation.AnimationMetadataSection;
|
||||
import net.minecraft.client.resources.metadata.animation.FrameSize;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
@@ -70,18 +74,16 @@ import net.minecraft.client.sounds.SoundEngine;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.locale.Language;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.chat.ChatSender;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.CommonComponents;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.FormattedText;
|
||||
import net.minecraft.network.chat.MessageSigner;
|
||||
import net.minecraft.network.chat.PlayerChatMessage;
|
||||
import net.minecraft.network.protocol.status.ServerStatus;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.RandomSource;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
@@ -93,6 +95,7 @@ import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.inventory.tooltip.TooltipComponent;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.RecipeManager;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
@@ -100,7 +103,6 @@ import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.FogType;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
@@ -142,17 +144,19 @@ import net.minecraftforge.client.textures.ForgeTextureMetadata;
|
||||
import net.minecraftforge.common.ForgeI18n;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.common.util.ItemStackMap;
|
||||
import net.minecraftforge.event.CreativeModeTabEvent;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.eventbus.api.SubscribeEvent;
|
||||
import net.minecraftforge.fml.IExtensionPoint;
|
||||
import net.minecraftforge.fml.ModList;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.StartupMessageManager;
|
||||
import net.minecraftforge.fml.VersionChecker;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import net.minecraftforge.fml.loading.toposort.CyclePresentException;
|
||||
import net.minecraftforge.fml.loading.toposort.TopologicalSort;
|
||||
import net.minecraftforge.network.NetworkConstants;
|
||||
import net.minecraftforge.network.NetworkRegistry;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import net.minecraftforge.versions.forge.ForgeVersion;
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
@@ -163,6 +167,8 @@ import org.apache.logging.log4j.MarkerManager;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -170,12 +176,14 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
@@ -298,16 +306,6 @@ public class ForgeHooksClient
|
||||
return MinecraftForge.EVENT_BUS.post(new RenderArmEvent(poseStack, multiBufferSource, packedLight, player, arm));
|
||||
}
|
||||
|
||||
public static void onTextureStitchedPre(TextureAtlas map, Set<ResourceLocation> resourceLocations)
|
||||
{
|
||||
StartupMessageManager.mcLoaderConsumer().ifPresent(c->c.accept("Atlas Stitching : "+map.location().toString()));
|
||||
ModLoader.get().postEvent(new TextureStitchEvent.Pre(map, resourceLocations));
|
||||
// ModelLoader.White.INSTANCE.register(map); // TODO Custom TAS
|
||||
Sheets.SIGN_MATERIALS.values().stream()
|
||||
.filter(rm -> rm.atlasLocation().equals(map.location()))
|
||||
.forEach(rm -> resourceLocations.add(rm.texture()));
|
||||
}
|
||||
|
||||
public static void onTextureStitchedPost(TextureAtlas map)
|
||||
{
|
||||
ModLoader.get().postEvent(new TextureStitchEvent.Post(map));
|
||||
@@ -502,22 +500,6 @@ public class ForgeHooksClient
|
||||
};
|
||||
}
|
||||
|
||||
public static void gatherFluidTextures(Set<Material> textures)
|
||||
{
|
||||
if (!ModLoader.isLoadingStateValid()) return;
|
||||
|
||||
ForgeRegistries.FLUIDS.getValues().stream()
|
||||
.flatMap(ForgeHooksClient::getFluidMaterials)
|
||||
.forEach(textures::add);
|
||||
}
|
||||
|
||||
public static Stream<Material> getFluidMaterials(Fluid fluid)
|
||||
{
|
||||
return IClientFluidTypeExtensions.of(fluid).getTextures()
|
||||
.filter(Objects::nonNull)
|
||||
.map(ForgeHooksClient::getBlockMaterial);
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public static Material getBlockMaterial(ResourceLocation loc)
|
||||
{
|
||||
@@ -785,17 +767,39 @@ public class ForgeHooksClient
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TextureAtlasSprite loadTextureAtlasSprite(
|
||||
TextureAtlas textureAtlas,
|
||||
ResourceManager resourceManager, TextureAtlasSprite.Info textureInfo,
|
||||
public static SpriteContents loadSpriteContents(
|
||||
ResourceLocation name,
|
||||
Resource resource,
|
||||
int atlasWidth, int atlasHeight,
|
||||
int spriteX, int spriteY, int mipmapLevel,
|
||||
NativeImage image
|
||||
) throws IOException
|
||||
FrameSize frameSize,
|
||||
NativeImage image,
|
||||
AnimationMetadataSection animationMeta
|
||||
)
|
||||
{
|
||||
ForgeTextureMetadata metadata = ForgeTextureMetadata.forResource(resource);
|
||||
return metadata.getLoader() == null ? null : metadata.getLoader().load(textureAtlas, resourceManager, textureInfo, resource, atlasWidth, atlasHeight, spriteX, spriteY, mipmapLevel, image);
|
||||
try
|
||||
{
|
||||
ForgeTextureMetadata forgeMeta = ForgeTextureMetadata.forResource(resource);
|
||||
return forgeMeta.getLoader() == null ? null : forgeMeta.getLoader().loadContents(name, resource, frameSize, image, animationMeta, forgeMeta);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOGGER.error("Unable to get Forge metadata for {}, falling back to vanilla loading", name);
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static TextureAtlasSprite loadTextureAtlasSprite(
|
||||
ResourceLocation atlasName,
|
||||
SpriteContents contents,
|
||||
int atlasWidth, int atlasHeight,
|
||||
int spriteX, int spriteY, int mipmapLevel
|
||||
)
|
||||
{
|
||||
if (contents.forgeMeta == null || contents.forgeMeta.getLoader() == null)
|
||||
return null;
|
||||
|
||||
return contents.forgeMeta.getLoader().makeSprite(atlasName, contents, atlasWidth, atlasHeight, spriteX, spriteY, mipmapLevel);
|
||||
}
|
||||
|
||||
|
||||
@@ -957,9 +961,16 @@ public class ForgeHooksClient
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Component onClientChat(ChatType.Bound boundChatType, Component message, PlayerChatMessage playerChatMessage, MessageSigner messageSigner)
|
||||
public static Component onClientChat(ChatType.Bound boundChatType, Component message, UUID sender)
|
||||
{
|
||||
ClientChatReceivedEvent event = new ClientChatReceivedEvent(boundChatType, message, playerChatMessage, messageSigner);
|
||||
ClientChatReceivedEvent event = new ClientChatReceivedEvent(boundChatType, message, sender);
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getMessage();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Component onClientPlayerChat(ChatType.Bound boundChatType, Component message, PlayerChatMessage playerChatMessage, UUID sender)
|
||||
{
|
||||
ClientChatReceivedEvent.Player event = new ClientChatReceivedEvent.Player(boundChatType, message, playerChatMessage, sender);
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getMessage();
|
||||
}
|
||||
|
||||
@@ -994,7 +1005,7 @@ public class ForgeHooksClient
|
||||
@SubscribeEvent
|
||||
public static void registerShaders(RegisterShadersEvent event) throws IOException
|
||||
{
|
||||
event.registerShader(new ShaderInstance(event.getResourceManager(), new ResourceLocation("forge","rendertype_entity_unlit_translucent"), DefaultVertexFormat.NEW_ENTITY), (p_172645_) -> {
|
||||
event.registerShader(new ShaderInstance(event.getResourceProvider(), new ResourceLocation("forge","rendertype_entity_unlit_translucent"), DefaultVertexFormat.NEW_ENTITY), (p_172645_) -> {
|
||||
rendertypeEntityTranslucentUnlitShader = p_172645_;
|
||||
});
|
||||
}
|
||||
@@ -1177,4 +1188,107 @@ public class ForgeHooksClient
|
||||
(isRelative ? basePath : "shaders/include/") + loc.getPath());
|
||||
return new ResourceLocation(loc.getNamespace(), normalised);
|
||||
}
|
||||
|
||||
public static CreativeModeTab.DisplayItemsGenerator onCreativeModeTabBuildContents(CreativeModeTab tab, CreativeModeTab.DisplayItemsGenerator originalGenerator) {
|
||||
Set<CreativeModeTabEvent.DisplayItemsAdapter> customGenerators = new HashSet<>();
|
||||
CreativeModeTabEvent.BuildContents event = ModLoader.get().postEventWithReturn(new net.minecraftforge.event.CreativeModeTabEvent.BuildContents(tab, customGenerators));
|
||||
|
||||
record ModificationEntry(CreativeModeTab.TabVisibility tabVisibility, ItemStack before, ItemStack after) {}
|
||||
|
||||
return (featureFlagSet, output, hasPermissions) -> {
|
||||
final Map<ItemStack, CreativeModeTab.TabVisibility> originalEntries = ItemStackMap.createTypeAndTagLinkedMap();
|
||||
final Map<ItemStack, ModificationEntry> entries = ItemStackMap.createTypeAndTagMap();
|
||||
|
||||
originalGenerator.accept(featureFlagSet, originalEntries::put, hasPermissions);
|
||||
customGenerators.forEach(generator -> generator.accept(featureFlagSet, (stack, visibility, before, after) -> {
|
||||
if (stack.getCount() != 1)
|
||||
throw new IllegalArgumentException("The stack count must be 1");
|
||||
|
||||
entries.put(stack, new ModificationEntry(visibility, before, after));
|
||||
}, hasPermissions));
|
||||
|
||||
// We switch to the stacks tag here, as we need to be able to compare and hash them for the graph!
|
||||
// We could not handle this with an open hashset since the builder does not support this internally.
|
||||
final MutableGraph<CompoundTag> graph = GraphBuilder.directed().nodeOrder(ElementOrder.insertion()).build();
|
||||
final Map<CompoundTag, ItemStack> tagToStack = Maps.newHashMap();
|
||||
|
||||
CompoundTag lastStackTag = null;
|
||||
for (ItemStack stack : originalEntries.keySet())
|
||||
{
|
||||
final CompoundTag tag = stack.serializeNBT();
|
||||
tagToStack.put(tag, stack);
|
||||
if (!stack.isEmpty())
|
||||
{
|
||||
graph.addNode(tag);
|
||||
}
|
||||
if (lastStackTag != null)
|
||||
{
|
||||
graph.putEdge(lastStackTag, tag);
|
||||
}
|
||||
lastStackTag = tag;
|
||||
}
|
||||
|
||||
CompoundTag finalLastStackTag = lastStackTag;
|
||||
entries.forEach((stack, modificationEntry) -> {
|
||||
final CompoundTag tag = stack.serializeNBT();
|
||||
if (!stack.isEmpty())
|
||||
{
|
||||
graph.addNode(tag);
|
||||
tagToStack.put(tag, stack);
|
||||
}
|
||||
if (!modificationEntry.after.isEmpty())
|
||||
{
|
||||
final CompoundTag afterTag = modificationEntry.after.serializeNBT();
|
||||
graph.putEdge(afterTag, tag);
|
||||
tagToStack.put(afterTag, modificationEntry.after);
|
||||
}
|
||||
else if (finalLastStackTag != null)
|
||||
{
|
||||
// If the user does not specify an after, we assume it is the last stack and put it after that.
|
||||
graph.putEdge(finalLastStackTag, tag);
|
||||
}
|
||||
if (!modificationEntry.before.isEmpty())
|
||||
{
|
||||
final CompoundTag beforeTag = modificationEntry.before.serializeNBT();
|
||||
graph.putEdge(tag, beforeTag);
|
||||
tagToStack.put(beforeTag, modificationEntry.before);
|
||||
}
|
||||
});
|
||||
|
||||
try
|
||||
{
|
||||
List<CompoundTag> tierList = TopologicalSort.topologicalSort(graph, null);
|
||||
|
||||
// Now we unwind the tags again so that they are sorted neatly.
|
||||
for (CompoundTag tag : tierList)
|
||||
{
|
||||
final ItemStack stack = tagToStack.get(tag);
|
||||
if (originalEntries.containsKey(stack))
|
||||
{
|
||||
output.accept(stack, originalEntries.get(stack));
|
||||
}
|
||||
else if (entries.containsKey(stack))
|
||||
{
|
||||
output.accept(stack, entries.get(stack).tabVisibility);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (CyclePresentException cyclePresentException)
|
||||
{
|
||||
LOGGER.error("Failed to inject custom items into creative mode tab {} due to a cycle in the dependency graph", tab, cyclePresentException);
|
||||
LOGGER.warn("Detected cycles:");
|
||||
for (Set<Object> cycle : cyclePresentException.getCycles())
|
||||
{
|
||||
graph.edges().forEach(edge -> {
|
||||
if (cycle.contains(edge.nodeU()) && cycle.contains(edge.nodeV()))
|
||||
{
|
||||
LOGGER.warn(" - {} -> {}", tagToStack.get(edge.nodeU()), tagToStack.get(edge.nodeV()));
|
||||
}
|
||||
});
|
||||
}
|
||||
LOGGER.error("Falling back to default!");
|
||||
originalGenerator.accept(featureFlagSet, output, hasPermissions);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,13 +8,13 @@ package net.minecraftforge.client.event;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MessageSigner;
|
||||
import net.minecraft.network.chat.PlayerChatMessage;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Fired when a chat message is received on the client.
|
||||
@@ -33,16 +33,14 @@ public class ClientChatReceivedEvent extends Event
|
||||
{
|
||||
private Component message;
|
||||
private final ChatType.Bound boundChatType;
|
||||
private final PlayerChatMessage playerChatMessage;
|
||||
private final MessageSigner messageSigner;
|
||||
private final UUID sender;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public ClientChatReceivedEvent(ChatType.Bound boundChatType, Component message, PlayerChatMessage playerChatMessage, MessageSigner messageSigner)
|
||||
public ClientChatReceivedEvent(ChatType.Bound boundChatType, Component message, UUID sender)
|
||||
{
|
||||
this.boundChatType = boundChatType;
|
||||
this.message = message;
|
||||
this.playerChatMessage = playerChatMessage;
|
||||
this.messageSigner = messageSigner;
|
||||
this.sender = sender;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,22 +71,12 @@ public class ClientChatReceivedEvent extends Event
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the full player chat message}.
|
||||
* This contains the sender UUID, various signing data, and the optional unsigned contents.
|
||||
* {@return the message sender}.
|
||||
* This will be {@link Util#NIL_UUID} if the message is a system message.
|
||||
*/
|
||||
public PlayerChatMessage getPlayerChatMessage()
|
||||
public UUID getSender()
|
||||
{
|
||||
return this.playerChatMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the message signer}.
|
||||
* This contains the sender UUID, timestamp of message creation, and signature salt.
|
||||
* The {@linkplain MessageSigner#profileId() sender UUID} will be {@link Util#NIL_UUID} if the message is a system message.
|
||||
*/
|
||||
public MessageSigner getMessageSigner()
|
||||
{
|
||||
return this.messageSigner;
|
||||
return this.sender;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -96,6 +84,38 @@ public class ClientChatReceivedEvent extends Event
|
||||
*/
|
||||
public boolean isSystem()
|
||||
{
|
||||
return this.messageSigner.isSystem();
|
||||
return this.sender.equals(Util.NIL_UUID);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when a player chat message is received on the client.
|
||||
*
|
||||
* <p>This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If the event is cancelled, the message is not displayed in the chat message window.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*
|
||||
* @see ChatType
|
||||
*/
|
||||
public static class Player extends ClientChatReceivedEvent
|
||||
{
|
||||
private final PlayerChatMessage playerChatMessage;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public Player(ChatType.Bound boundChatType, Component message, PlayerChatMessage playerChatMessage, UUID sender)
|
||||
{
|
||||
super(boundChatType, message, sender);
|
||||
this.playerChatMessage = playerChatMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the full player chat message}.
|
||||
* This contains the sender UUID, various signing data, and the optional unsigned contents.
|
||||
*/
|
||||
public PlayerChatMessage getPlayerChatMessage()
|
||||
{
|
||||
return this.playerChatMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ package net.minecraftforge.client.event;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.client.renderer.ShaderInstance;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.ResourceProvider;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
@@ -29,29 +30,29 @@ import java.util.function.Consumer;
|
||||
*/
|
||||
public class RegisterShadersEvent extends Event implements IModBusEvent
|
||||
{
|
||||
private final ResourceManager resourceManager;
|
||||
private final ResourceProvider resourceProvider;
|
||||
private final List<Pair<ShaderInstance, Consumer<ShaderInstance>>> shaderList;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RegisterShadersEvent(ResourceManager resourceManager, List<Pair<ShaderInstance, Consumer<ShaderInstance>>> shaderList)
|
||||
public RegisterShadersEvent(ResourceProvider resourceProvider, List<Pair<ShaderInstance, Consumer<ShaderInstance>>> shaderList)
|
||||
{
|
||||
this.resourceManager = resourceManager;
|
||||
this.resourceProvider = resourceProvider;
|
||||
this.shaderList = shaderList;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the client-side resource manager}
|
||||
* {@return the client-side resource provider}
|
||||
*/
|
||||
public ResourceManager getResourceManager()
|
||||
public ResourceProvider getResourceProvider()
|
||||
{
|
||||
return resourceManager;
|
||||
return resourceProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a shader, and a callback for when the shader is loaded.
|
||||
*
|
||||
* <p>When creating a {@link ShaderInstance}, pass in the {@linkplain #getResourceManager()
|
||||
* client-side resource manager} as the resource provider.</p>
|
||||
* <p>When creating a {@link ShaderInstance}, pass in the {@linkplain #getResourceProvider()
|
||||
* client-side resource provider} as the resource provider.</p>
|
||||
*
|
||||
* <p>Mods should not store the shader instance passed into this method. Instead, mods should store the shader
|
||||
* passed into the registered load callback.</p>
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
/**
|
||||
* Fired after all level rendering.
|
||||
|
||||
@@ -11,7 +11,6 @@ import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
@@ -21,13 +20,14 @@ import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.ForgeRenderTypes;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
/**
|
||||
* Fires at various times during LevelRenderer.renderLevel.
|
||||
* Fires at various times during LevelRenderer.renderLevel.
|
||||
* Check {@link #getStage} to render during the appropriate time for your use case.
|
||||
*
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}. </p>
|
||||
*
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}. </p>
|
||||
*/
|
||||
@@ -122,9 +122,9 @@ public class RenderLevelStageEvent extends Event
|
||||
/**
|
||||
* Use to create a custom {@linkplain RenderLevelStageEvent.Stage stages}.
|
||||
* Fired after the LevelRenderer has been created.
|
||||
*
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}. </p>
|
||||
*
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}. </p>
|
||||
*/
|
||||
@@ -184,7 +184,7 @@ public class RenderLevelStageEvent extends Event
|
||||
* Use this to render custom effects into the world, such as custom entity-like objects or special rendering effects.
|
||||
* Called within a fabulous graphics target.
|
||||
* Happens after entities render.
|
||||
*
|
||||
*
|
||||
* @see ForgeRenderTypes#TRANSLUCENT_ON_PARTICLES_TARGET
|
||||
*/
|
||||
public static final Stage AFTER_PARTICLES = register("after_particles", null);
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package net.minecraftforge.client.event;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
@@ -17,10 +16,8 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Fired before and after a texture atlas stitched together.
|
||||
* See the two subclasses to listen for before and after stitching.
|
||||
* Fired after a texture atlas is stitched together.
|
||||
*
|
||||
* @see TextureStitchEvent.Pre
|
||||
* @see TextureStitchEvent.Post
|
||||
* @see TextureAtlas
|
||||
*/
|
||||
@@ -42,39 +39,40 @@ public class TextureStitchEvent extends Event implements IModBusEvent
|
||||
return atlas;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Fired <b>before</b> a texture atlas is stitched together.
|
||||
* This can be used to add custom sprites to be stitched into the atlas.</p>
|
||||
*
|
||||
* <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.</p>
|
||||
*
|
||||
* <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus()} mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
*/
|
||||
public static class Pre extends TextureStitchEvent
|
||||
{
|
||||
private final Set<ResourceLocation> sprites;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public Pre(TextureAtlas map, Set<ResourceLocation> sprites)
|
||||
{
|
||||
super(map);
|
||||
this.sprites = sprites;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a sprite to be stitched into the texture atlas.
|
||||
*
|
||||
* <p>Callers should check that the atlas which the event is fired for is the atlas they wish to stitch the
|
||||
* sprite into, as otherwise they would be stitching the sprite into all atlases.</p>
|
||||
*
|
||||
* @param sprite the location of the sprite
|
||||
*/
|
||||
public boolean addSprite(ResourceLocation sprite)
|
||||
{
|
||||
return this.sprites.add(sprite);
|
||||
}
|
||||
}
|
||||
// Use atlas info JSON files instead
|
||||
// /**
|
||||
// * <p>Fired <b>before</b> a texture atlas is stitched together.
|
||||
// * This can be used to add custom sprites to be stitched into the atlas.</p>
|
||||
// *
|
||||
// * <p>This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.</p>
|
||||
// *
|
||||
// * <p>This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus()} mod-specific event bus},
|
||||
// * only on the {@linkplain LogicalSide#CLIENT logical client}.</p>
|
||||
// */
|
||||
// public static class Pre extends TextureStitchEvent
|
||||
// {
|
||||
// private final Set<ResourceLocation> sprites;
|
||||
//
|
||||
// @ApiStatus.Internal
|
||||
// public Pre(TextureAtlas map, Set<ResourceLocation> sprites)
|
||||
// {
|
||||
// super(map);
|
||||
// this.sprites = sprites;
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Adds a sprite to be stitched into the texture atlas.
|
||||
// *
|
||||
// * <p>Callers should check that the atlas which the event is fired for is the atlas they wish to stitch the
|
||||
// * sprite into, as otherwise they would be stitching the sprite into all atlases.</p>
|
||||
// *
|
||||
// * @param sprite the location of the sprite
|
||||
// */
|
||||
// public boolean addSprite(ResourceLocation sprite)
|
||||
// {
|
||||
// return this.sprites.add(sprite);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Fired <b>after</b> a texture atlas is stitched together and all textures therein has been loaded.
|
||||
|
||||
+2
-2
@@ -6,12 +6,12 @@
|
||||
package net.minecraftforge.client.extensions;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.DimensionSpecialEffects;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* Extension interface for {@link DimensionSpecialEffects}.
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.extensions;
|
||||
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.util.function.Function;
|
||||
|
||||
public interface IForgeModelBaker
|
||||
{
|
||||
@Nullable
|
||||
BakedModel bake(ResourceLocation location, ModelState state, Function<Material, TextureAtlasSprite> sprites);
|
||||
|
||||
Function<Material, TextureAtlasSprite> getModelTextureGetter();
|
||||
}
|
||||
@@ -7,7 +7,7 @@ package net.minecraftforge.client.extensions;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* Extension interface for {@link com.mojang.blaze3d.vertex.PoseStack}.
|
||||
|
||||
@@ -8,12 +8,12 @@ package net.minecraftforge.client.extensions;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.core.Direction;
|
||||
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import com.mojang.math.Vector4f;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
/**
|
||||
* Extension interface for {@link Transformation}.
|
||||
@@ -58,7 +58,7 @@ public interface IForgeTransformation
|
||||
*/
|
||||
default void transformPosition(Vector4f position)
|
||||
{
|
||||
position.transform(self().getMatrix());
|
||||
position.mul(self().getMatrix());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +68,7 @@ public interface IForgeTransformation
|
||||
*/
|
||||
default void transformNormal(Vector3f normal)
|
||||
{
|
||||
normal.transform(self().getNormalMatrix());
|
||||
normal.mul(self().getNormalMatrix());
|
||||
normal.normalize();
|
||||
}
|
||||
|
||||
@@ -120,11 +120,10 @@ public interface IForgeTransformation
|
||||
if (transform.isIdentity()) return Transformation.identity();
|
||||
|
||||
Matrix4f ret = transform.getMatrix();
|
||||
Matrix4f tmp = Matrix4f.createTranslateMatrix(origin.x(), origin.y(), origin.z());
|
||||
ret.multiplyBackward(tmp);
|
||||
tmp.setIdentity();
|
||||
tmp.setTranslation(-origin.x(), -origin.y(), -origin.z());
|
||||
ret.multiply(tmp);
|
||||
Matrix4f tmp = new Matrix4f().translation(origin.x(), origin.y(), origin.z());
|
||||
tmp.mul(ret, ret);
|
||||
tmp.translation(-origin.x(), -origin.y(), -origin.z());
|
||||
ret.mul(tmp);
|
||||
return new Transformation(ret);
|
||||
}
|
||||
}
|
||||
@@ -8,10 +8,10 @@ package net.minecraftforge.client.extensions;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||
import com.mojang.math.Matrix3f;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraftforge.client.model.IQuadTransformer;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
@@ -63,7 +63,7 @@ public interface IForgeVertexConsumer
|
||||
if (nx != 0 || ny != 0 || nz != 0)
|
||||
{
|
||||
generated.set(nx / 127f, ny / 127f, nz / 127f);
|
||||
generated.transform(normalTransform);
|
||||
generated.mul(normalTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -5,7 +5,6 @@
|
||||
|
||||
package net.minecraftforge.client.extensions.common;
|
||||
|
||||
import com.mojang.math.Vector3d;
|
||||
import net.minecraft.client.particle.ParticleEngine;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
@@ -19,6 +18,7 @@ import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.joml.Vector3d;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -71,7 +71,7 @@ public interface IClientBlockExtensions
|
||||
*/
|
||||
default boolean addDestroyEffects(BlockState state, Level Level, BlockPos pos, ParticleEngine manager)
|
||||
{
|
||||
return false;
|
||||
return !state.shouldSpawnParticlesOnBreak();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+18
-27
@@ -6,21 +6,14 @@
|
||||
package net.minecraftforge.client.extensions.common;
|
||||
|
||||
import com.mojang.blaze3d.shaders.FogShape;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.BufferUploader;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Vector3f;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.FogRenderer;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.ScreenEffectRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -33,10 +26,7 @@ import net.minecraftforge.fluids.FluidType;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Stream;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* {@linkplain LogicalSide#CLIENT Client-only} extensions to {@link FluidType}.
|
||||
@@ -130,19 +120,20 @@ public interface IClientFluidTypeExtensions
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of textures applied to a fluid.
|
||||
*
|
||||
* <p>This is used by the {@link net.minecraft.client.resources.model.ModelBakery} to load in all textures that
|
||||
* can be applied on reload.
|
||||
*
|
||||
* @return a stream of textures applied to a fluid
|
||||
*/
|
||||
default Stream<ResourceLocation> getTextures()
|
||||
{
|
||||
return Stream.of(this.getStillTexture(), this.getFlowingTexture(), this.getOverlayTexture())
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
// Add entries to assets/minecraft/atlases/blocks.json if your texture location is not already covered by the default atlas search locations.
|
||||
// /**
|
||||
// * Returns a stream of textures applied to a fluid.
|
||||
// *
|
||||
// * <p>This is used by the {@link net.minecraft.client.resources.model.ModelBakery} to load in all textures that
|
||||
// * can be applied on reload.
|
||||
// *
|
||||
// * @return a stream of textures applied to a fluid
|
||||
// */
|
||||
// default Stream<ResourceLocation> getTextures()
|
||||
// {
|
||||
// return Stream.of(this.getStillTexture(), this.getFlowingTexture(), this.getOverlayTexture())
|
||||
// .filter(Objects::nonNull);
|
||||
// }
|
||||
|
||||
/**
|
||||
* Returns the location of the texture to apply to the camera when it is
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.client.gui;
|
||||
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.CreativeModeTabs;
|
||||
import net.minecraftforge.common.util.ConcatenatedListView;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class CreativeTabsScreenPage
|
||||
{
|
||||
private final List<CreativeModeTab> tabs;
|
||||
private final List<CreativeModeTab> topTabs;
|
||||
private final List<CreativeModeTab> bottomTabs;
|
||||
private final ConcatenatedListView<CreativeModeTab> visibleTabs;
|
||||
|
||||
public CreativeTabsScreenPage(List<CreativeModeTab> tabs)
|
||||
{
|
||||
this.tabs = tabs;
|
||||
this.topTabs = new ArrayList<>();
|
||||
this.bottomTabs = new ArrayList<>();
|
||||
this.visibleTabs = ConcatenatedListView.of(tabs, CreativeModeTabs.defaultTabs());
|
||||
|
||||
int maxLength = 10;
|
||||
int topLength = maxLength / 2;
|
||||
int length = Math.min(10, tabs.size());
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
CreativeModeTab tab = tabs.get(i);
|
||||
(i < topLength ? this.topTabs : this.bottomTabs).add(tab);
|
||||
}
|
||||
}
|
||||
|
||||
public List<CreativeModeTab> getVisibleTabs()
|
||||
{
|
||||
return this.visibleTabs.stream().filter(CreativeModeTab::shouldDisplay).toList();
|
||||
}
|
||||
|
||||
public boolean isTop(CreativeModeTab tab)
|
||||
{
|
||||
if (!this.tabs.contains(tab))
|
||||
return CreativeModeTabs.defaultTabs().indexOf(tab) < (CreativeModeTabs.defaultTabs().size() / 2);
|
||||
|
||||
return this.topTabs.contains(tab);
|
||||
}
|
||||
|
||||
public int getColumn(CreativeModeTab tab)
|
||||
{
|
||||
if (!this.tabs.contains(tab))
|
||||
return (CreativeModeTabs.defaultTabs().indexOf(tab) % (CreativeModeTabs.defaultTabs().size() / 2)) + 5;
|
||||
|
||||
return this.topTabs.contains(tab) ? this.topTabs.indexOf(tab) : this.bottomTabs.indexOf(tab);
|
||||
}
|
||||
|
||||
public CreativeModeTab getDefaultTab()
|
||||
{
|
||||
return this.tabs.get(0);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ import java.util.stream.Collectors;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.gui.narration.NarrationElementOutput;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.server.packs.resources.IoSupplier;
|
||||
import net.minecraftforge.client.ConfigScreenHandler;
|
||||
import net.minecraftforge.client.gui.widget.ModListWidget;
|
||||
import net.minecraftforge.client.gui.widget.ScrollPanel;
|
||||
@@ -264,14 +265,14 @@ public class ModListScreen extends Screen
|
||||
int y = this.height - 20 - PADDING;
|
||||
int fullButtonHeight = PADDING + 20 + PADDING;
|
||||
|
||||
doneButton = new Button(((listWidth + PADDING + this.width - doneButtonWidth) / 2), y, doneButtonWidth, 20, Component.translatable("gui.done"), b -> ModListScreen.this.onClose());
|
||||
openModsFolderButton = new Button(6, y, this.listWidth, 20, Component.translatable("fml.menu.mods.openmodsfolder"), b -> Util.getPlatform().openFile(FMLPaths.MODSDIR.get().toFile()));
|
||||
doneButton = Button.builder(Component.translatable("gui.done"), b -> ModListScreen.this.onClose()).bounds(((listWidth + PADDING + this.width - doneButtonWidth) / 2), y, doneButtonWidth, 20).build();
|
||||
openModsFolderButton = Button.builder(Component.translatable("fml.menu.mods.openmodsfolder"), b -> Util.getPlatform().openFile(FMLPaths.MODSDIR.get().toFile())).bounds(6, y, this.listWidth, 20).build();
|
||||
y -= 20 + PADDING;
|
||||
configButton = new Button(6, y, this.listWidth, 20, Component.translatable("fml.menu.mods.config"), b -> ModListScreen.this.displayModConfig());
|
||||
configButton = Button.builder(Component.translatable("fml.menu.mods.config"), b -> ModListScreen.this.displayModConfig()).bounds(6, y, this.listWidth, 20).build();
|
||||
y -= 14 + PADDING;
|
||||
search = new EditBox(getFontRenderer(), PADDING + 1, y, listWidth - 2, 14, Component.translatable("fml.menu.mods.search"));
|
||||
|
||||
this.modList = new ModListWidget(this, listWidth, fullButtonHeight, search.y - getFontRenderer().lineHeight - PADDING);
|
||||
this.modList = new ModListWidget(this, listWidth, fullButtonHeight, search.getY() - getFontRenderer().lineHeight - PADDING);
|
||||
this.modList.setLeftPos(6);
|
||||
this.modInfo = new InfoPanel(this.minecraft, modInfoWidth, this.height - PADDING - fullButtonHeight, PADDING);
|
||||
|
||||
@@ -288,11 +289,11 @@ public class ModListScreen extends Screen
|
||||
|
||||
final int width = listWidth / numButtons;
|
||||
int x = PADDING;
|
||||
addRenderableWidget(SortType.NORMAL.button = new Button(x, PADDING, width - buttonMargin, 20, SortType.NORMAL.getButtonText(), b -> resortMods(SortType.NORMAL)));
|
||||
addRenderableWidget(SortType.NORMAL.button = Button.builder(SortType.NORMAL.getButtonText(), b -> resortMods(SortType.NORMAL)).bounds(x, PADDING, width - buttonMargin, 20).build());
|
||||
x += width + buttonMargin;
|
||||
addRenderableWidget(SortType.A_TO_Z.button = new Button(x, PADDING, width - buttonMargin, 20, SortType.A_TO_Z.getButtonText(), b -> resortMods(SortType.A_TO_Z)));
|
||||
addRenderableWidget(SortType.A_TO_Z.button = Button.builder(SortType.A_TO_Z.getButtonText(), b -> resortMods(SortType.A_TO_Z)).bounds(x, PADDING, width - buttonMargin, 20).build());
|
||||
x += width + buttonMargin;
|
||||
addRenderableWidget(SortType.Z_TO_A.button = new Button(x, PADDING, width - buttonMargin, 20, SortType.Z_TO_A.getButtonText(), b -> resortMods(SortType.Z_TO_A)));
|
||||
addRenderableWidget(SortType.Z_TO_A.button = Button.builder(SortType.Z_TO_A.getButtonText(), b -> resortMods(SortType.Z_TO_A)).bounds(x, PADDING, width - buttonMargin, 20).build());
|
||||
resortMods(SortType.NORMAL);
|
||||
updateCache();
|
||||
}
|
||||
@@ -371,7 +372,7 @@ public class ModListScreen extends Screen
|
||||
int x = modList.getLeft() + ((modList.getRight() - modList.getLeft()) / 2) - (getFontRenderer().width(text) / 2);
|
||||
this.search.render(poseStack, mouseX , mouseY, partialTick);
|
||||
super.render(poseStack, mouseX, mouseY, partialTick);
|
||||
getFontRenderer().draw(poseStack, text.getVisualOrderText(), x, search.y - getFontRenderer().lineHeight, 0xFFFFFF);
|
||||
getFontRenderer().draw(poseStack, text.getVisualOrderText(), x, search.getY() - getFontRenderer().lineHeight, 0xFFFFFF);
|
||||
}
|
||||
|
||||
public Minecraft getMinecraftInstance()
|
||||
@@ -412,9 +413,9 @@ public class ModListScreen extends Screen
|
||||
try
|
||||
{
|
||||
NativeImage logo = null;
|
||||
InputStream logoResource = resourcePack.getRootResource(logoFile);
|
||||
IoSupplier<InputStream> logoResource = resourcePack.getRootResource(logoFile);
|
||||
if (logoResource != null)
|
||||
logo = NativeImage.read(logoResource);
|
||||
logo = NativeImage.read(logoResource.get());
|
||||
if (logo != null)
|
||||
{
|
||||
|
||||
|
||||
@@ -90,9 +90,15 @@ public class ModMismatchDisconnectedScreen extends Screen
|
||||
this.addRenderableWidget(new MismatchInfoPanel(minecraft, listWidth, listHeight, (this.height - this.listHeight) / 2, listLeft));
|
||||
|
||||
int buttonWidth = Math.min(210, this.width / 2 - 20);
|
||||
this.addRenderableWidget(new Button(Math.max(this.width / 4 - buttonWidth / 2, listLeft), upperButtonHeight, buttonWidth, 20, Component.literal(ForgeI18n.parseMessage("fml.button.open.file", logFile.getFileName())), button -> Util.getPlatform().openFile(logFile.toFile())));
|
||||
this.addRenderableWidget(new Button(Math.min(this.width * 3 / 4 - buttonWidth / 2, listLeft + listWidth - buttonWidth), upperButtonHeight, buttonWidth, 20, Component.literal(ForgeI18n.parseMessage("fml.button.open.mods.folder")), button -> Util.getPlatform().openFile(modsDir.toFile())));
|
||||
this.addRenderableWidget(new Button((this.width - buttonWidth) / 2, lowerButtonHeight, buttonWidth, 20, Component.translatable("gui.toMenu"), button -> this.minecraft.setScreen(this.parent)));
|
||||
this.addRenderableWidget(Button.builder(Component.literal(ForgeI18n.parseMessage("fml.button.open.file", logFile.getFileName())), button -> Util.getPlatform().openFile(logFile.toFile()))
|
||||
.bounds(Math.max(this.width / 4 - buttonWidth / 2, listLeft), upperButtonHeight, buttonWidth, 20)
|
||||
.build());
|
||||
this.addRenderableWidget(Button.builder(Component.literal(ForgeI18n.parseMessage("fml.button.open.mods.folder")), button -> Util.getPlatform().openFile(modsDir.toFile()))
|
||||
.bounds(Math.min(this.width * 3 / 4 - buttonWidth / 2, listLeft + listWidth - buttonWidth), upperButtonHeight, buttonWidth, 20)
|
||||
.build());
|
||||
this.addRenderableWidget(Button.builder(Component.translatable("gui.toMenu"), button -> this.minecraft.setScreen(this.parent))
|
||||
.bounds((this.width - buttonWidth) / 2, lowerButtonHeight, buttonWidth, 20)
|
||||
.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -12,10 +12,10 @@ import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import com.mojang.math.Matrix4f;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
/**
|
||||
* This class provides several methods and constants used by the Config GUI classes.
|
||||
|
||||
@@ -59,8 +59,8 @@ public class TitleScreenModUpdateIndicator extends Screen
|
||||
|
||||
RenderSystem.setShaderTexture(0, VERSION_CHECK_ICONS);
|
||||
|
||||
int x = modButton.x;
|
||||
int y = modButton.y;
|
||||
int x = modButton.getX();
|
||||
int y = modButton.getY();
|
||||
int w = modButton.getWidth();
|
||||
int h = modButton.getHeight();
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.client.gui.overlay;
|
||||
|
||||
import com.mojang.blaze3d.platform.Window;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.Util;
|
||||
@@ -22,6 +23,7 @@ import net.minecraft.util.StringUtil;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.PlayerRideableJumping;
|
||||
import net.minecraft.world.entity.ai.attributes.AttributeInstance;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
@@ -420,13 +422,13 @@ public class ForgeGui extends Gui
|
||||
}
|
||||
|
||||
@Override
|
||||
public void renderJumpMeter(PoseStack poseStack, int x)
|
||||
public void renderJumpMeter(PlayerRideableJumping playerRideableJumping, PoseStack poseStack, int x)
|
||||
{
|
||||
bind(GUI_ICONS_LOCATION);
|
||||
RenderSystem.setShaderColor(1.0F, 1.0F, 1.0F, 1.0F);
|
||||
RenderSystem.disableBlend();
|
||||
|
||||
super.renderJumpMeter(poseStack, x);
|
||||
super.renderJumpMeter(playerRideableJumping, poseStack, x);
|
||||
|
||||
RenderSystem.enableBlend();
|
||||
minecraft.getProfiler().pop();
|
||||
@@ -572,12 +574,16 @@ public class ForgeGui extends Gui
|
||||
{
|
||||
minecraft.getProfiler().push("chat");
|
||||
|
||||
var event = new CustomizeGuiOverlayEvent.Chat(minecraft.getWindow(), pStack, minecraft.getFrameTime(), 0, height - 48);
|
||||
Window window = minecraft.getWindow();
|
||||
var event = new CustomizeGuiOverlayEvent.Chat(window, pStack, minecraft.getFrameTime(), 0, height - 48);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
|
||||
pStack.pushPose();
|
||||
pStack.translate(event.getPosX(), event.getPosY(), 0.0D);
|
||||
chat.render(pStack, tickCount);
|
||||
// We give the absolute Y position of the chat component in the event and account for the chat component's own offsetting here.
|
||||
pStack.translate(event.getPosX(), (event.getPosY() - height + 40) / chat.getScale(), 0.0D);
|
||||
int mouseX = Mth.floor(minecraft.mouseHandler.xpos() * window.getGuiScaledWidth() / window.getScreenWidth());
|
||||
int mouseY = Mth.floor(minecraft.mouseHandler.ypos() * window.getGuiScaledHeight() / window.getScreenHeight());
|
||||
chat.render(pStack, tickCount, mouseX, mouseY);
|
||||
pStack.popPose();
|
||||
|
||||
minecraft.getProfiler().pop();
|
||||
|
||||
@@ -10,6 +10,7 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.PlayerRideableJumping;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.scores.Objective;
|
||||
import net.minecraft.world.scores.PlayerTeam;
|
||||
@@ -119,14 +120,15 @@ public enum VanillaGuiOverlay
|
||||
}
|
||||
}),
|
||||
JUMP_BAR("jump_bar", (gui, poseStack, partialTick, screenWidth, screenHeight) -> {
|
||||
if (gui.getMinecraft().player.isRidingJumpable() && !gui.getMinecraft().options.hideGui)
|
||||
PlayerRideableJumping playerRideableJumping = gui.getMinecraft().player.jumpableVehicle();
|
||||
if (playerRideableJumping != null && !gui.getMinecraft().options.hideGui)
|
||||
{
|
||||
gui.setupOverlayRenderState(true, false);
|
||||
gui.renderJumpMeter(poseStack, screenWidth / 2 - 91);
|
||||
gui.renderJumpMeter(playerRideableJumping, poseStack, screenWidth / 2 - 91);
|
||||
}
|
||||
}),
|
||||
EXPERIENCE_BAR("experience_bar", (gui, poseStack, partialTick, screenWidth, screenHeight) -> {
|
||||
if (!gui.getMinecraft().player.isRidingJumpable() && !gui.getMinecraft().options.hideGui)
|
||||
if (gui.getMinecraft().player.jumpableVehicle() == null && !gui.getMinecraft().options.hideGui)
|
||||
{
|
||||
gui.setupOverlayRenderState(true, false);
|
||||
gui.renderExperience(screenWidth / 2 - 91, poseStack);
|
||||
|
||||
@@ -25,7 +25,12 @@ public class ExtendedButton extends Button
|
||||
{
|
||||
public ExtendedButton(int xPos, int yPos, int width, int height, Component displayString, OnPress handler)
|
||||
{
|
||||
super(xPos, yPos, width, height, displayString, handler);
|
||||
this(xPos, yPos, width, height, displayString, handler, DEFAULT_NARRATION);
|
||||
}
|
||||
|
||||
public ExtendedButton(int xPos, int yPos, int width, int height, Component displayString, OnPress handler, CreateNarration createNarration)
|
||||
{
|
||||
super(xPos, yPos, width, height, displayString, handler, createNarration);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -36,7 +41,7 @@ public class ExtendedButton extends Button
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
int k = this.getYImage(this.isHovered);
|
||||
ScreenUtils.blitWithBorder(poseStack, WIDGETS_LOCATION, this.x, this.y, 0, 46 + k * 20, this.width, this.height, 200, 20, 2, 3, 2, 2, this.getBlitOffset());
|
||||
ScreenUtils.blitWithBorder(poseStack, WIDGETS_LOCATION, this.getX(), this.getY(), 0, 46 + k * 20, this.width, this.height, 200, 20, 2, 3, 2, 2, this.getBlitOffset());
|
||||
this.renderBg(poseStack, mc, mouseX, mouseY);
|
||||
|
||||
Component buttonText = this.getMessage();
|
||||
@@ -47,6 +52,6 @@ public class ExtendedButton extends Button
|
||||
//TODO, srg names make it hard to figure out how to append to an ITextProperties from this trim operation, wraping this in StringTextComponent is kinda dirty.
|
||||
buttonText = Component.literal(mc.font.substrByWidth(buttonText, width - 6 - ellipsisWidth).getString() + "...");
|
||||
|
||||
drawCenteredString(poseStack, mc.font, buttonText, this.x + this.width / 2, this.y + (this.height - 8) / 2, getFGColor());
|
||||
drawCenteredString(poseStack, mc.font, buttonText, this.getX() + this.width / 2, this.getY() + (this.height - 8) / 2, getFGColor());
|
||||
}
|
||||
}
|
||||
@@ -160,7 +160,7 @@ public class ForgeSlider extends AbstractSliderButton
|
||||
|
||||
private void setValueFromMouse(double mouseX)
|
||||
{
|
||||
this.setSliderValue((mouseX - (this.x + 4)) / (this.width - 8));
|
||||
this.setSliderValue((mouseX - (this.getX() + 4)) / (this.width - 8));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,6 +13,7 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.Tesselator;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import net.minecraft.client.gui.components.Renderable;
|
||||
import net.minecraft.client.gui.narration.NarratableEntry;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
|
||||
@@ -22,13 +23,12 @@ import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiComponent;
|
||||
import net.minecraft.client.gui.components.events.AbstractContainerEventHandler;
|
||||
import net.minecraft.client.gui.components.events.GuiEventListener;
|
||||
import net.minecraft.client.gui.components.Widget;
|
||||
import net.minecraftforge.client.gui.ScreenUtils;
|
||||
|
||||
/**
|
||||
* Abstract scroll panel class.
|
||||
*/
|
||||
public abstract class ScrollPanel extends AbstractContainerEventHandler implements Widget, NarratableEntry
|
||||
public abstract class ScrollPanel extends AbstractContainerEventHandler implements Renderable, NarratableEntry
|
||||
{
|
||||
private final Minecraft client;
|
||||
protected final int width;
|
||||
|
||||
@@ -34,9 +34,9 @@ public class UnicodeGlyphButton extends ExtendedButton
|
||||
if (this.visible)
|
||||
{
|
||||
Minecraft mc = Minecraft.getInstance();
|
||||
this.isHovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
|
||||
this.isHovered = mouseX >= this.getX() && mouseY >= this.getY() && mouseX < this.getX() + this.width && mouseY < this.getY() + this.height;
|
||||
int k = this.getYImage(this.isHovered);
|
||||
ScreenUtils.blitWithBorder(poseStack, WIDGETS_LOCATION, this.x, this.y, 0, 46 + k * 20, this.width, this.height, 200, 20, 2, 3, 2, 2, this.getBlitOffset());
|
||||
ScreenUtils.blitWithBorder(poseStack, WIDGETS_LOCATION, this.getX(), this.getY(), 0, 46 + k * 20, this.width, this.height, 200, 20, 2, 3, 2, 2, this.getBlitOffset());
|
||||
this.renderBg(poseStack, mc, mouseX, mouseY);
|
||||
|
||||
Component buttonText = this.createNarrationMessage();
|
||||
@@ -54,12 +54,12 @@ public class UnicodeGlyphButton extends ExtendedButton
|
||||
poseStack.pushPose();
|
||||
poseStack.scale(glyphScale, glyphScale, 1.0F);
|
||||
this.drawCenteredString(poseStack, mc.font, Component.literal(glyph),
|
||||
(int) (((this.x + (this.width / 2) - (strWidth / 2)) / glyphScale) - (glyphWidth / (2 * glyphScale)) + 2),
|
||||
(int) (((this.y + ((this.height - 8) / glyphScale) / 2) - 1) / glyphScale), getFGColor());
|
||||
(int) (((this.getX() + (this.width / 2) - (strWidth / 2)) / glyphScale) - (glyphWidth / (2 * glyphScale)) + 2),
|
||||
(int) (((this.getY() + ((this.height - 8) / glyphScale) / 2) - 1) / glyphScale), getFGColor());
|
||||
poseStack.popPose();
|
||||
|
||||
this.drawCenteredString(poseStack, mc.font, buttonText, (int) (this.x + (this.width / 2) + (glyphWidth / glyphScale)),
|
||||
this.y + (this.height - 8) / 2, getFGColor());
|
||||
this.drawCenteredString(poseStack, mc.font, buttonText, (int) (this.getX() + (this.width / 2) + (glyphWidth / glyphScale)),
|
||||
this.getY() + (this.height - 8) / 2, getFGColor());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class ClientModLoader
|
||||
}
|
||||
}
|
||||
}
|
||||
public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager, ClientPackSource metadataSerializer)
|
||||
public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager)
|
||||
{
|
||||
// force log4j to shutdown logging in a shutdown hook. This is because we disable default shutdown hook so the server properly logs it's shutdown
|
||||
Runtime.getRuntime().addShutdownHook(new Thread(LogManager::shutdown));
|
||||
@@ -183,31 +183,34 @@ public class ClientModLoader
|
||||
}
|
||||
|
||||
private static RepositorySource buildPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks) {
|
||||
return (packList, factory) -> clientPackFinder(modResourcePacks, packList, factory);
|
||||
return packAcceptor -> clientPackFinder(modResourcePacks, packAcceptor);
|
||||
}
|
||||
|
||||
private static void clientPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks, Consumer<Pack> consumer, Pack.PackConstructor factory) {
|
||||
private static void clientPackFinder(Map<IModFile, ? extends PathPackResources> modResourcePacks, Consumer<Pack> packAcceptor) {
|
||||
List<PathPackResources> hiddenPacks = new ArrayList<>();
|
||||
for (Entry<IModFile, ? extends PathPackResources> e : modResourcePacks.entrySet())
|
||||
{
|
||||
IModInfo mod = e.getKey().getModInfos().get(0);
|
||||
final String name = "mod:" + mod.getModId();
|
||||
final Pack packInfo = Pack.create(name, false, e::getValue, factory, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
if (packInfo == null) {
|
||||
final Pack modPack = Pack.readMetaAndCreate(name, Component.literal(e.getValue().packId()), false, id -> e.getValue(), PackType.CLIENT_RESOURCES, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
if (modPack == null) {
|
||||
// Vanilla only logs an error, instead of propagating, so handle null and warn that something went wrong
|
||||
ModLoader.get().addWarning(new ModLoadingWarning(mod, ModLoadingStage.ERROR, "fml.modloading.brokenresources", e.getKey()));
|
||||
continue;
|
||||
}
|
||||
LOGGER.debug(CORE, "Generating PackInfo named {} for mod file {}", name, e.getKey().getFilePath());
|
||||
if (mod.getOwningFile().showAsResourcePack()) {
|
||||
consumer.accept(packInfo);
|
||||
packAcceptor.accept(modPack);
|
||||
} else {
|
||||
hiddenPacks.add(e.getValue());
|
||||
}
|
||||
}
|
||||
final Pack packInfo = Pack.create("mod_resources", true, () -> new DelegatingPackResources("mod_resources", "Mod Resources",
|
||||
new PackMetadataSection(Component.translatable("fml.resources.modresources", hiddenPacks.size()), PackType.CLIENT_RESOURCES.getVersion(SharedConstants.getCurrentVersion())),
|
||||
hiddenPacks), factory, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
consumer.accept(packInfo);
|
||||
|
||||
// Create a resource pack merging all mod resources that should be hidden
|
||||
final Pack modResourcesPack = Pack.readMetaAndCreate("mod_resources", Component.literal("Mod Resources"), true,
|
||||
id -> new DelegatingPackResources(id, false, new PackMetadataSection(Component.translatable("fml.resources.modresources", hiddenPacks.size()),
|
||||
PackType.CLIENT_RESOURCES.getVersion(SharedConstants.getCurrentVersion())), hiddenPacks),
|
||||
PackType.CLIENT_RESOURCES, Pack.Position.BOTTOM, PackSource.DEFAULT);
|
||||
packAcceptor.accept(modResourcesPack);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,15 @@ import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
@@ -20,9 +28,8 @@ import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -43,17 +50,6 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.IdentityHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A model composed of several named children.
|
||||
* <p>
|
||||
@@ -81,7 +77,7 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel>
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
if (logWarning)
|
||||
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated \"parts\" field in its composite model instead of \"children\". This field will be removed in 1.20.");
|
||||
@@ -100,7 +96,7 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel>
|
||||
if (!context.isComponentVisible(name, true))
|
||||
continue;
|
||||
var model = entry.getValue();
|
||||
bakedPartsBuilder.put(name, model.bake(bakery, model, spriteGetter, modelState, modelLocation, true));
|
||||
bakedPartsBuilder.put(name, model.bake(baker, model, spriteGetter, modelState, modelLocation, true));
|
||||
}
|
||||
var bakedParts = bakedPartsBuilder.build();
|
||||
|
||||
@@ -116,17 +112,6 @@ public class CompositeModel implements IUnbakedGeometry<CompositeModel>
|
||||
return new Baked(context.isGui3d(), context.useBlockLight(), context.useAmbientOcclusion(), particle, context.getTransforms(), overrides, bakedParts, itemPassesBuilder.build());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
Set<Material> textures = new HashSet<>();
|
||||
if (context.hasMaterial("particle"))
|
||||
textures.add(context.getMaterial("particle"));
|
||||
for (BlockModel part : children.values())
|
||||
textures.addAll(part.getMaterials(modelGetter, missingTextureErrors));
|
||||
return textures;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> getConfigurableComponentNames()
|
||||
{
|
||||
|
||||
@@ -11,9 +11,7 @@ import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.math.Quaternion;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.client.color.item.ItemColor;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
@@ -22,7 +20,7 @@ import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.BlockModelRotation;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -46,6 +44,8 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
@@ -67,8 +67,8 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
// Depth offsets to prevent Z-fighting
|
||||
private static final Transformation FLUID_TRANSFORM = new Transformation(Vector3f.ZERO, Quaternion.ONE, new Vector3f(1, 1, 1.002f), Quaternion.ONE);
|
||||
private static final Transformation COVER_TRANSFORM = new Transformation(Vector3f.ZERO, Quaternion.ONE, new Vector3f(1, 1, 1.004f), Quaternion.ONE);
|
||||
private static final Transformation FLUID_TRANSFORM = new Transformation(new Vector3f(), new Quaternionf(), new Vector3f(1, 1, 1.002f), new Quaternionf());
|
||||
private static final Transformation COVER_TRANSFORM = new Transformation(new Vector3f(), new Quaternionf(), new Vector3f(1, 1, 1.004f), new Quaternionf());
|
||||
|
||||
private final Fluid fluid;
|
||||
private final boolean flipGas;
|
||||
@@ -107,7 +107,7 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
if (deprecatedLoader)
|
||||
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated loader \"forge:bucket\" instead of \"forge:fluid_container\". This loader will be removed in 1.20.");
|
||||
@@ -134,19 +134,19 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
{
|
||||
modelState = new SimpleModelState(
|
||||
modelState.getRotation().compose(
|
||||
new Transformation(null, new Quaternion(0, 0, 1, 0), null, null)));
|
||||
new Transformation(null, new Quaternionf(0, 0, 1, 0), null, null)));
|
||||
}
|
||||
|
||||
// We need to disable GUI 3D and block lighting for this to render properly
|
||||
var itemContext = StandaloneGeometryBakingContext.builder(context).withGui3d(false).withUseBlockLight(false).build(modelLocation);
|
||||
var modelBuilder = CompositeModel.Baked.builder(itemContext, particleSprite, new ContainedFluidOverrideHandler(overrides, bakery, itemContext, this), context.getTransforms());
|
||||
var modelBuilder = CompositeModel.Baked.builder(itemContext, particleSprite, new ContainedFluidOverrideHandler(overrides, baker, itemContext, this), context.getTransforms());
|
||||
|
||||
var normalRenderTypes = getLayerRenderTypes(false);
|
||||
|
||||
if (baseLocation != null && baseSprite != null)
|
||||
{
|
||||
// Base texture
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(0, baseSprite);
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(0, baseSprite.contents());
|
||||
var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> baseSprite, modelState, modelLocation);
|
||||
modelBuilder.addQuads(normalRenderTypes, quads);
|
||||
}
|
||||
@@ -158,7 +158,7 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
{
|
||||
// Fluid layer
|
||||
var transformedState = new SimpleModelState(modelState.getRotation().compose(FLUID_TRANSFORM), modelState.isUvLocked());
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemMaskElements(1, templateSprite); // Use template as mask
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemMaskElements(1, templateSprite.contents()); // Use template as mask
|
||||
var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> fluidSprite, transformedState, modelLocation); // Bake with fluid texture
|
||||
|
||||
var emissive = applyFluidLuminosity && fluid.getFluidType().getLightLevel() > 0;
|
||||
@@ -176,7 +176,7 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
{
|
||||
// Cover/overlay
|
||||
var transformedState = new SimpleModelState(modelState.getRotation().compose(COVER_TRANSFORM), modelState.isUvLocked());
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemMaskElements(2, coverSprite); // Use cover as mask
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemMaskElements(2, coverSprite.contents()); // Use cover as mask
|
||||
var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> sprite, transformedState, modelLocation); // Bake with selected texture
|
||||
modelBuilder.addQuads(normalRenderTypes, quads);
|
||||
}
|
||||
@@ -187,17 +187,6 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
return modelBuilder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
Set<Material> textures = Sets.newHashSet();
|
||||
if (context.hasMaterial("particle")) textures.add(context.getMaterial("particle"));
|
||||
if (context.hasMaterial("base")) textures.add(context.getMaterial("base"));
|
||||
if (context.hasMaterial("fluid")) textures.add(context.getMaterial("fluid"));
|
||||
if (context.hasMaterial("cover")) textures.add(context.getMaterial("cover"));
|
||||
return textures;
|
||||
}
|
||||
|
||||
public static final class Loader implements IGeometryLoader<DynamicFluidContainerModel>
|
||||
{
|
||||
public static final Loader INSTANCE = new Loader(false);
|
||||
@@ -252,14 +241,14 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
{
|
||||
private final Map<String, BakedModel> cache = Maps.newHashMap(); // contains all the baked models since they'll never change
|
||||
private final ItemOverrides nested;
|
||||
private final ModelBakery bakery;
|
||||
private final ModelBaker baker;
|
||||
private final IGeometryBakingContext owner;
|
||||
private final DynamicFluidContainerModel parent;
|
||||
|
||||
private ContainedFluidOverrideHandler(ItemOverrides nested, ModelBakery bakery, IGeometryBakingContext owner, DynamicFluidContainerModel parent)
|
||||
private ContainedFluidOverrideHandler(ItemOverrides nested, ModelBaker baker, IGeometryBakingContext owner, DynamicFluidContainerModel parent)
|
||||
{
|
||||
this.nested = nested;
|
||||
this.bakery = bakery;
|
||||
this.baker = baker;
|
||||
this.owner = owner;
|
||||
this.parent = parent;
|
||||
}
|
||||
@@ -277,7 +266,7 @@ public class DynamicFluidContainerModel implements IUnbakedGeometry<DynamicFluid
|
||||
if (!cache.containsKey(name))
|
||||
{
|
||||
DynamicFluidContainerModel unbaked = this.parent.withFluid(fluid);
|
||||
BakedModel bakedModel = unbaked.bake(owner, bakery, Material::sprite, BlockModelRotation.X0_Y0, this, new ResourceLocation("forge:bucket_override"));
|
||||
BakedModel bakedModel = unbaked.bake(owner, baker, Material::sprite, BlockModelRotation.X0_Y0, this, new ResourceLocation("forge:bucket_override"));
|
||||
cache.put(name, bakedModel);
|
||||
return bakedModel;
|
||||
}
|
||||
|
||||
@@ -11,13 +11,18 @@ import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
import net.minecraft.client.renderer.block.model.BlockElementFace;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -29,12 +34,6 @@ import net.minecraftforge.client.model.geometry.SimpleUnbakedGeometry;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A model composed of vanilla {@linkplain BlockElement block elements}.
|
||||
*/
|
||||
@@ -57,7 +56,7 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addQuads(IGeometryBakingContext context, IModelBuilder<?> modelBuilder, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation)
|
||||
protected void addQuads(IGeometryBakingContext context, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation)
|
||||
{
|
||||
if (deprecatedLoader)
|
||||
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated loader \"minecraft:elements\" instead of \"forge:elements\". This loader will be removed in 1.20.");
|
||||
@@ -85,26 +84,6 @@ public class ElementsModel extends SimpleUnbakedGeometry<ElementsModel>
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
Set<Material> textures = Sets.newHashSet();
|
||||
if (context.hasMaterial("particle"))
|
||||
textures.add(context.getMaterial("particle"));
|
||||
for (BlockElement part : elements)
|
||||
{
|
||||
for (BlockElementFace face : part.faces.values())
|
||||
{
|
||||
Material texture = context.getMaterial(face.texture);
|
||||
if (texture.texture().equals(MissingTextureAtlasSprite.getLocation()))
|
||||
missingTextureErrors.add(Pair.of(face.texture, context.getModelName()));
|
||||
textures.add(texture);
|
||||
}
|
||||
}
|
||||
|
||||
return textures;
|
||||
}
|
||||
|
||||
public static final class Loader implements IGeometryLoader<ElementsModel>
|
||||
{
|
||||
public static final Loader INSTANCE = new Loader(false);
|
||||
|
||||
@@ -6,6 +6,11 @@
|
||||
package net.minecraftforge.client.model;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
@@ -13,7 +18,7 @@ import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.SimpleBakedModel;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
@@ -25,12 +30,6 @@ import net.minecraftforge.client.model.geometry.IUnbakedGeometry;
|
||||
import net.minecraftforge.client.model.geometry.SimpleUnbakedGeometry;
|
||||
import net.minecraftforge.client.textures.UnitTextureAtlasSprite;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A completely empty model with no quads or texture dependencies.
|
||||
* <p>
|
||||
@@ -47,23 +46,17 @@ public class EmptyModel extends SimpleUnbakedGeometry<EmptyModel>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
{
|
||||
// NO-OP
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
return BAKED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
return List.of(); // NO-OP
|
||||
}
|
||||
|
||||
private static class Baked extends SimpleBakedModel
|
||||
{
|
||||
private static final Material MISSING_TEXTURE = new Material(TextureAtlas.LOCATION_BLOCKS, MissingTextureAtlasSprite.getLocation());
|
||||
|
||||
@@ -21,7 +21,7 @@ import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -71,10 +71,18 @@ public class ItemLayerModel implements IUnbakedGeometry<ItemLayerModel>
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
if (textures == null)
|
||||
throw new IllegalStateException("Textures have not been initialized. Either pass them in through the constructor or call getMaterials(...) first.");
|
||||
if (textures == null) {
|
||||
ImmutableList.Builder<Material> builder = ImmutableList.builder();
|
||||
if (context.hasMaterial("particle"))
|
||||
builder.add(context.getMaterial("particle"));
|
||||
for (int i = 0; context.hasMaterial("layer" + i); i++)
|
||||
{
|
||||
builder.add(context.getMaterial("layer" + i));
|
||||
}
|
||||
textures = builder.build();
|
||||
}
|
||||
|
||||
if (deprecatedLoader)
|
||||
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated loader \"forge:item-layers\" instead of \"forge:item_layers\". This loader will be removed in 1.20.");
|
||||
@@ -93,7 +101,7 @@ public class ItemLayerModel implements IUnbakedGeometry<ItemLayerModel>
|
||||
for (int i = 0; i < textures.size(); i++)
|
||||
{
|
||||
TextureAtlasSprite sprite = spriteGetter.apply(textures.get(i));
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(i, sprite);
|
||||
var unbaked = UnbakedGeometryHelper.createUnbakedItemElements(i, sprite.contents());
|
||||
var quads = UnbakedGeometryHelper.bakeElements(unbaked, $ -> sprite, modelState, modelLocation);
|
||||
if (emissiveLayers.contains(i)) QuadTransformers.settingMaxEmissivity().processInPlace(quads);
|
||||
var renderTypeName = renderTypeNames.get(i);
|
||||
@@ -104,22 +112,6 @@ public class ItemLayerModel implements IUnbakedGeometry<ItemLayerModel>
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
if (textures != null)
|
||||
return textures;
|
||||
|
||||
ImmutableList.Builder<Material> builder = ImmutableList.builder();
|
||||
if (context.hasMaterial("particle"))
|
||||
builder.add(context.getMaterial("particle"));
|
||||
for (int i = 0; context.hasMaterial("layer" + i); i++)
|
||||
{
|
||||
builder.add(context.getMaterial("layer" + i));
|
||||
}
|
||||
return textures = builder.build();
|
||||
}
|
||||
|
||||
public static final class Loader implements IGeometryLoader<ItemLayerModel>
|
||||
{
|
||||
public static final Loader INSTANCE = new Loader(false);
|
||||
|
||||
@@ -7,11 +7,11 @@ package net.minecraftforge.client.model;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import com.mojang.math.Vector4f;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -53,7 +53,7 @@ public final class QuadTransformers {
|
||||
|
||||
Vector4f pos = new Vector4f(x, y, z, 1);
|
||||
transform.transformPosition(pos);
|
||||
pos.perspectiveDivide();
|
||||
pos.div(pos.w);
|
||||
|
||||
vertices[offset] = Float.floatToRawIntBits(pos.x());
|
||||
vertices[offset + 1] = Float.floatToRawIntBits(pos.y());
|
||||
|
||||
@@ -7,11 +7,13 @@ package net.minecraftforge.client.model;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.RenderType;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
@@ -20,9 +22,8 @@ import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
@@ -38,13 +39,6 @@ import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A model composed of multiple sub-models which are picked based on the {@link ItemTransforms.TransformType} being used.
|
||||
*/
|
||||
@@ -69,7 +63,7 @@ public class SeparateTransformsModel implements IUnbakedGeometry<SeparateTransfo
|
||||
}
|
||||
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
if (deprecatedLoader)
|
||||
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated loader \"forge:separate-perspective\" instead of \"forge:separate_transforms\". This loader will be removed in 1.20.");
|
||||
@@ -77,25 +71,13 @@ public class SeparateTransformsModel implements IUnbakedGeometry<SeparateTransfo
|
||||
return new Baked(
|
||||
context.useAmbientOcclusion(), context.isGui3d(), context.useBlockLight(),
|
||||
spriteGetter.apply(context.getMaterial("particle")), overrides,
|
||||
baseModel.bake(bakery, baseModel, spriteGetter, modelState, modelLocation, context.useBlockLight()),
|
||||
baseModel.bake(baker, baseModel, spriteGetter, modelState, modelLocation, context.useBlockLight()),
|
||||
ImmutableMap.copyOf(Maps.transformValues(perspectives, value -> {
|
||||
return value.bake(bakery, value, spriteGetter, modelState, modelLocation, context.useBlockLight());
|
||||
return value.bake(baker, value, spriteGetter, modelState, modelLocation, context.useBlockLight());
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
Set<Material> textures = Sets.newHashSet();
|
||||
if (context.hasMaterial("particle"))
|
||||
textures.add(context.getMaterial("particle"));
|
||||
textures.addAll(baseModel.getMaterials(modelGetter, missingTextureErrors));
|
||||
for (BlockModel model : perspectives.values())
|
||||
textures.addAll(model.getMaterials(modelGetter, missingTextureErrors));
|
||||
return textures;
|
||||
}
|
||||
|
||||
public static class Baked implements IDynamicBakedModel
|
||||
{
|
||||
private final boolean isAmbientOcclusion;
|
||||
|
||||
@@ -8,20 +8,21 @@ package net.minecraftforge.client.model.generators;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.math.Quaternion;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.StringRepresentable;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.common.util.TransformationHelper;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* Builder for block models, does not currently provide any additional
|
||||
* functionality over {@link ModelBuilder}, purely a stub class with a concrete
|
||||
* generic.
|
||||
*
|
||||
*
|
||||
* @see ModelProvider
|
||||
* @see ModelBuilder
|
||||
*/
|
||||
@@ -58,9 +59,9 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
{
|
||||
private static final Vector3f ONE = new Vector3f(1, 1, 1);
|
||||
|
||||
private Vector3f translation = Vector3f.ZERO;
|
||||
private Quaternion leftRotation = Quaternion.ONE.copy();
|
||||
private Quaternion rightRotation = Quaternion.ONE.copy();
|
||||
private Vector3f translation = new Vector3f();
|
||||
private Quaternionf leftRotation = new Quaternionf();
|
||||
private Quaternionf rightRotation = new Quaternionf();
|
||||
private Vector3f scale = ONE;
|
||||
|
||||
private @Nullable TransformOrigin origin;
|
||||
@@ -103,7 +104,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
* @return this builder
|
||||
* @throws NullPointerException if {@code rotation} is {@code null}
|
||||
*/
|
||||
public RootTransformBuilder rotation(Quaternion rotation)
|
||||
public RootTransformBuilder rotation(Quaternionf rotation)
|
||||
{
|
||||
this.leftRotation = Preconditions.checkNotNull(rotation, "Rotation must not be null");
|
||||
return this;
|
||||
@@ -120,7 +121,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
*/
|
||||
public RootTransformBuilder rotation(float x, float y, float z, boolean isDegrees)
|
||||
{
|
||||
return rotation(new Quaternion(x, y, z, isDegrees));
|
||||
return rotation(TransformationHelper.quatFromXYZ(x, y, z, isDegrees));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -130,7 +131,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
* @return this builder
|
||||
* @throws NullPointerException if {@code leftRotation} is {@code null}
|
||||
*/
|
||||
public RootTransformBuilder leftRotation(Quaternion leftRotation)
|
||||
public RootTransformBuilder leftRotation(Quaternionf leftRotation)
|
||||
{
|
||||
return rotation(leftRotation);
|
||||
}
|
||||
@@ -146,7 +147,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
*/
|
||||
public RootTransformBuilder leftRotation(float x, float y, float z, boolean isDegrees)
|
||||
{
|
||||
return leftRotation(new Quaternion(x, y, z, isDegrees));
|
||||
return leftRotation(TransformationHelper.quatFromXYZ(x, y, z, isDegrees));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,7 +157,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
* @return this builder
|
||||
* @throws NullPointerException if {@code rightRotation} is {@code null}
|
||||
*/
|
||||
public RootTransformBuilder rightRotation(Quaternion rightRotation)
|
||||
public RootTransformBuilder rightRotation(Quaternionf rightRotation)
|
||||
{
|
||||
this.rightRotation = Preconditions.checkNotNull(rightRotation, "Rotation must not be null");
|
||||
return this;
|
||||
@@ -173,7 +174,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
*/
|
||||
public RootTransformBuilder rightRotation(float x, float y, float z, boolean isDegrees)
|
||||
{
|
||||
return rightRotation(new Quaternion(x, y, z, isDegrees));
|
||||
return rightRotation(TransformationHelper.quatFromXYZ(x, y, z, isDegrees));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,7 +184,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
* @return this builder
|
||||
* @throws NullPointerException if {@code rightRotation} is {@code null}
|
||||
*/
|
||||
public RootTransformBuilder postRotation(Quaternion postRotation)
|
||||
public RootTransformBuilder postRotation(Quaternionf postRotation)
|
||||
{
|
||||
return rightRotation(postRotation);
|
||||
}
|
||||
@@ -199,7 +200,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
*/
|
||||
public RootTransformBuilder postRotation(float x, float y, float z, boolean isDegrees)
|
||||
{
|
||||
return postRotation(new Quaternion(x, y, z, isDegrees));
|
||||
return postRotation(TransformationHelper.quatFromXYZ(x, y, z, isDegrees));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,7 +300,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
// Write the transform to an object
|
||||
JsonObject transform = new JsonObject();
|
||||
|
||||
if (!translation.equals(Vector3f.ZERO))
|
||||
if (!translation.equals(0, 0, 0))
|
||||
{
|
||||
transform.add("translation", writeVec3(translation));
|
||||
}
|
||||
@@ -309,12 +310,12 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
transform.add("scale", writeVec3(scale));
|
||||
}
|
||||
|
||||
if (!leftRotation.equals(Quaternion.ONE))
|
||||
if (!leftRotation.equals(0, 0, 0, 1))
|
||||
{
|
||||
transform.add("rotation", writeQuaternion(leftRotation));
|
||||
}
|
||||
|
||||
if (!rightRotation.equals(Quaternion.ONE))
|
||||
if (!rightRotation.equals(0, 0, 0, 1))
|
||||
{
|
||||
transform.add("post_rotation", writeQuaternion(rightRotation));
|
||||
}
|
||||
@@ -323,7 +324,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
{
|
||||
transform.addProperty("origin", origin.getSerializedName());
|
||||
}
|
||||
else if (originVec != null && !originVec.equals(Vector3f.ZERO))
|
||||
else if (originVec != null && !originVec.equals(0, 0, 0))
|
||||
{
|
||||
transform.add("origin", writeVec3(originVec));
|
||||
}
|
||||
@@ -334,7 +335,7 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
public enum TransformOrigin implements StringRepresentable
|
||||
{
|
||||
CENTER(new Vector3f(.5f, .5f, .5f), "center"),
|
||||
CORNER(Vector3f.ZERO, "corner"),
|
||||
CORNER(new Vector3f(), "corner"),
|
||||
OPPOSING_CORNER(ONE, "opposing-corner");
|
||||
|
||||
private final Vector3f vec;
|
||||
@@ -385,13 +386,13 @@ public class BlockModelBuilder extends ModelBuilder<BlockModelBuilder>
|
||||
return array;
|
||||
}
|
||||
|
||||
private JsonArray writeQuaternion(Quaternion quaternion)
|
||||
private JsonArray writeQuaternion(Quaternionf quaternion)
|
||||
{
|
||||
JsonArray array = new JsonArray();
|
||||
array.add(quaternion.i());
|
||||
array.add(quaternion.j());
|
||||
array.add(quaternion.k());
|
||||
array.add(quaternion.r());
|
||||
array.add(quaternion.x());
|
||||
array.add(quaternion.y());
|
||||
array.add(quaternion.z());
|
||||
array.add(quaternion.w());
|
||||
return array;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,23 +5,6 @@
|
||||
|
||||
package net.minecraftforge.client.model.generators;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.world.level.block.ButtonBlock;
|
||||
import net.minecraft.world.level.block.PressurePlateBlock;
|
||||
import net.minecraft.world.level.block.StandingSignBlock;
|
||||
import net.minecraft.world.level.block.WallSignBlock;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
@@ -31,35 +14,51 @@ import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.ButtonBlock;
|
||||
import net.minecraft.world.level.block.CrossCollisionBlock;
|
||||
import net.minecraft.world.level.block.DoorBlock;
|
||||
import net.minecraft.world.level.block.FenceBlock;
|
||||
import net.minecraft.world.level.block.FenceGateBlock;
|
||||
import net.minecraft.world.level.block.CrossCollisionBlock;
|
||||
import net.minecraft.world.level.block.IronBarsBlock;
|
||||
import net.minecraft.world.level.block.RotatedPillarBlock;
|
||||
import net.minecraft.world.level.block.PipeBlock;
|
||||
import net.minecraft.world.level.block.PressurePlateBlock;
|
||||
import net.minecraft.world.level.block.RotatedPillarBlock;
|
||||
import net.minecraft.world.level.block.SlabBlock;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.StandingSignBlock;
|
||||
import net.minecraft.world.level.block.TrapDoorBlock;
|
||||
import net.minecraft.world.level.block.WallBlock;
|
||||
import net.minecraft.world.level.block.state.properties.WallSide;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.level.block.WallSignBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.AttachFace;
|
||||
import net.minecraft.world.level.block.state.properties.BlockStateProperties;
|
||||
import net.minecraft.world.level.block.state.properties.DoorHingeSide;
|
||||
import net.minecraft.world.level.block.state.properties.DoubleBlockHalf;
|
||||
import net.minecraft.world.level.block.state.properties.Half;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import net.minecraft.world.level.block.state.properties.StairsShape;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Direction.Axis;
|
||||
import net.minecraft.world.level.block.state.properties.WallSide;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -83,28 +82,31 @@ public abstract class BlockStateProvider implements DataProvider {
|
||||
this.generator = gen;
|
||||
this.modid = modid;
|
||||
this.blockModels = new BlockModelProvider(gen, modid, exFileHelper) {
|
||||
@Override public void run(CachedOutput p_236071_) throws IOException {}
|
||||
@Override public CompletableFuture<?> run(CachedOutput cache) { return CompletableFuture.allOf(); }
|
||||
|
||||
@Override protected void registerModels() {}
|
||||
};
|
||||
this.itemModels = new ItemModelProvider(gen, modid, this.blockModels.existingFileHelper) {
|
||||
@Override protected void registerModels() {}
|
||||
|
||||
@Override public void run(CachedOutput p_236071_) throws IOException {}
|
||||
@Override public CompletableFuture<?> run(CachedOutput cache) { return CompletableFuture.allOf(); }
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(CachedOutput cache) throws IOException {
|
||||
public CompletableFuture<?> run(CachedOutput cache) {
|
||||
models().clear();
|
||||
itemModels().clear();
|
||||
registeredBlocks.clear();
|
||||
registerStatesAndModels();
|
||||
models().generateAll(cache);
|
||||
itemModels().generateAll(cache);
|
||||
CompletableFuture<?>[] futures = new CompletableFuture<?>[this.registeredBlocks.size()];
|
||||
int i = 0;
|
||||
for (Map.Entry<Block, IGeneratedBlockState> entry : registeredBlocks.entrySet()) {
|
||||
saveBlockState(cache, entry.getValue().toJson(), entry.getKey());
|
||||
futures[i++] = saveBlockState(cache, entry.getValue().toJson(), entry.getKey());
|
||||
}
|
||||
return CompletableFuture.allOf(futures);
|
||||
}
|
||||
|
||||
protected abstract void registerStatesAndModels();
|
||||
@@ -853,16 +855,11 @@ public abstract class BlockStateProvider implements DataProvider {
|
||||
}, TrapDoorBlock.POWERED, TrapDoorBlock.WATERLOGGED);
|
||||
}
|
||||
|
||||
private void saveBlockState(CachedOutput cache, JsonObject stateJson, Block owner) {
|
||||
private CompletableFuture<?> saveBlockState(CachedOutput cache, JsonObject stateJson, Block owner) {
|
||||
ResourceLocation blockName = Preconditions.checkNotNull(key(owner));
|
||||
Path mainOutput = generator.getOutputFolder();
|
||||
String pathSuffix = "assets/" + blockName.getNamespace() + "/blockstates/" + blockName.getPath() + ".json";
|
||||
Path outputPath = mainOutput.resolve(pathSuffix);
|
||||
try {
|
||||
DataProvider.saveStable(cache, stateJson, outputPath);
|
||||
} catch (IOException e) {
|
||||
LOGGER.error("Couldn't save blockstate to {}", outputPath, e);
|
||||
}
|
||||
Path outputPath = this.generator.getPackOutput().getOutputFolder(PackOutput.Target.RESOURCE_PACK)
|
||||
.resolve(blockName.getNamespace()).resolve("blockstates").resolve(blockName.getPath() + ".json");
|
||||
return DataProvider.saveStable(cache, stateJson, outputPath);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
|
||||
@@ -32,9 +32,9 @@ import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.util.Mth;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
/**
|
||||
* General purpose model builder, contains all the commonalities between item
|
||||
@@ -285,11 +285,11 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
|
||||
|
||||
if (part.rotation != null) {
|
||||
JsonObject rotation = new JsonObject();
|
||||
rotation.add("origin", serializeVector3f(part.rotation.origin));
|
||||
rotation.addProperty("axis", part.rotation.axis.getSerializedName());
|
||||
rotation.addProperty("angle", part.rotation.angle);
|
||||
if (part.rotation.rescale) {
|
||||
rotation.addProperty("rescale", part.rotation.rescale);
|
||||
rotation.add("origin", serializeVector3f(part.rotation.origin()));
|
||||
rotation.addProperty("axis", part.rotation.axis().getSerializedName());
|
||||
rotation.addProperty("angle", part.rotation.angle());
|
||||
if (part.rotation.rescale()) {
|
||||
rotation.addProperty("rescale", part.rotation.rescale());
|
||||
}
|
||||
partObj.add("rotation", rotation);
|
||||
}
|
||||
@@ -695,10 +695,10 @@ public class ModelBuilder<T extends ModelBuilder<T>> extends ModelFile {
|
||||
|
||||
public class TransformVecBuilder {
|
||||
|
||||
private Vector3f rotation = ItemTransform.Deserializer.DEFAULT_ROTATION.copy();
|
||||
private Vector3f translation = ItemTransform.Deserializer.DEFAULT_TRANSLATION.copy();
|
||||
private Vector3f scale = ItemTransform.Deserializer.DEFAULT_SCALE.copy();
|
||||
private Vector3f rightRotation = ItemTransform.Deserializer.DEFAULT_ROTATION.copy();
|
||||
private Vector3f rotation = new Vector3f(ItemTransform.Deserializer.DEFAULT_ROTATION);
|
||||
private Vector3f translation = new Vector3f(ItemTransform.Deserializer.DEFAULT_TRANSLATION);
|
||||
private Vector3f scale = new Vector3f(ItemTransform.Deserializer.DEFAULT_SCALE);
|
||||
private Vector3f rightRotation = new Vector3f(ItemTransform.Deserializer.DEFAULT_ROTATION);
|
||||
|
||||
TransformVecBuilder(TransformType type) {
|
||||
// param unused for functional match
|
||||
|
||||
@@ -5,24 +5,22 @@
|
||||
|
||||
package net.minecraftforge.client.model.generators;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.HashCache;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper.ResourceType;
|
||||
|
||||
@@ -262,7 +260,7 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements DataPr
|
||||
public T wallSide(String name, ResourceLocation wall) {
|
||||
return singleTexture(name, BLOCK_FOLDER + "/template_wall_side", "wall", wall);
|
||||
}
|
||||
|
||||
|
||||
public T wallSideTall(String name, ResourceLocation wall) {
|
||||
return singleTexture(name, BLOCK_FOLDER + "/template_wall_side_tall", "wall", wall);
|
||||
}
|
||||
@@ -384,31 +382,32 @@ public abstract class ModelProvider<T extends ModelBuilder<T>> implements DataPr
|
||||
ret.assertExistence();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
protected void clear() {
|
||||
generatedModels.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(CachedOutput cache) throws IOException {
|
||||
public CompletableFuture<?> run(CachedOutput cache) {
|
||||
clear();
|
||||
registerModels();
|
||||
generateAll(cache);
|
||||
return generateAll(cache);
|
||||
}
|
||||
|
||||
protected void generateAll(CachedOutput cache) {
|
||||
for (T model : generatedModels.values()) {
|
||||
protected CompletableFuture<?> generateAll(CachedOutput cache) {
|
||||
CompletableFuture<?>[] futures = new CompletableFuture<?>[this.generatedModels.size()];
|
||||
int i = 0;
|
||||
|
||||
for (T model : this.generatedModels.values()) {
|
||||
Path target = getPath(model);
|
||||
try {
|
||||
DataProvider.saveStable(cache, model.toJson(), target);
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
futures[i++] = DataProvider.saveStable(cache, model.toJson(), target);
|
||||
}
|
||||
|
||||
return CompletableFuture.allOf(futures);
|
||||
}
|
||||
|
||||
private Path getPath(T model) {
|
||||
protected Path getPath(T model) {
|
||||
ResourceLocation loc = model.getLocation();
|
||||
return generator.getOutputFolder().resolve("assets/" + loc.getNamespace() + "/models/" + loc.getPath() + ".json");
|
||||
return this.generator.getPackOutput().getOutputFolder(PackOutput.Target.RESOURCE_PACK).resolve(loc.getNamespace()).resolve("models").resolve(loc.getPath() + ".json");
|
||||
}
|
||||
}
|
||||
+14
-22
@@ -7,25 +7,24 @@ package net.minecraftforge.client.model.geometry;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.math.Transformation;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||
import net.minecraft.client.renderer.block.model.ItemTransforms;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* A {@linkplain IGeometryBakingContext geometry baking context} that is bound to a {@link BlockModel}.
|
||||
@@ -150,19 +149,12 @@ public class BlockGeometryBakingContext implements IGeometryBakingContext
|
||||
this.renderTypeHint = other.renderTypeHint;
|
||||
}
|
||||
|
||||
public Collection<Material> getTextureDependencies(Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
IUnbakedGeometry<?> geometry = getCustomGeometry();
|
||||
return geometry == null ? Collections.emptySet() :
|
||||
geometry.getMaterials(this, modelGetter, missingTextureErrors);
|
||||
}
|
||||
|
||||
public BakedModel bake(ModelBakery bakery, Function<Material, TextureAtlasSprite> bakedTextureGetter, ModelState modelTransform, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
public BakedModel bake(ModelBaker baker, Function<Material, TextureAtlasSprite> bakedTextureGetter, ModelState modelTransform, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
IUnbakedGeometry<?> geometry = getCustomGeometry();
|
||||
if (geometry == null)
|
||||
throw new IllegalStateException("Can not use custom baking without custom geometry");
|
||||
return geometry.bake(this, bakery, bakedTextureGetter, modelTransform, overrides, modelLocation);
|
||||
return geometry.bake(this, baker, bakedTextureGetter, modelTransform, overrides, modelLocation);
|
||||
}
|
||||
|
||||
public static class VisibilityData
|
||||
|
||||
@@ -5,20 +5,17 @@
|
||||
|
||||
package net.minecraftforge.client.model.geometry;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* General interface for any model that can be baked, superset of vanilla {@link UnbakedModel}.
|
||||
* <p>
|
||||
@@ -29,9 +26,7 @@ import java.util.function.Function;
|
||||
*/
|
||||
public interface IUnbakedGeometry<T extends IUnbakedGeometry<T>>
|
||||
{
|
||||
BakedModel bake(IGeometryBakingContext context, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation);
|
||||
|
||||
Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors);
|
||||
BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation);
|
||||
|
||||
/**
|
||||
* {@return a set of all the components whose visibility may be configured via {@link IGeometryBakingContext}}
|
||||
|
||||
@@ -5,23 +5,18 @@
|
||||
|
||||
package net.minecraftforge.client.model.geometry;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.ItemOverrides;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.client.RenderTypeGroup;
|
||||
import net.minecraftforge.client.model.IModelBuilder;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Base class for implementations of {@link IUnbakedGeometry} which do not wish to handle model creation themselves,
|
||||
* instead supplying {@linkplain BakedQuad baked quads} through a builder.
|
||||
@@ -29,7 +24,7 @@ import java.util.function.Function;
|
||||
public abstract class SimpleUnbakedGeometry<T extends SimpleUnbakedGeometry<T>> implements IUnbakedGeometry<T>
|
||||
{
|
||||
@Override
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
public BakedModel bake(IGeometryBakingContext context, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ItemOverrides overrides, ResourceLocation modelLocation)
|
||||
{
|
||||
TextureAtlasSprite particle = spriteGetter.apply(context.getMaterial("particle"));
|
||||
|
||||
@@ -38,13 +33,10 @@ public abstract class SimpleUnbakedGeometry<T extends SimpleUnbakedGeometry<T>>
|
||||
IModelBuilder<?> builder = IModelBuilder.of(context.useAmbientOcclusion(), context.useBlockLight(), context.isGui3d(),
|
||||
context.getTransforms(), overrides, particle, renderTypes);
|
||||
|
||||
addQuads(context, builder, bakery, spriteGetter, modelState, modelLocation);
|
||||
addQuads(context, builder, baker, spriteGetter, modelState, modelLocation);
|
||||
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
protected abstract void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation);
|
||||
|
||||
@Override
|
||||
public abstract Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<Pair<String, String>> missingTextureErrors);
|
||||
protected abstract void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation);
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
package net.minecraftforge.client.model.geometry;
|
||||
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.block.model.BlockElement;
|
||||
@@ -16,11 +15,13 @@ import net.minecraft.client.renderer.block.model.BlockModel;
|
||||
import net.minecraft.client.renderer.block.model.FaceBakery;
|
||||
import net.minecraft.client.renderer.block.model.ItemModelGenerator;
|
||||
import net.minecraft.client.renderer.texture.MissingTextureAtlasSprite;
|
||||
import net.minecraft.client.renderer.texture.SpriteContents;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.BakedModel;
|
||||
import net.minecraft.client.resources.model.BuiltInModel;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -30,6 +31,7 @@ import net.minecraftforge.client.model.IModelBuilder;
|
||||
import net.minecraftforge.client.model.SimpleModelState;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.BitSet;
|
||||
@@ -93,17 +95,17 @@ public class UnbakedGeometryHelper
|
||||
* Helper for baking {@link BlockModel} instances. Handles baking custom geometries and deferring item model baking.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public static BakedModel bake(BlockModel blockModel, ModelBakery modelBakery, BlockModel owner, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation, boolean guiLight3d)
|
||||
public static BakedModel bake(BlockModel blockModel, ModelBaker modelBaker, BlockModel owner, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation, boolean guiLight3d)
|
||||
{
|
||||
IUnbakedGeometry<?> customModel = blockModel.customData.getCustomGeometry();
|
||||
if (customModel != null)
|
||||
return customModel.bake(blockModel.customData, modelBakery, spriteGetter, modelState, blockModel.getOverrides(modelBakery, owner, spriteGetter), modelLocation);
|
||||
return customModel.bake(blockModel.customData, modelBaker, spriteGetter, modelState, blockModel.getOverrides(modelBaker, owner, spriteGetter), modelLocation);
|
||||
|
||||
// Handle vanilla item models here, since vanilla has a shortcut for them
|
||||
if (blockModel.getRootModel() == ModelBakery.GENERATION_MARKER)
|
||||
return ITEM_MODEL_GENERATOR.generateBlockModel(spriteGetter, blockModel).bake(modelBakery, blockModel, spriteGetter, modelState, modelLocation, guiLight3d);
|
||||
return ITEM_MODEL_GENERATOR.generateBlockModel(spriteGetter, blockModel).bake(modelBaker, blockModel, spriteGetter, modelState, modelLocation, guiLight3d);
|
||||
|
||||
return bakeVanilla(blockModel, modelBakery, owner, spriteGetter, modelState, modelLocation);
|
||||
return bakeVanilla(blockModel, modelBaker, owner, spriteGetter, modelState, modelLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -113,48 +115,48 @@ public class UnbakedGeometryHelper
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
@Deprecated(forRemoval = true, since = "1.19.2")
|
||||
public static BakedModel bakeVanilla(BlockModel blockModel, ModelBakery modelBakery, BlockModel owner, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation)
|
||||
public static BakedModel bakeVanilla(BlockModel blockModel, ModelBaker modelBaker, BlockModel owner, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelState, ResourceLocation modelLocation)
|
||||
{
|
||||
if (blockModel.getRootModel() == ModelBakery.BLOCK_ENTITY_MARKER)
|
||||
{
|
||||
var particleSprite = spriteGetter.apply(blockModel.getMaterial("particle"));
|
||||
return new BuiltInModel(blockModel.getTransforms(), blockModel.getOverrides(modelBakery, owner, spriteGetter), particleSprite, blockModel.getGuiLight().lightLikeBlock());
|
||||
return new BuiltInModel(blockModel.getTransforms(), blockModel.getOverrides(modelBaker, owner, spriteGetter), particleSprite, blockModel.getGuiLight().lightLikeBlock());
|
||||
}
|
||||
|
||||
var elementsModel = new ElementsModel(blockModel.getElements());
|
||||
return elementsModel.bake(blockModel.customData, modelBakery, spriteGetter, modelState, blockModel.getOverrides(modelBakery, owner, spriteGetter), modelLocation);
|
||||
return elementsModel.bake(blockModel.customData, modelBaker, spriteGetter, modelState, blockModel.getOverrides(modelBaker, owner, spriteGetter), modelLocation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of {@linkplain BlockElement block elements} in the shape of the specified sprite.
|
||||
* Creates a list of {@linkplain BlockElement block elements} in the shape of the specified sprite contents.
|
||||
* These can later be baked using the same, or another texture.
|
||||
* <p>
|
||||
* The {@link Direction#NORTH} and {@link Direction#SOUTH} faces take up the whole surface.
|
||||
*/
|
||||
public static List<BlockElement> createUnbakedItemElements(int layerIndex, TextureAtlasSprite sprite)
|
||||
public static List<BlockElement> createUnbakedItemElements(int layerIndex, SpriteContents spriteContents)
|
||||
{
|
||||
return ITEM_MODEL_GENERATOR.processFrames(layerIndex, "layer" + layerIndex, sprite);
|
||||
return ITEM_MODEL_GENERATOR.processFrames(layerIndex, "layer" + layerIndex, spriteContents);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a list of {@linkplain BlockElement block elements} in the shape of the specified sprite.
|
||||
* Creates a list of {@linkplain BlockElement block elements} in the shape of the specified sprite contents.
|
||||
* These can later be baked using the same, or another texture.
|
||||
* <p>
|
||||
* The {@link Direction#NORTH} and {@link Direction#SOUTH} faces take up only the pixels the texture uses.
|
||||
*/
|
||||
public static List<BlockElement> createUnbakedItemMaskElements(int layerIndex, TextureAtlasSprite sprite)
|
||||
public static List<BlockElement> createUnbakedItemMaskElements(int layerIndex, SpriteContents spriteContents)
|
||||
{
|
||||
var elements = createUnbakedItemElements(layerIndex, sprite);
|
||||
var elements = createUnbakedItemElements(layerIndex, spriteContents);
|
||||
elements.remove(0); // Remove north and south faces
|
||||
|
||||
int width = sprite.getWidth(), height = sprite.getHeight();
|
||||
int width = spriteContents.width(), height = spriteContents.height();
|
||||
var bits = new BitSet(width * height);
|
||||
|
||||
// For every frame in the texture, mark all the opaque pixels (this is what vanilla does too)
|
||||
sprite.getUniqueFrames().forEach(frame -> {
|
||||
spriteContents.getUniqueFrames().forEach(frame -> {
|
||||
for (int x = 0; x < width; x++)
|
||||
for (int y = 0; y < height; y++)
|
||||
if (!sprite.isTransparent(frame, x, y))
|
||||
if (!spriteContents.isTransparent(frame, x, y))
|
||||
bits.set(x + y * width);
|
||||
});
|
||||
|
||||
@@ -244,4 +246,4 @@ public class UnbakedGeometryHelper
|
||||
{
|
||||
return FACE_BAKERY.bakeQuad(element.from, element.to, face, sprite, direction, state, element.rotation, element.shade, modelLocation);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,12 +7,12 @@ package net.minecraftforge.client.model.lighting;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.client.color.block.BlockColors;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.BlockAndTintGetter;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
package net.minecraftforge.client.model.obj;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import com.mojang.math.Vector4f;
|
||||
import joptsimple.internal.Strings;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@@ -100,11 +100,11 @@ public class ObjMaterialLibrary
|
||||
public static class Material
|
||||
{
|
||||
public final String name;
|
||||
public Vector4f ambientColor = new Vector4f(0, 0, 0, 1);
|
||||
public Vector4f ambientColor = new Vector4f();
|
||||
public String ambientColorMap;
|
||||
public Vector4f diffuseColor = new Vector4f(1, 1, 1, 1);
|
||||
public String diffuseColorMap;
|
||||
public Vector4f specularColor = new Vector4f(0, 0, 0, 1);
|
||||
public Vector4f specularColor = new Vector4f();
|
||||
public float specularHighlight = 0;
|
||||
public String specularColorMap;
|
||||
|
||||
|
||||
@@ -9,14 +9,12 @@ import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import com.mojang.math.Vector4f;
|
||||
import joptsimple.internal.Strings;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.model.Material;
|
||||
import net.minecraft.client.resources.model.ModelBakery;
|
||||
import net.minecraft.client.resources.model.ModelBaker;
|
||||
import net.minecraft.client.resources.model.ModelState;
|
||||
import net.minecraft.client.resources.model.UnbakedModel;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -35,6 +33,8 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -326,7 +326,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
{
|
||||
return switch (line.length)
|
||||
{
|
||||
case 1 -> new Vector3f(0, 0, 0);
|
||||
case 1 -> new Vector3f();
|
||||
case 2 -> new Vector3f(Float.parseFloat(line[1]), 0, 0);
|
||||
case 3 -> new Vector3f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), 0);
|
||||
default -> new Vector3f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), Float.parseFloat(line[3]));
|
||||
@@ -337,7 +337,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
{
|
||||
return switch (line.length)
|
||||
{
|
||||
case 1 -> new Vector4f(0, 0, 0, 1);
|
||||
case 1 -> new Vector4f();
|
||||
case 2 -> new Vector4f(Float.parseFloat(line[1]), 0, 0, 1);
|
||||
case 3 -> new Vector4f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), 0, 1);
|
||||
case 4 -> new Vector4f(Float.parseFloat(line[1]), Float.parseFloat(line[2]), Float.parseFloat(line[3]), 1);
|
||||
@@ -346,22 +346,13 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
protected void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
{
|
||||
for (var entry : deprecationWarnings.entrySet())
|
||||
LOGGER.warn("Model \"" + modelLocation + "\" is using the deprecated \"" + entry.getKey() + "\" field in its OBJ model instead of \"" + entry.getValue() + "\". This field will be removed in 1.20.");
|
||||
|
||||
parts.values().stream().filter(part -> owner.isComponentVisible(part.name(), true))
|
||||
.forEach(part -> part.addQuads(owner, modelBuilder, bakery, spriteGetter, modelTransform, modelLocation));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Material> getMaterials(IGeometryBakingContext context, Function<ResourceLocation, UnbakedModel> modelGetter, Set<com.mojang.datafixers.util.Pair<String, String>> missingTextureErrors)
|
||||
{
|
||||
Set<Material> combined = Sets.newHashSet();
|
||||
for (ModelGroup part : parts.values())
|
||||
combined.addAll(part.getTextures(context, modelGetter, missingTextureErrors));
|
||||
return combined;
|
||||
.forEach(part -> part.addQuads(owner, modelBuilder, baker, spriteGetter, modelTransform, modelLocation));
|
||||
}
|
||||
|
||||
public Set<String> getRootComponentNames()
|
||||
@@ -387,15 +378,15 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
{
|
||||
needsNormalRecalculation |= ints.length < 3;
|
||||
}
|
||||
Vector3f faceNormal = new Vector3f(0, 0, 0);
|
||||
Vector3f faceNormal = new Vector3f();
|
||||
if (needsNormalRecalculation)
|
||||
{
|
||||
Vector3f a = positions.get(indices[0][0]);
|
||||
Vector3f ab = positions.get(indices[1][0]);
|
||||
Vector3f ac = positions.get(indices[2][0]);
|
||||
Vector3f abs = ab.copy();
|
||||
Vector3f abs = new Vector3f(ab);
|
||||
abs.sub(a);
|
||||
Vector3f acs = ac.copy();
|
||||
Vector3f acs = new Vector3f(ac);
|
||||
acs.sub(a);
|
||||
abs.cross(acs);
|
||||
abs.normalize();
|
||||
@@ -429,14 +420,14 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
int[] index = indices[Math.min(i, indices.length - 1)];
|
||||
Vector4f position = new Vector4f(positions.get(index[0]));
|
||||
Vector4f position = new Vector4f(positions.get(index[0]), 1);
|
||||
Vec2 texCoord = index.length >= 2 && texCoords.size() > 0 ? texCoords.get(index[1]) : DEFAULT_COORDS[i];
|
||||
Vector3f norm0 = !needsNormalRecalculation && index.length >= 3 && normals.size() > 0 ? normals.get(index[2]) : faceNormal;
|
||||
Vector3f normal = norm0;
|
||||
Vector4f color = index.length >= 4 && colors.size() > 0 ? colors.get(index[3]) : COLOR_WHITE;
|
||||
if (hasTransform)
|
||||
{
|
||||
normal = norm0.copy();
|
||||
normal = new Vector3f(norm0);
|
||||
transformation.transformPosition(position);
|
||||
transformation.transformNormal(normal);
|
||||
}
|
||||
@@ -548,7 +539,7 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
return name;
|
||||
}
|
||||
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
{
|
||||
for (ModelMesh mesh : meshes)
|
||||
{
|
||||
@@ -589,12 +580,12 @@ public class ObjModel extends SimpleUnbakedGeometry<ObjModel>
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBakery bakery, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
public void addQuads(IGeometryBakingContext owner, IModelBuilder<?> modelBuilder, ModelBaker baker, Function<Material, TextureAtlasSprite> spriteGetter, ModelState modelTransform, ResourceLocation modelLocation)
|
||||
{
|
||||
super.addQuads(owner, modelBuilder, bakery, spriteGetter, modelTransform, modelLocation);
|
||||
super.addQuads(owner, modelBuilder, baker, spriteGetter, modelTransform, modelLocation);
|
||||
|
||||
parts.values().stream().filter(part -> owner.isComponentVisible(part.name(), true))
|
||||
.forEach(part -> part.addQuads(owner, modelBuilder, bakery, spriteGetter, modelTransform, modelLocation));
|
||||
.forEach(part -> part.addQuads(owner, modelBuilder, baker, spriteGetter, modelTransform, modelLocation));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,9 +9,9 @@ import com.mojang.blaze3d.vertex.DefaultVertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.blaze3d.vertex.VertexFormat;
|
||||
import com.mojang.blaze3d.vertex.VertexFormatElement;
|
||||
import com.mojang.math.Vector3d;
|
||||
import com.mojang.math.Vector3f;
|
||||
import net.minecraft.client.renderer.texture.OverlayTexture;
|
||||
import org.joml.Vector3d;
|
||||
import org.joml.Vector3f;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.IdentityHashMap;
|
||||
@@ -31,8 +31,8 @@ public class RemappingVertexPipeline implements VertexConsumer
|
||||
private final VertexConsumer parent;
|
||||
private final VertexFormat targetFormat;
|
||||
|
||||
private final Vector3d position = new Vector3d(0, 0, 0);
|
||||
private final Vector3f normal = new Vector3f(0, 0, 0);
|
||||
private final Vector3d position = new Vector3d();
|
||||
private final Vector3f normal = new Vector3f();
|
||||
private final int[] color = new int[] { 255, 255, 255, 255 };
|
||||
private final float[] uv0 = new float[] { 0, 0 };
|
||||
private final int[] uv1 = new int[] { OverlayTexture.NO_WHITE_U, OverlayTexture.WHITE_OVERLAY_V };
|
||||
|
||||
+3
-3
@@ -7,8 +7,8 @@ package net.minecraftforge.client.model.pipeline;
|
||||
|
||||
import com.mojang.blaze3d.vertex.VertexConsumer;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import com.mojang.math.Vector4f;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
/**
|
||||
* Vertex pipeline element that applies a transformation to incoming geometry.
|
||||
@@ -28,7 +28,7 @@ public class TransformingVertexPipeline extends VertexConsumerWrapper
|
||||
{
|
||||
var vec = new Vector4f((float) x, (float) y, (float) z, 1);
|
||||
transformation.transformPosition(vec);
|
||||
vec.perspectiveDivide();
|
||||
vec.div(vec.w);
|
||||
return super.vertex(vec.x(), vec.y(), vec.z());
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package net.minecraftforge.client.model.renderable;
|
||||
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Vector4f;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
@@ -19,6 +18,7 @@ import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraftforge.client.model.data.ModelData;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ package net.minecraftforge.client.model.renderable;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import com.mojang.math.Matrix4f;
|
||||
import net.minecraft.client.renderer.MultiBufferSource;
|
||||
import net.minecraft.client.renderer.block.model.BakedQuad;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@@ -6,10 +6,13 @@
|
||||
package net.minecraftforge.client.textures;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.SpriteContents;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.metadata.animation.AnimationMetadataSection;
|
||||
import net.minecraft.client.resources.metadata.animation.FrameSize;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraftforge.client.event.RegisterTextureAtlasSpriteLoadersEvent;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
@@ -24,15 +27,16 @@ import org.jetbrains.annotations.NotNull;
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see net.minecraftforge.client.event.RegisterTextureAtlasSpriteLoadersEvent
|
||||
* @see RegisterTextureAtlasSpriteLoadersEvent
|
||||
*/
|
||||
public interface ITextureAtlasSpriteLoader
|
||||
{
|
||||
SpriteContents loadContents(ResourceLocation name, Resource resource, FrameSize frameSize, NativeImage image,
|
||||
AnimationMetadataSection animationMeta, ForgeTextureMetadata forgeMeta);
|
||||
|
||||
/**
|
||||
* Load a {@link TextureAtlasSprite} for the given resource.
|
||||
* Creates a {@link TextureAtlasSprite} from the given {@link SpriteContents}.
|
||||
*/
|
||||
@NotNull
|
||||
TextureAtlasSprite load(TextureAtlas atlas, ResourceManager resourceManager, TextureAtlasSprite.Info textureInfo,
|
||||
Resource resource, int atlasWidth, int atlasHeight, int spriteX, int spriteY,
|
||||
int mipmapLevel, NativeImage image);
|
||||
TextureAtlasSprite makeSprite(ResourceLocation atlasName, SpriteContents contents, int atlasWidth, int atlasHeight, int spriteX, int spriteY, int mipmapLevel);
|
||||
}
|
||||
@@ -6,9 +6,11 @@
|
||||
package net.minecraftforge.client.textures;
|
||||
|
||||
import com.mojang.blaze3d.platform.NativeImage;
|
||||
import net.minecraft.client.renderer.texture.SpriteContents;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlas;
|
||||
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
|
||||
import net.minecraft.client.resources.metadata.animation.AnimationMetadataSection;
|
||||
import net.minecraft.client.resources.metadata.animation.FrameSize;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
|
||||
/**
|
||||
@@ -23,10 +25,7 @@ public class UnitTextureAtlasSprite extends TextureAtlasSprite
|
||||
|
||||
private UnitTextureAtlasSprite()
|
||||
{
|
||||
super(new TextureAtlas(LOCATION),
|
||||
new Info(LOCATION, 1, 1, AnimationMetadataSection.EMPTY),
|
||||
0, 1, 1,
|
||||
0, 0, new NativeImage(1, 1, false));
|
||||
super(LOCATION, new SpriteContents(LOCATION, new FrameSize(1, 1), new NativeImage(1, 1, false), AnimationMetadataSection.EMPTY, null), 1, 1, 0, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.graph.ElementOrder;
|
||||
import com.google.common.graph.GraphBuilder;
|
||||
import com.google.common.graph.MutableGraph;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import it.unimi.dsi.fastutil.booleans.BooleanConsumer;
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.packs.resources.PreparableReloadListener;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.server.packs.resources.SimplePreparableReloadListener;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.util.profiling.ProfilerFiller;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.CreativeModeTabs;
|
||||
import net.minecraftforge.api.distmarker.Dist;
|
||||
import net.minecraftforge.client.CreativeModeTabSearchRegistry;
|
||||
import net.minecraftforge.event.CreativeModeTabEvent;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
import net.minecraftforge.fml.loading.FMLEnvironment;
|
||||
import net.minecraftforge.fml.loading.FMLLoader;
|
||||
import net.minecraftforge.fml.loading.toposort.TopologicalSort;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
public final class CreativeModeTabRegistry
|
||||
{
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final ResourceLocation CREATIVE_MODE_TAB_ORDERING_JSON = new ResourceLocation("forge", "creative_mode_tab_ordering.json");
|
||||
private static final List<CreativeModeTab> SORTED_TABS = new ArrayList<>();
|
||||
private static final List<CreativeModeTab> SORTED_TABS_VIEW = Collections.unmodifiableList(SORTED_TABS);
|
||||
|
||||
/**
|
||||
* {@return an unmodifiable view of the sorted list of creative mode tabs in ascending order}
|
||||
*/
|
||||
public static List<CreativeModeTab> getSortedCreativeModeTabs()
|
||||
{
|
||||
return SORTED_TABS_VIEW;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the {@linkplain CreativeModeTab} with the given name, or null}
|
||||
*
|
||||
* @param name the name to look up
|
||||
*/
|
||||
@Nullable
|
||||
public static CreativeModeTab getTab(ResourceLocation name)
|
||||
{
|
||||
return creativeModeTabs.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the name of the given {@linkplain CreativeModeTab}, or null}
|
||||
*
|
||||
* @param tab the tab to look up
|
||||
*/
|
||||
@Nullable
|
||||
public static ResourceLocation getName(CreativeModeTab tab)
|
||||
{
|
||||
return creativeModeTabs.inverse().get(tab);
|
||||
}
|
||||
|
||||
private static void processCreativeModeTab(CreativeModeTab creativeModeTab, ResourceLocation name, List<Object> afterEntries, List<Object> beforeEntries)
|
||||
{
|
||||
creativeModeTabs.put(name, creativeModeTab);
|
||||
for (Object after : afterEntries)
|
||||
{
|
||||
ResourceLocation other = getCreativeModeTabName(after);
|
||||
edges.put(other, name);
|
||||
}
|
||||
for (Object before : beforeEntries)
|
||||
{
|
||||
ResourceLocation other = getCreativeModeTabName(before);
|
||||
edges.put(name, other);
|
||||
}
|
||||
}
|
||||
|
||||
private static ResourceLocation getCreativeModeTabName(Object entry)
|
||||
{
|
||||
if (entry instanceof String s)
|
||||
return new ResourceLocation(s);
|
||||
if (entry instanceof ResourceLocation rl)
|
||||
return rl;
|
||||
if (entry instanceof CreativeModeTab t)
|
||||
return Objects.requireNonNull(getName(t), "Can't have sorting dependencies for creative mode tabs not registered in the CreativeModeTabSortingRegistry");
|
||||
throw new IllegalStateException("Invalid object type passed into the CreativeModeTab dependencies " + entry.getClass());
|
||||
}
|
||||
|
||||
private static final BiMap<ResourceLocation, CreativeModeTab> creativeModeTabs = HashBiMap.create();
|
||||
private static final BiMap<ResourceLocation, CreativeModeTab> vanillaCreativeModeTabs = HashBiMap.create();
|
||||
private static final Multimap<ResourceLocation, ResourceLocation> edges = HashMultimap.create();
|
||||
private static final Multimap<ResourceLocation, ResourceLocation> vanillaEdges = HashMultimap.create();
|
||||
|
||||
static
|
||||
{
|
||||
final ResourceLocation buildingBlocks = new ResourceLocation("building_blocks");
|
||||
final ResourceLocation coloredBlocks = new ResourceLocation("colored_blocks");
|
||||
final ResourceLocation naturalBlocks = new ResourceLocation("natural_blocks");
|
||||
final ResourceLocation functionalBlocks = new ResourceLocation("functional_blocks");
|
||||
final ResourceLocation redstoneBlocks = new ResourceLocation("redstone_blocks");
|
||||
final ResourceLocation toolsAndUtilities = new ResourceLocation("tools_and_utilities");
|
||||
final ResourceLocation combat = new ResourceLocation("combat");
|
||||
final ResourceLocation foodAndDrinks = new ResourceLocation("food_and_drinks");
|
||||
final ResourceLocation ingredients = new ResourceLocation("ingredients");
|
||||
final ResourceLocation spawnEggs = new ResourceLocation("spawn_eggs");
|
||||
|
||||
processCreativeModeTab(CreativeModeTabs.BUILDING_BLOCKS, buildingBlocks, List.of(), List.of());
|
||||
processCreativeModeTab(CreativeModeTabs.COLORED_BLOCKS, coloredBlocks, List.of(buildingBlocks), List.of(naturalBlocks));
|
||||
processCreativeModeTab(CreativeModeTabs.NATURAL_BLOCKS, naturalBlocks, List.of(coloredBlocks), List.of(functionalBlocks));
|
||||
processCreativeModeTab(CreativeModeTabs.FUNCTIONAL_BLOCKS, functionalBlocks, List.of(naturalBlocks), List.of(redstoneBlocks));
|
||||
processCreativeModeTab(CreativeModeTabs.REDSTONE_BLOCKS, redstoneBlocks, List.of(functionalBlocks), List.of(toolsAndUtilities));
|
||||
processCreativeModeTab(CreativeModeTabs.TOOLS_AND_UTILITIES, toolsAndUtilities, List.of(redstoneBlocks), List.of(combat));
|
||||
processCreativeModeTab(CreativeModeTabs.COMBAT, combat, List.of(toolsAndUtilities), List.of(foodAndDrinks));
|
||||
processCreativeModeTab(CreativeModeTabs.FOOD_AND_DRINKS, foodAndDrinks, List.of(combat), List.of(ingredients));
|
||||
processCreativeModeTab(CreativeModeTabs.INGREDIENTS, ingredients, List.of(foodAndDrinks), List.of(spawnEggs));
|
||||
processCreativeModeTab(CreativeModeTabs.SPAWN_EGGS, spawnEggs, List.of(ingredients), List.of());
|
||||
|
||||
vanillaEdges.putAll(edges);
|
||||
vanillaCreativeModeTabs.putAll(creativeModeTabs);
|
||||
}
|
||||
|
||||
static PreparableReloadListener getReloadListener()
|
||||
{
|
||||
return new SimplePreparableReloadListener<JsonObject>()
|
||||
{
|
||||
final Gson gson = new GsonBuilder().create();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected JsonObject prepare(@NotNull ResourceManager resourceManager, ProfilerFiller profiler)
|
||||
{
|
||||
Optional<Resource> res = resourceManager.getResource(CREATIVE_MODE_TAB_ORDERING_JSON);
|
||||
if (res.isEmpty())
|
||||
return new JsonObject();
|
||||
|
||||
try (Reader reader = res.get().openAsReader())
|
||||
{
|
||||
return this.gson.fromJson(reader, JsonObject.class);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOGGER.error("Could not read CreativeModeTab sorting file " + CREATIVE_MODE_TAB_ORDERING_JSON, e);
|
||||
return new JsonObject();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void apply(@NotNull JsonObject data, @NotNull ResourceManager resourceManager, ProfilerFiller p)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (data.size() > 0)
|
||||
{
|
||||
JsonArray order = GsonHelper.getAsJsonArray(data, "order");
|
||||
List<CreativeModeTab> customOrder = new ArrayList<>();
|
||||
for (JsonElement entry : order)
|
||||
{
|
||||
ResourceLocation id = new ResourceLocation(entry.getAsString());
|
||||
CreativeModeTab CreativeModeTab = getTab(id);
|
||||
if (CreativeModeTab == null)
|
||||
throw new IllegalStateException("CreativeModeTab not found with name " + id);
|
||||
customOrder.add(CreativeModeTab);
|
||||
}
|
||||
|
||||
List<CreativeModeTab> missingCreativeModeTabs = creativeModeTabs.values().stream().filter(CreativeModeTab -> !customOrder.contains(CreativeModeTab)).toList();
|
||||
if (!missingCreativeModeTabs.isEmpty())
|
||||
throw new IllegalStateException("CreativeModeTabs missing from the ordered list: " + missingCreativeModeTabs.stream()
|
||||
.map(CreativeModeTab -> Objects.toString(CreativeModeTabRegistry.getName(CreativeModeTab))).collect(Collectors.joining(", ")));
|
||||
|
||||
setCreativeModeTabOrder(customOrder);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Error parsing CreativeModeTab sorting file " + CREATIVE_MODE_TAB_ORDERING_JSON, e);
|
||||
}
|
||||
|
||||
recalculateItemCreativeModeTabs();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnstableApiUsage")
|
||||
private static void recalculateItemCreativeModeTabs()
|
||||
{
|
||||
final MutableGraph<CreativeModeTab> graph = GraphBuilder.directed().nodeOrder(ElementOrder.<CreativeModeTab>insertion()).build();
|
||||
|
||||
for (CreativeModeTab CreativeModeTab : creativeModeTabs.values())
|
||||
{
|
||||
graph.addNode(CreativeModeTab);
|
||||
}
|
||||
edges.forEach((key, value) -> {
|
||||
if (creativeModeTabs.containsKey(key) && creativeModeTabs.containsKey(value))
|
||||
graph.putEdge(creativeModeTabs.get(key), creativeModeTabs.get(value));
|
||||
});
|
||||
List<CreativeModeTab> tierList = TopologicalSort.topologicalSort(graph, null);
|
||||
|
||||
setCreativeModeTabOrder(tierList);
|
||||
}
|
||||
|
||||
private static void setCreativeModeTabOrder(List<CreativeModeTab> tierList)
|
||||
{
|
||||
runInServerThreadIfPossible(hasServer -> {
|
||||
SORTED_TABS.clear();
|
||||
SORTED_TABS.addAll(tierList);
|
||||
});
|
||||
}
|
||||
|
||||
private static void runInServerThreadIfPossible(BooleanConsumer runnable)
|
||||
{
|
||||
MinecraftServer server = ServerLifecycleHooks.getCurrentServer();
|
||||
if (server != null)
|
||||
server.execute(() -> runnable.accept(true));
|
||||
else
|
||||
runnable.accept(false);
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
public static void fireCollectionEvent()
|
||||
{
|
||||
edges.clear();
|
||||
edges.putAll(vanillaEdges);
|
||||
|
||||
creativeModeTabs.clear();
|
||||
creativeModeTabs.putAll(vanillaCreativeModeTabs);
|
||||
|
||||
ModLoader.get().postEvent(new CreativeModeTabEvent.Register(CreativeModeTabRegistry::registerCreativeModeTab));
|
||||
|
||||
recalculateItemCreativeModeTabs();
|
||||
|
||||
if (FMLEnvironment.dist == Dist.CLIENT && !FMLLoader.getLaunchHandler().isData())
|
||||
CreativeModeTabSearchRegistry.createSearchTrees();
|
||||
}
|
||||
|
||||
@ApiStatus.Internal
|
||||
private static CreativeModeTab registerCreativeModeTab(Consumer<CreativeModeTab.Builder> configurator, ResourceLocation name, List<Object> afterEntries, List<Object> beforeEntries)
|
||||
{
|
||||
if (creativeModeTabs.containsKey(name))
|
||||
throw new IllegalStateException("Duplicate creative mode tab with name: " + name);
|
||||
|
||||
// The initial values for the builder do not matter
|
||||
CreativeModeTab.Builder builder = new CreativeModeTab.Builder(CreativeModeTab.Row.TOP, 0);
|
||||
configurator.accept(builder);
|
||||
CreativeModeTab creativeModeTab = builder.build();
|
||||
|
||||
if (creativeModeTab.isAlignedRight())
|
||||
throw new IllegalStateException("CreativeModeTab " + name + " is aligned right, this is not supported!");
|
||||
|
||||
processCreativeModeTab(creativeModeTab, name, afterEntries, beforeEntries);
|
||||
|
||||
return creativeModeTab;
|
||||
}
|
||||
}
|
||||
@@ -7,17 +7,25 @@ package net.minecraftforge.common;
|
||||
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.*;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Deque;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Multimap;
|
||||
@@ -27,8 +35,6 @@ import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
@@ -37,14 +43,24 @@ import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.commands.CommandSourceStack;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.commands.SharedSuggestionProvider;
|
||||
import net.minecraft.core.*;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.network.chat.ChatDecorator;
|
||||
import net.minecraft.network.chat.ClickEvent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.network.chat.TextColor;
|
||||
import net.minecraft.network.chat.contents.LiteralContents;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.TagEntry;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.util.CrudeIncrementalIntIdentityHashBiMap;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
import net.minecraft.util.Mth;
|
||||
import net.minecraft.util.datafix.fixes.StructuresBecomeConfiguredFix;
|
||||
import net.minecraft.world.Difficulty;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
@@ -77,15 +93,11 @@ import net.minecraft.world.level.storage.WorldData;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.level.storage.loot.LootTable;
|
||||
import net.minecraft.world.level.storage.loot.LootTables;
|
||||
import net.minecraft.util.*;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.inventory.AnvilMenu;
|
||||
import net.minecraft.world.Container;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
@@ -104,12 +116,10 @@ import net.minecraft.world.level.block.entity.BlockEntity;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.EntityHitResult;
|
||||
import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.BiomeSpecialEffects;
|
||||
import net.minecraft.world.level.biome.BiomeGenerationSettings;
|
||||
import net.minecraft.world.level.biome.MobSpawnSettings;
|
||||
import net.minecraftforge.common.crafting.conditions.ICondition;
|
||||
import net.minecraftforge.common.loot.IGlobalLootModifier;
|
||||
import net.minecraftforge.common.loot.LootModifierManager;
|
||||
import net.minecraftforge.common.loot.LootTableIdCondition;
|
||||
@@ -174,16 +184,13 @@ import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.resources.RegistryResourceAccess;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.resources.RegistryResourceAccess.EntryThunk;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.level.GameType;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelAccessor;
|
||||
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
|
||||
import net.minecraft.world.level.dimension.LevelStem;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||
@@ -215,66 +222,6 @@ public class ForgeHooks
|
||||
return player.hasCorrectToolForDrops(state);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a player uses 'pick block', calls new Entity and Block hooks.
|
||||
*/
|
||||
@SuppressWarnings("resource")
|
||||
@Deprecated(forRemoval = true, since = "1.19")
|
||||
public static boolean onPickBlock(HitResult target, Player player, Level level)
|
||||
{
|
||||
ItemStack result = ItemStack.EMPTY;
|
||||
boolean isCreative = player.getAbilities().instabuild;
|
||||
BlockEntity te = null;
|
||||
|
||||
if (target.getType() == HitResult.Type.BLOCK)
|
||||
{
|
||||
BlockPos pos = ((BlockHitResult)target).getBlockPos();
|
||||
BlockState state = level.getBlockState(pos);
|
||||
|
||||
if (state.isAir())
|
||||
return false;
|
||||
|
||||
if (isCreative && Screen.hasControlDown() && state.hasBlockEntity())
|
||||
te = level.getBlockEntity(pos);
|
||||
|
||||
result = state.getCloneItemStack(target, level, pos, player);
|
||||
|
||||
if (result.isEmpty())
|
||||
LOGGER.warn("Picking on: [{}] {} gave null item", target.getType(), ForgeRegistries.BLOCKS.getKey(state.getBlock()));
|
||||
}
|
||||
else if (target.getType() == HitResult.Type.ENTITY)
|
||||
{
|
||||
Entity entity = ((EntityHitResult)target).getEntity();
|
||||
result = entity.getPickedResult(target);
|
||||
|
||||
if (result.isEmpty())
|
||||
LOGGER.warn("Picking on: [{}] {} gave null item", target.getType(), ForgeRegistries.ENTITY_TYPES.getKey(entity.getType()));
|
||||
}
|
||||
|
||||
if (result.isEmpty())
|
||||
return false;
|
||||
|
||||
if (te != null)
|
||||
Minecraft.getInstance().addCustomNbtData(result, te);
|
||||
|
||||
if (isCreative)
|
||||
{
|
||||
player.getInventory().setPickedItem(result);
|
||||
Minecraft.getInstance().gameMode.handleCreativeModeItemAdd(player.getItemInHand(InteractionHand.MAIN_HAND), 36 + player.getInventory().selected);
|
||||
return true;
|
||||
}
|
||||
int slot = player.getInventory().findSlotMatchingItem(result);
|
||||
if (slot != -1)
|
||||
{
|
||||
if (Inventory.isHotbarSlot(slot))
|
||||
player.getInventory().selected = slot;
|
||||
else
|
||||
Minecraft.getInstance().gameMode.handlePickItem(slot);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean onItemStackedOn(ItemStack carriedItem, ItemStack stackedOnItem, Slot slot, ClickAction action, Player player, SlotAccess carriedSlotAccess)
|
||||
{
|
||||
return MinecraftForge.EVENT_BUS.post(new ItemStackedOnOtherEvent(carriedItem, stackedOnItem, slot, action, player, carriedSlotAccess));
|
||||
@@ -301,12 +248,12 @@ public class ForgeHooks
|
||||
{
|
||||
MinecraftForge.EVENT_BUS.post(new LivingSetAttackTargetEvent(entity, target, targetType));
|
||||
}
|
||||
|
||||
|
||||
public static LivingChangeTargetEvent onLivingChangeTarget(LivingEntity entity, LivingEntity originalTarget, ILivingTargetType targetType)
|
||||
{
|
||||
LivingChangeTargetEvent event = new LivingChangeTargetEvent(entity, originalTarget, targetType);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
@@ -457,71 +404,23 @@ public class ForgeHooks
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Component onServerChatSubmittedEvent(ServerPlayer player, String plain, Component decorated, boolean canChangeMessage)
|
||||
public static Component onServerChatSubmittedEvent(ServerPlayer player, String plain, Component decorated)
|
||||
{
|
||||
ServerChatEvent.Submitted event = new ServerChatEvent.Submitted(player, plain, decorated, canChangeMessage);
|
||||
ServerChatEvent event = new ServerChatEvent(player, plain, decorated);
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getMessage();
|
||||
}
|
||||
|
||||
private static final ChatDecorator SERVER_CHAT_SUBMITTED_DECORATOR = new ChatDecorator()
|
||||
{
|
||||
@NotNull
|
||||
@Override
|
||||
public CompletableFuture<Component> decorate(@Nullable ServerPlayer sender, Component message)
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
if (sender == null)
|
||||
return message; // Vanilla should never get here with the patches we use, but let's be safe with dumb mods
|
||||
|
||||
return onServerChatSubmittedEvent(sender, getRawText(message), message, true);
|
||||
});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public CompletableFuture<PlayerChatMessage> decorate(@Nullable ServerPlayer sender, PlayerChatMessage message)
|
||||
{
|
||||
if (message.signedContent().isDecorated())
|
||||
{
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
if (sender != null)
|
||||
return onServerChatSubmittedEvent(sender, message.signedContent().plain(), message.signedContent().decorated(), false) == null;
|
||||
|
||||
return false;
|
||||
}).thenApply(canceled -> canceled == Boolean.TRUE ? null : message);
|
||||
}
|
||||
|
||||
return this.decorate(sender, message.serverContent()).thenApply(component -> component == null ? null : message.withUnsignedContent(component));
|
||||
}
|
||||
};
|
||||
|
||||
@NotNull
|
||||
public static ChatDecorator getServerChatSubmittedDecorator()
|
||||
{
|
||||
return SERVER_CHAT_SUBMITTED_DECORATOR;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public static Component onServerChatPreviewEvent(@NotNull ServerPlayer player, @NotNull Component message)
|
||||
{
|
||||
ServerChatEvent.Preview event = new ServerChatEvent.Preview(player, getRawText(message), message);
|
||||
return MinecraftForge.EVENT_BUS.post(event) ? null : event.getMessage();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static ChatDecorator getServerChatPreviewDecorator()
|
||||
{
|
||||
return (player, message) -> CompletableFuture.supplyAsync(() -> {
|
||||
if (player == null)
|
||||
return (sender, message) -> CompletableFuture.supplyAsync(() -> {
|
||||
if (sender == null)
|
||||
return message; // Vanilla should never get here with the patches we use, but let's be safe with dumb mods
|
||||
|
||||
Component preview = onServerChatPreviewEvent(player, message);
|
||||
// Send the input message back to the client if the event was cancelled
|
||||
return preview == null ? message : preview;
|
||||
return onServerChatSubmittedEvent(sender, getRawText(message), message);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
static final Pattern URL_PATTERN = Pattern.compile(
|
||||
// schema ipv4 OR namespace port path ends
|
||||
// |-----------------| |-------------------------| |-------------------------| |---------| |--| |---------------|
|
||||
@@ -615,7 +514,7 @@ public class ForgeHooks
|
||||
|
||||
if (!entityPlayer.mayBuild())
|
||||
{
|
||||
if (itemstack.isEmpty() || !itemstack.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY), new BlockInWorld(level, pos, false)))
|
||||
if (itemstack.isEmpty() || !itemstack.hasAdventureModeBreakTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, pos, false)))
|
||||
preCancelEvent = true;
|
||||
}
|
||||
}
|
||||
@@ -658,7 +557,7 @@ public class ForgeHooks
|
||||
Level level = context.getLevel();
|
||||
|
||||
Player player = context.getPlayer();
|
||||
if (player != null && !player.getAbilities().mayBuild && !itemstack.hasAdventureModePlaceTagForBlock(level.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY), new BlockInWorld(level, context.getClickedPos(), false)))
|
||||
if (player != null && !player.getAbilities().mayBuild && !itemstack.hasAdventureModePlaceTagForBlock(level.registryAccess().registryOrThrow(Registries.BLOCK), new BlockInWorld(level, context.getClickedPos(), false)))
|
||||
return InteractionResult.PASS;
|
||||
|
||||
// handle all placement events here
|
||||
@@ -978,6 +877,11 @@ public class ForgeHooks
|
||||
};
|
||||
}
|
||||
|
||||
public static Collection<CreativeModeTab> onCheckCreativeTabs(CreativeModeTab... vanillaTabs) {
|
||||
final List<CreativeModeTab> tabs = new ArrayList<>(Arrays.asList(vanillaTabs));
|
||||
return tabs;
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface BiomeCallbackFunction
|
||||
{
|
||||
@@ -1340,8 +1244,6 @@ public class ForgeHooks
|
||||
private static final Set<String> VANILLA_DIMS = Sets.newHashSet("minecraft:overworld", "minecraft:the_nether", "minecraft:the_end");
|
||||
private static final String DIMENSIONS_KEY = "dimensions";
|
||||
private static final String SEED_KEY = "seed";
|
||||
//No to static init!
|
||||
private static final Supplier<Codec<Registry<LevelStem>>> CODEC = Suppliers.memoize(() -> RegistryCodecs.dataPackAwareCodec(Registry.LEVEL_STEM_REGISTRY, Lifecycle.stable(), LevelStem.CODEC).xmap(LevelStem::sortMap, Function.identity()));
|
||||
|
||||
private static final Map<EntityType<? extends LivingEntity>, AttributeSupplier> FORGE_ATTRIBUTES = new HashMap<>();
|
||||
/** FOR INTERNAL USE ONLY, DO NOT CALL DIRECTLY */
|
||||
@@ -1665,12 +1567,4 @@ public class ForgeHooks
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <E> Collection<Entry<ResourceKey<E>, EntryThunk<E>>> filterThunks(Map<ResourceKey<E>, RegistryResourceAccess.EntryThunk<E>> map)
|
||||
{
|
||||
return map.entrySet().stream().filter(e ->
|
||||
((EntryThunk<Boolean>)e.getValue()).parseElement(JsonOps.INSTANCE, ICondition.DECODER)
|
||||
.get().left().get().value()).toList(); // Validity of this .get() call is enforced by the above Decoder object, which only returns DataResult.success.
|
||||
}
|
||||
}
|
||||
@@ -133,6 +133,7 @@ public class ForgeInternalHandler
|
||||
public void resourceReloadListeners(AddReloadListenerEvent event)
|
||||
{
|
||||
event.addListener(TierSortingRegistry.getReloadListener());
|
||||
event.addListener(CreativeModeTabRegistry.getReloadListener());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,9 @@ import net.minecraft.commands.synchronization.ArgumentTypeInfo;
|
||||
import net.minecraft.commands.synchronization.ArgumentTypeInfos;
|
||||
import net.minecraft.commands.synchronization.SingletonArgumentInfo;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.sounds.SoundEvents;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Mob;
|
||||
@@ -29,13 +32,11 @@ import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.util.ExtraCodecs;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryCodecs;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.pathfinder.BlockPathTypes;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.client.extensions.common.IClientFluidTypeExtensions;
|
||||
import net.minecraftforge.common.capabilities.RegisterCapabilitiesEvent;
|
||||
import net.minecraftforge.common.crafting.PartialNBTIngredient;
|
||||
import net.minecraftforge.common.crafting.DifferenceIngredient;
|
||||
import net.minecraftforge.common.crafting.IntersectionIngredient;
|
||||
@@ -54,7 +55,6 @@ import net.minecraftforge.common.world.ForgeBiomeModifiers.RemoveSpawnsBiomeModi
|
||||
import net.minecraftforge.common.world.NoneBiomeModifier;
|
||||
import net.minecraftforge.common.world.NoneStructureModifier;
|
||||
import net.minecraftforge.common.world.StructureModifier;
|
||||
import net.minecraftforge.event.ServerChatEvent;
|
||||
import net.minecraftforge.eventbus.api.IEventBus;
|
||||
import net.minecraftforge.fluids.FluidType;
|
||||
import net.minecraftforge.fluids.ForgeFlowingFluid;
|
||||
@@ -103,9 +103,6 @@ import net.minecraftforge.common.data.ForgeEntityTypeTagsProvider;
|
||||
import net.minecraftforge.common.data.ForgeItemTagsProvider;
|
||||
import net.minecraftforge.common.data.ForgeLootTableProvider;
|
||||
import net.minecraftforge.common.data.ForgeRecipeProvider;
|
||||
import net.minecraftforge.energy.CapabilityEnergy;
|
||||
import net.minecraftforge.fluids.capability.CapabilityFluidHandler;
|
||||
import net.minecraftforge.items.CapabilityItemHandler;
|
||||
import net.minecraftforge.fml.common.Mod;
|
||||
import org.apache.logging.log4j.Marker;
|
||||
import org.apache.logging.log4j.MarkerManager;
|
||||
@@ -116,6 +113,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -127,7 +125,7 @@ public class ForgeMod
|
||||
private static final Marker FORGEMOD = MarkerManager.getMarker("FORGEMOD");
|
||||
|
||||
private static final DeferredRegister<Attribute> ATTRIBUTES = DeferredRegister.create(ForgeRegistries.Keys.ATTRIBUTES, "forge");
|
||||
private static final DeferredRegister<ArgumentTypeInfo<?, ?>> COMMAND_ARGUMENT_TYPES = DeferredRegister.create(Registry.COMMAND_ARGUMENT_TYPE_REGISTRY, "forge");
|
||||
private static final DeferredRegister<ArgumentTypeInfo<?, ?>> COMMAND_ARGUMENT_TYPES = DeferredRegister.create(Registries.COMMAND_ARGUMENT_TYPE, "forge");
|
||||
private static final DeferredRegister<Codec<? extends BiomeModifier>> BIOME_MODIFIER_SERIALIZERS = DeferredRegister.create(ForgeRegistries.Keys.BIOME_MODIFIER_SERIALIZERS, "forge");
|
||||
private static final DeferredRegister<Codec<? extends StructureModifier>> STRUCTURE_MODIFIER_SERIALIZERS = DeferredRegister.create(ForgeRegistries.Keys.STRUCTURE_MODIFIER_SERIALIZERS, "forge");
|
||||
private static final DeferredRegister<HolderSetType> HOLDER_SET_TYPES = DeferredRegister.create(ForgeRegistries.Keys.HOLDER_SET_TYPES, "forge");
|
||||
@@ -384,7 +382,6 @@ public class ForgeMod
|
||||
});
|
||||
|
||||
private static boolean enableMilkFluid = false;
|
||||
private static boolean serverChatPreviewEnabled = false;
|
||||
public static final RegistryObject<FluidType> MILK_TYPE = RegistryObject.createOptional(new ResourceLocation("milk"), ForgeRegistries.Keys.FLUID_TYPES.location(), "minecraft");
|
||||
public static final RegistryObject<Fluid> MILK = RegistryObject.create(new ResourceLocation("milk"), ForgeRegistries.FLUIDS);
|
||||
public static final RegistryObject<Fluid> FLOWING_MILK = RegistryObject.create(new ResourceLocation("flowing_milk"), ForgeRegistries.FLUIDS);
|
||||
@@ -403,25 +400,6 @@ public class ForgeMod
|
||||
enableMilkFluid = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run this method during mod constructor to enable chat previews for the server.
|
||||
* Recommended for mods which modify the chat message in {@link ServerChatEvent}.
|
||||
*
|
||||
* @see ServerChatEvent
|
||||
*/
|
||||
public static void enableServerChatPreview()
|
||||
{
|
||||
serverChatPreviewEnabled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if server chat previews are enabled
|
||||
*/
|
||||
public static boolean isServerChatPreviewEnabled()
|
||||
{
|
||||
return serverChatPreviewEnabled;
|
||||
}
|
||||
|
||||
public ForgeMod()
|
||||
{
|
||||
LOGGER.info(FORGEMOD,"Forge mod loading, version {}, for MC {} with MCP {}", ForgeVersion.getVersion(), MCPVersion.getMCVersion(), MCPVersion.getMCPVersion());
|
||||
@@ -438,6 +416,11 @@ public class ForgeMod
|
||||
CrashReportCallables.registerCrashCallable("Forge", ()->ForgeVersion.getGroup()+":"+ForgeVersion.getVersion());
|
||||
|
||||
final IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
|
||||
// Forge-provided datapack registries
|
||||
modEventBus.addListener((DataPackRegistryEvent.NewRegistry event) -> {
|
||||
event.dataPackRegistry(ForgeRegistries.Keys.BIOME_MODIFIERS, BiomeModifier.DIRECT_CODEC);
|
||||
event.dataPackRegistry(ForgeRegistries.Keys.STRUCTURE_MODIFIERS, StructureModifier.DIRECT_CODEC);
|
||||
});
|
||||
modEventBus.addListener(this::preInit);
|
||||
modEventBus.addListener(this::gatherData);
|
||||
modEventBus.addListener(this::loadComplete);
|
||||
@@ -493,16 +476,18 @@ public class ForgeMod
|
||||
public void gatherData(GatherDataEvent event)
|
||||
{
|
||||
DataGenerator gen = event.getGenerator();
|
||||
PackOutput packOutput = gen.getPackOutput();
|
||||
CompletableFuture<HolderLookup.Provider> lookupProvider = event.getLookupProvider();
|
||||
|
||||
ExistingFileHelper existingFileHelper = event.getExistingFileHelper();
|
||||
ForgeBlockTagsProvider blockTags = new ForgeBlockTagsProvider(gen, existingFileHelper);
|
||||
ForgeBlockTagsProvider blockTags = new ForgeBlockTagsProvider(packOutput, lookupProvider, existingFileHelper);
|
||||
gen.addProvider(event.includeServer(), blockTags);
|
||||
gen.addProvider(event.includeServer(), new ForgeItemTagsProvider(gen, blockTags, existingFileHelper));
|
||||
gen.addProvider(event.includeServer(), new ForgeEntityTypeTagsProvider(gen, existingFileHelper));
|
||||
gen.addProvider(event.includeServer(), new ForgeFluidTagsProvider(gen, existingFileHelper));
|
||||
gen.addProvider(event.includeServer(), new ForgeRecipeProvider(gen));
|
||||
gen.addProvider(event.includeServer(), new ForgeLootTableProvider(gen));
|
||||
gen.addProvider(event.includeServer(), new ForgeBiomeTagsProvider(gen, existingFileHelper));
|
||||
gen.addProvider(event.includeServer(), new ForgeItemTagsProvider(packOutput, lookupProvider, blockTags, existingFileHelper));
|
||||
gen.addProvider(event.includeServer(), new ForgeEntityTypeTagsProvider(packOutput, lookupProvider, existingFileHelper));
|
||||
gen.addProvider(event.includeServer(), new ForgeFluidTagsProvider(packOutput, lookupProvider, existingFileHelper));
|
||||
gen.addProvider(event.includeServer(), new ForgeRecipeProvider(packOutput));
|
||||
gen.addProvider(event.includeServer(), new ForgeLootTableProvider(packOutput));
|
||||
gen.addProvider(event.includeServer(), new ForgeBiomeTagsProvider(packOutput, lookupProvider, existingFileHelper));
|
||||
}
|
||||
|
||||
public void missingSoundMapping(MissingMappingsEvent event)
|
||||
@@ -595,11 +580,11 @@ public class ForgeMod
|
||||
|
||||
public void registerLootData(RegisterEvent event)
|
||||
{
|
||||
if (!event.getRegistryKey().equals(Registry.LOOT_ITEM_REGISTRY))
|
||||
if (!event.getRegistryKey().equals(Registries.LOOT_CONDITION_TYPE))
|
||||
return;
|
||||
|
||||
event.register(Registry.LOOT_ITEM_REGISTRY, new ResourceLocation("forge:loot_table_id"), () -> LootTableIdCondition.LOOT_TABLE_ID);
|
||||
event.register(Registry.LOOT_ITEM_REGISTRY, new ResourceLocation("forge:can_tool_perform_action"), () -> CanToolPerformAction.LOOT_CONDITION_TYPE);
|
||||
event.register(Registries.LOOT_CONDITION_TYPE, new ResourceLocation("forge:loot_table_id"), () -> LootTableIdCondition.LOOT_TABLE_ID);
|
||||
event.register(Registries.LOOT_CONDITION_TYPE, new ResourceLocation("forge:can_tool_perform_action"), () -> CanToolPerformAction.LOOT_CONDITION_TYPE);
|
||||
}
|
||||
|
||||
public static final PermissionNode<Boolean> USE_SELECTORS_PERMISSION = new PermissionNode<>("forge", "use_entity_selectors",
|
||||
|
||||
@@ -63,7 +63,10 @@ public class ForgeSpawnEggItem extends SpawnEggItem
|
||||
return ret != null ? ret : SpawnEggItem.byId(type);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected EntityType<?> getDefaultType() {
|
||||
return this.typeSupplier.get();
|
||||
}
|
||||
|
||||
private static final DispenseItemBehavior DEFAULT_DISPENSE_BEHAVIOR = (source, stack) ->
|
||||
{
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.common;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BiomeTags;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
@@ -191,7 +192,7 @@ public class Tags
|
||||
|
||||
private static TagKey<EntityType<?>> tag(String name)
|
||||
{
|
||||
return TagKey.create(Registry.ENTITY_TYPE_REGISTRY, new ResourceLocation("forge", name));
|
||||
return TagKey.create(Registries.ENTITY_TYPE, new ResourceLocation("forge", name));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -614,7 +615,7 @@ public class Tags
|
||||
|
||||
private static TagKey<Biome> tag(String name)
|
||||
{
|
||||
return TagKey.create(Registry.BIOME_REGISTRY, new ResourceLocation("forge", name));
|
||||
return TagKey.create(Registries.BIOME, new ResourceLocation("forge", name));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,11 +5,8 @@
|
||||
|
||||
package net.minecraftforge.common.crafting.conditions;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import com.mojang.serialization.DataResult;
|
||||
import com.mojang.serialization.Decoder;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
@@ -24,27 +21,13 @@ import java.util.Set;
|
||||
|
||||
public interface ICondition
|
||||
{
|
||||
static boolean shouldRegisterEntry(JsonElement json)
|
||||
{
|
||||
if (!(json instanceof JsonObject obj) || !obj.has("forge:conditions"))
|
||||
return true;
|
||||
|
||||
Decoder<Boolean> DECODER = new Decoder<>() {
|
||||
@Override
|
||||
public <T> DataResult<Pair<Boolean, T>> decode(DynamicOps<T> ops, T input)
|
||||
{
|
||||
if(input instanceof JsonObject obj && obj.has("forge:conditions"))
|
||||
{
|
||||
try
|
||||
{
|
||||
boolean result = CraftingHelper.processConditions(obj, "forge:conditions", IContext.TAGS_INVALID);
|
||||
return DataResult.success(Pair.of(result, input));
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
return DataResult.success(Pair.of(false, input)); // Print stacktrace and do not load errored conditions.
|
||||
}
|
||||
}
|
||||
return DataResult.success(Pair.of(true, input));
|
||||
}
|
||||
};
|
||||
return CraftingHelper.processConditions(obj, "forge:conditions", IContext.TAGS_INVALID);
|
||||
}
|
||||
|
||||
ResourceLocation getID();
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ package net.minecraftforge.common.crafting.conditions;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.util.GsonHelper;
|
||||
@@ -30,7 +31,7 @@ public class TagEmptyCondition implements ICondition
|
||||
|
||||
public TagEmptyCondition(ResourceLocation tag)
|
||||
{
|
||||
this.tag = TagKey.create(Registry.ITEM_REGISTRY, tag);
|
||||
this.tag = TagKey.create(Registries.ITEM, tag);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.IntrinsicHolderTagsProvider;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class BlockTagsProvider extends IntrinsicHolderTagsProvider<Block>
|
||||
{
|
||||
@SuppressWarnings("deprecation")
|
||||
public BlockTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, String modId, @Nullable ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(output, Registries.BLOCK, lookupProvider, block -> block.builtInRegistryHolder().key(), modId, existingFileHelper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.core.RegistrySetBuilder;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.registries.RegistriesDatapackGenerator;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class DatapackBuiltinEntriesProvider extends RegistriesDatapackGenerator
|
||||
{
|
||||
public DatapackBuiltinEntriesProvider(PackOutput output, Supplier<HolderLookup.Provider> registriesSupplier)
|
||||
{
|
||||
super(output, CompletableFuture.supplyAsync(registriesSupplier, Util.backgroundExecutor()));
|
||||
}
|
||||
|
||||
public DatapackBuiltinEntriesProvider(PackOutput output, RegistrySetBuilder datapackEntriesBuilder)
|
||||
{
|
||||
this(output, () -> createLookup(datapackEntriesBuilder));
|
||||
}
|
||||
|
||||
public static HolderLookup.Provider createLookup(RegistrySetBuilder datapackEntriesBuilder) {
|
||||
return datapackEntriesBuilder.build(RegistryAccess.fromRegistryOfRegistries(BuiltInRegistries.REGISTRY));
|
||||
}
|
||||
}
|
||||
@@ -18,12 +18,10 @@ import com.google.common.collect.HashMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
import net.minecraft.client.resources.ClientPackSource;
|
||||
import net.minecraft.client.resources.AssetIndex;
|
||||
import net.minecraft.client.resources.DefaultClientPackResources;
|
||||
import net.minecraft.client.resources.IndexedAssetSource;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.HashCache;
|
||||
import net.minecraft.server.packs.FilePackResources;
|
||||
import net.minecraft.server.packs.FolderPackResources;
|
||||
import net.minecraft.server.packs.PathPackResources;
|
||||
import net.minecraft.server.packs.repository.ServerPacksSource;
|
||||
import net.minecraft.server.packs.resources.MultiPackResourceManager;
|
||||
import net.minecraft.server.packs.resources.Resource;
|
||||
@@ -98,15 +96,14 @@ public class ExistingFileHelper {
|
||||
List<PackResources> candidateClientResources = new ArrayList<>();
|
||||
List<PackResources> candidateServerResources = new ArrayList<>();
|
||||
|
||||
candidateClientResources.add(new VanillaPackResources(ClientPackSource.BUILT_IN, "minecraft", "realms"));
|
||||
if (assetIndex != null && assetsDir != null)
|
||||
if (assetIndex != null && assetsDir != null && assetsDir.exists())
|
||||
{
|
||||
candidateClientResources.add(new DefaultClientPackResources(ClientPackSource.BUILT_IN, new AssetIndex(assetsDir, assetIndex)));
|
||||
candidateClientResources.add(ClientPackSource.createVanillaPackSource(IndexedAssetSource.createIndexFs(assetsDir.toPath(), assetIndex)));
|
||||
}
|
||||
candidateServerResources.add(new VanillaPackResources(ServerPacksSource.BUILT_IN_METADATA, "minecraft"));
|
||||
candidateServerResources.add(ServerPacksSource.createVanillaPackSource());
|
||||
for (Path existing : existingPacks) {
|
||||
File file = existing.toFile();
|
||||
PackResources pack = file.isDirectory() ? new FolderPackResources(file) : new FilePackResources(file);
|
||||
PackResources pack = file.isDirectory() ? new PathPackResources(file.getName(), file.toPath(), false) : new FilePackResources(file.getName(), file, false);
|
||||
candidateClientResources.add(pack);
|
||||
candidateServerResources.add(pack);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.BiomeTagsProvider;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.tags.BiomeTags;
|
||||
@@ -14,16 +15,18 @@ import net.minecraft.world.level.biome.Biome;
|
||||
import net.minecraft.world.level.biome.Biomes;
|
||||
import net.minecraftforge.common.Tags;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public final class ForgeBiomeTagsProvider extends BiomeTagsProvider
|
||||
{
|
||||
|
||||
public ForgeBiomeTagsProvider(DataGenerator arg, ExistingFileHelper existingFileHelper)
|
||||
public ForgeBiomeTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(arg, "forge", existingFileHelper);
|
||||
super(output, lookupProvider, "forge", existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addTags()
|
||||
protected void addTags(HolderLookup.Provider lookupProvider)
|
||||
{
|
||||
tag(Biomes.PLAINS, Tags.Biomes.IS_PLAINS);
|
||||
tag(Biomes.DESERT, Tags.Biomes.IS_HOT_OVERWORLD, Tags.Biomes.IS_DRY_OVERWORLD, Tags.Biomes.IS_SANDY, Tags.Biomes.IS_DESERT);
|
||||
|
||||
@@ -5,8 +5,10 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.tags.BlockTagsProvider;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.IntrinsicHolderTagsProvider;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.BlockTags;
|
||||
import net.minecraft.tags.TagKey;
|
||||
@@ -15,22 +17,24 @@ import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraftforge.common.Tags;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import static net.minecraftforge.common.Tags.Blocks.*;
|
||||
|
||||
public final class ForgeBlockTagsProvider extends BlockTagsProvider
|
||||
{
|
||||
public ForgeBlockTagsProvider(DataGenerator gen, ExistingFileHelper existingFileHelper)
|
||||
public ForgeBlockTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, @Nullable ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(gen, "forge", existingFileHelper);
|
||||
super(output, lookupProvider, "forge", existingFileHelper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void addTags()
|
||||
public void addTags(HolderLookup.Provider p_256380_)
|
||||
{
|
||||
tag(BARRELS).addTag(BARRELS_WOODEN);
|
||||
tag(BARRELS_WOODEN).add(Blocks.BARREL);
|
||||
|
||||
@@ -5,21 +5,24 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.EntityTypeTagsProvider;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraftforge.common.Tags;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class ForgeEntityTypeTagsProvider extends EntityTypeTagsProvider
|
||||
{
|
||||
|
||||
public ForgeEntityTypeTagsProvider(DataGenerator generator, ExistingFileHelper existingFileHelper)
|
||||
|
||||
public ForgeEntityTypeTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(generator, "forge", existingFileHelper);
|
||||
super(output, lookupProvider, "forge", existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTags()
|
||||
public void addTags(HolderLookup.Provider lookupProvider)
|
||||
{
|
||||
tag(Tags.EntityTypes.BOSSES).add(EntityType.ENDER_DRAGON, EntityType.WITHER);
|
||||
}
|
||||
|
||||
@@ -5,21 +5,24 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.FluidTagsProvider;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import static net.minecraftforge.common.Tags.Fluids.MILK;
|
||||
|
||||
public final class ForgeFluidTagsProvider extends FluidTagsProvider
|
||||
{
|
||||
public ForgeFluidTagsProvider(DataGenerator gen, ExistingFileHelper existingFileHelper)
|
||||
public ForgeFluidTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(gen, "forge", existingFileHelper);
|
||||
super(output, lookupProvider, "forge", existingFileHelper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTags()
|
||||
public void addTags(HolderLookup.Provider lookupProvider)
|
||||
{
|
||||
tag(MILK).addOptional(ForgeMod.MILK.getId()).addOptional(ForgeMod.FLOWING_MILK.getId());
|
||||
}
|
||||
|
||||
@@ -5,9 +5,10 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.tags.BlockTagsProvider;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.tags.ItemTagsProvider;
|
||||
import net.minecraft.data.tags.TagsProvider;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.DyeColor;
|
||||
@@ -18,18 +19,19 @@ import net.minecraftforge.common.Tags;
|
||||
import net.minecraftforge.registries.ForgeRegistries;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ForgeItemTagsProvider extends ItemTagsProvider
|
||||
{
|
||||
public ForgeItemTagsProvider(DataGenerator gen, BlockTagsProvider blockTagProvider, ExistingFileHelper existingFileHelper)
|
||||
public ForgeItemTagsProvider(PackOutput output, CompletableFuture<HolderLookup.Provider> lookupProvider, TagsProvider<Block> blockTagProvider, ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(gen, blockTagProvider, "forge", existingFileHelper);
|
||||
super(output, lookupProvider, blockTagProvider, "forge", existingFileHelper);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void addTags()
|
||||
public void addTags(HolderLookup.Provider lookupProvider)
|
||||
{
|
||||
copy(Tags.Blocks.BARRELS, Tags.Items.BARRELS);
|
||||
copy(Tags.Blocks.BARRELS_WOODEN, Tags.Items.BARRELS_WOODEN);
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import com.mojang.datafixers.util.Pair;
|
||||
import net.minecraft.advancements.critereon.ItemPredicate;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.loot.LootTableProvider;
|
||||
import net.minecraft.data.loot.LootTableSubProvider;
|
||||
import net.minecraft.data.loot.packs.VanillaLootTableProvider;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -24,9 +25,6 @@ import net.minecraftforge.fml.util.ObfuscationReflectionHelper;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import net.minecraft.world.level.storage.loot.LootPool;
|
||||
@@ -34,32 +32,30 @@ import net.minecraft.world.level.storage.loot.LootTable;
|
||||
import net.minecraft.world.level.storage.loot.ValidationContext;
|
||||
import net.minecraft.world.level.storage.loot.entries.CompositeEntryBase;
|
||||
import net.minecraft.world.level.storage.loot.entries.LootPoolEntryContainer;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSet;
|
||||
|
||||
/**
|
||||
* Currently used only for replacing shears item to shears_dig tool action
|
||||
*/
|
||||
public final class ForgeLootTableProvider extends LootTableProvider {
|
||||
|
||||
public ForgeLootTableProvider(DataGenerator gen) {
|
||||
super(gen);
|
||||
public ForgeLootTableProvider(PackOutput packOutput) {
|
||||
super(packOutput, Set.of(), VanillaLootTableProvider.create(packOutput).getTables());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validate(Map<ResourceLocation, LootTable> map, ValidationContext validationtracker) {
|
||||
// do not validate against all registered loot tables
|
||||
protected void validate(Map<ResourceLocation, LootTable> map, ValidationContext validationcontext) {
|
||||
// Do not validate against all registered loot tables
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<Pair<Supplier<Consumer<BiConsumer<ResourceLocation, LootTable.Builder>>>, LootContextParamSet>> getTables() {
|
||||
return super.getTables().stream().map(pair -> {
|
||||
// provides new consumer with filtering only changed loot tables and replacing condition item to condition tag
|
||||
return new Pair<Supplier<Consumer<BiConsumer<ResourceLocation, LootTable.Builder>>>, LootContextParamSet>(() -> replaceAndFilterChangesOnly(pair.getFirst().get()), pair.getSecond());
|
||||
public List<LootTableProvider.SubProviderEntry> getTables() {
|
||||
return super.getTables().stream().map(entry -> {
|
||||
// Provides new sub provider with filtering only changed loot tables and replacing condition item to condition tag
|
||||
return new LootTableProvider.SubProviderEntry(() -> replaceAndFilterChangesOnly(entry.provider().get()), entry.paramSet());
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private Consumer<BiConsumer<ResourceLocation, LootTable.Builder>> replaceAndFilterChangesOnly(Consumer<BiConsumer<ResourceLocation, LootTable.Builder>> consumer) {
|
||||
return (newConsumer) -> consumer.accept((resourceLocation, builder) -> {
|
||||
private LootTableSubProvider replaceAndFilterChangesOnly(LootTableSubProvider subProvider) {
|
||||
return newConsumer -> subProvider.generate((resourceLocation, builder) -> {
|
||||
if (findAndReplaceInLootTableBuilder(builder, Items.SHEARS, ToolActions.SHEARS_DIG)) {
|
||||
newConsumer.accept(resourceLocation, builder);
|
||||
}
|
||||
|
||||
@@ -6,12 +6,13 @@
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.advancements.Advancement;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.data.recipes.FinishedRecipe;
|
||||
import net.minecraft.data.recipes.RecipeProvider;
|
||||
import net.minecraft.data.recipes.ShapedRecipeBuilder;
|
||||
import net.minecraft.data.recipes.ShapelessRecipeBuilder;
|
||||
import net.minecraft.data.recipes.packs.VanillaRecipeProvider;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
import net.minecraft.world.item.Item;
|
||||
@@ -30,16 +31,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class ForgeRecipeProvider extends RecipeProvider
|
||||
public final class ForgeRecipeProvider extends VanillaRecipeProvider
|
||||
{
|
||||
private final Map<Item, TagKey<Item>> replacements = new HashMap<>();
|
||||
private final Set<ResourceLocation> excludes = new HashSet<>();
|
||||
|
||||
public ForgeRecipeProvider(DataGenerator generatorIn)
|
||||
public ForgeRecipeProvider(PackOutput packOutput)
|
||||
{
|
||||
super(generatorIn);
|
||||
super(packOutput);
|
||||
}
|
||||
|
||||
private void exclude(ItemLike item)
|
||||
@@ -53,7 +55,7 @@ public final class ForgeRecipeProvider extends RecipeProvider
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void buildCraftingRecipes(Consumer<FinishedRecipe> consumer)
|
||||
protected void buildRecipes(Consumer<FinishedRecipe> consumer)
|
||||
{
|
||||
replace(Items.STICK, Tags.Items.RODS_WOODEN);
|
||||
replace(Items.GOLD_INGOT, Tags.Items.INGOTS_GOLD);
|
||||
@@ -84,7 +86,7 @@ public final class ForgeRecipeProvider extends RecipeProvider
|
||||
exclude(Blocks.COBBLED_DEEPSLATE_SLAB);
|
||||
exclude(Blocks.COBBLED_DEEPSLATE_WALL);
|
||||
|
||||
super.buildCraftingRecipes(vanilla -> {
|
||||
super.buildRecipes(vanilla -> {
|
||||
FinishedRecipe modified = enhance(vanilla);
|
||||
if (modified != null)
|
||||
consumer.accept(modified);
|
||||
@@ -118,10 +120,19 @@ public final class ForgeRecipeProvider extends RecipeProvider
|
||||
return modified ? vanilla : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected void saveAdvancement(CachedOutput output, JsonObject advancementJson, Path pathIn)
|
||||
protected CompletableFuture<?> saveAdvancement(CachedOutput output, FinishedRecipe finishedRecipe, JsonObject advancementJson)
|
||||
{
|
||||
//NOOP - We dont replace any of the advancement things yet...
|
||||
// NOOP - We don't replace any of the advancement things yet...
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CompletableFuture<?> buildAdvancement(CachedOutput p_253674_, ResourceLocation p_254102_, Advancement.Builder p_253712_)
|
||||
{
|
||||
// NOOP - We don't replace any of the advancement things yet...
|
||||
return CompletableFuture.allOf();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import com.mojang.serialization.Lifecycle;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.tags.TagsProvider;
|
||||
import net.minecraftforge.registries.GameData;
|
||||
import net.minecraftforge.registries.IForgeRegistry;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public abstract class ForgeRegistryTagsProvider<T> extends TagsProvider<T>
|
||||
{
|
||||
private static <T> Registry<T> wrapRegistry(IForgeRegistry<T> forgeRegistry)
|
||||
{
|
||||
if (forgeRegistry.tags() == null)
|
||||
throw new IllegalArgumentException("Forge registry " + forgeRegistry.getRegistryName() + " does not have support for tags");
|
||||
if (forgeRegistry.getDefaultKey() == null)
|
||||
return GameData.getWrapper(forgeRegistry.getRegistryKey(), Lifecycle.experimental());
|
||||
return GameData.getWrapper(forgeRegistry.getRegistryKey(), Lifecycle.experimental(), "default");
|
||||
}
|
||||
|
||||
public ForgeRegistryTagsProvider(DataGenerator generator, IForgeRegistry<T> forgeRegistry, String modId, @Nullable ExistingFileHelper existingFileHelper)
|
||||
{
|
||||
super(generator, wrapRegistry(forgeRegistry), modId, existingFileHelper);
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -14,6 +15,7 @@ import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraftforge.common.loot.IGlobalLootModifier;
|
||||
import net.minecraftforge.common.loot.LootModifier;
|
||||
@@ -24,6 +26,7 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
@@ -59,26 +62,30 @@ public abstract class GlobalLootModifierProvider implements DataProvider
|
||||
protected abstract void start();
|
||||
|
||||
@Override
|
||||
public void run(CachedOutput cache) throws IOException
|
||||
public CompletableFuture<?> run(CachedOutput cache)
|
||||
{
|
||||
start();
|
||||
|
||||
Path forgePath = gen.getOutputFolder().resolve("data/forge/loot_modifiers/global_loot_modifiers.json");
|
||||
String modPath = "data/" + modid + "/loot_modifiers/";
|
||||
Path forgePath = this.gen.getPackOutput().getOutputFolder(PackOutput.Target.DATA_PACK).resolve("forge").resolve("loot_modifiers").resolve("global_loot_modifiers.json");
|
||||
Path modifierFolderPath = this.gen.getPackOutput().getOutputFolder(PackOutput.Target.DATA_PACK).resolve(this.modid).resolve("loot_modifiers");
|
||||
List<ResourceLocation> entries = new ArrayList<>();
|
||||
|
||||
ImmutableList.Builder<CompletableFuture<?>> futuresBuilder = new ImmutableList.Builder<>();
|
||||
|
||||
toSerialize.forEach(LamdbaExceptionUtils.rethrowBiConsumer((name, json) ->
|
||||
{
|
||||
entries.add(new ResourceLocation(modid, name));
|
||||
Path modifierPath = gen.getOutputFolder().resolve(modPath + name + ".json");
|
||||
DataProvider.saveStable(cache, json, modifierPath);
|
||||
Path modifierPath = modifierFolderPath.resolve(name + ".json");
|
||||
futuresBuilder.add(DataProvider.saveStable(cache, json, modifierPath));
|
||||
}));
|
||||
|
||||
JsonObject forgeJson = new JsonObject();
|
||||
forgeJson.addProperty("replace", this.replace);
|
||||
forgeJson.add("entries", GSON.toJsonTree(entries.stream().map(ResourceLocation::toString).collect(Collectors.toList())));
|
||||
|
||||
DataProvider.saveStable(cache, forgeJson, forgePath);
|
||||
futuresBuilder.add(DataProvider.saveStable(cache, forgeJson, forgePath));
|
||||
|
||||
return CompletableFuture.allOf(futuresBuilder.build().toArray(CompletableFuture[]::new));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,25 +5,26 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import com.mojang.logging.LogUtils;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.DynamicOps;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BiConsumer;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.RegistryDataLoader;
|
||||
import net.minecraft.resources.RegistryOps;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
@@ -31,6 +32,8 @@ import net.minecraft.server.packs.PackType;
|
||||
import net.minecraftforge.common.crafting.CraftingHelper;
|
||||
import net.minecraftforge.common.crafting.conditions.ICondition;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper.ResourceType;
|
||||
import net.minecraftforge.data.event.GatherDataEvent;
|
||||
import net.minecraftforge.registries.DataPackRegistriesHooks;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
/**
|
||||
@@ -57,7 +60,7 @@ public class JsonCodecProvider<T> implements DataProvider
|
||||
|
||||
/**
|
||||
* @param dataGenerator DataGenerator provided by {@link GatherDataEvent}.
|
||||
* @param dynamicOps DynamicOps to encode values to jsons with using the provided Codec, e.g. {@link JsonOps.INSTANCE}.
|
||||
* @param dynamicOps DynamicOps to encode values to jsons with using the provided Codec, e.g. {@link JsonOps#INSTANCE}.
|
||||
* @param packType PackType specifying whether to generate entries in assets or data.
|
||||
* @param directory String representing the directory to generate jsons in, e.g. "dimension" or "cheesemod/cheese".
|
||||
* @param codec Codec to encode values to jsons with using the provided DynamicOps.
|
||||
@@ -95,6 +98,7 @@ public class JsonCodecProvider<T> implements DataProvider
|
||||
* @param registryKey ResourceKey identifying the registry and its directory.
|
||||
* @param entries Map of entries to encode and their ResourceLocations. Paths for values are derived from the ResourceLocation's entryid:entrypath.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> JsonCodecProvider<T> forDatapackRegistry(DataGenerator dataGenerator, ExistingFileHelper existingFileHelper, String modid,
|
||||
RegistryOps<JsonElement> registryOps, ResourceKey<Registry<T>> registryKey, Map<ResourceLocation, T> entries)
|
||||
{
|
||||
@@ -104,21 +108,25 @@ public class JsonCodecProvider<T> implements DataProvider
|
||||
final String registryFolder = registryId.getNamespace().equals("minecraft")
|
||||
? registryId.getPath()
|
||||
: registryId.getNamespace() + "/" + registryId.getPath();
|
||||
final Codec<T> codec = (Codec<T>) RegistryAccess.REGISTRIES.get(registryKey).codec();
|
||||
RegistryDataLoader.RegistryData<?> registryData = DataPackRegistriesHooks.getDataPackRegistries().stream().filter(data -> data.key() == registryKey).findAny().orElseThrow();
|
||||
final Codec<T> codec = (Codec<T>) registryData.elementCodec();
|
||||
return new JsonCodecProvider<>(dataGenerator, existingFileHelper, modid, registryOps, PackType.SERVER_DATA, registryFolder, codec, entries);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run(final CachedOutput cache) throws IOException
|
||||
public CompletableFuture<?> run(final CachedOutput cache)
|
||||
{
|
||||
final Path outputFolder = this.dataGenerator.getOutputFolder();
|
||||
final String dataFolder = this.packType.getDirectory();
|
||||
final Path outputFolder = this.dataGenerator.getPackOutput().getOutputFolder(this.packType == PackType.CLIENT_RESOURCES
|
||||
? PackOutput.Target.RESOURCE_PACK
|
||||
: PackOutput.Target.DATA_PACK);
|
||||
ImmutableList.Builder<CompletableFuture<?>> futuresBuilder = new ImmutableList.Builder<>();
|
||||
|
||||
gather(LamdbaExceptionUtils.rethrowBiConsumer((id, value) -> {
|
||||
final Path path = outputFolder.resolve(String.join("/", dataFolder, id.getNamespace(), this.directory, id.getPath() + ".json"));
|
||||
final Path path = outputFolder.resolve(id.getNamespace()).resolve(this.directory).resolve(id.getPath() + ".json");
|
||||
JsonElement encoded = this.codec.encodeStart(this.dynamicOps, value)
|
||||
.getOrThrow(false, msg -> LOGGER.error("Failed to encode {}: {}", path, msg));
|
||||
ICondition[] conditions = this.conditions.get(id);
|
||||
if (conditions != null && conditions.length > 0)
|
||||
if (conditions != null && conditions.length > 0)
|
||||
{
|
||||
if(encoded instanceof JsonObject obj)
|
||||
{
|
||||
@@ -129,8 +137,10 @@ public class JsonCodecProvider<T> implements DataProvider
|
||||
LOGGER.error("Attempted to apply conditions to a type that is not a JsonObject! - Path: {}", path);
|
||||
}
|
||||
}
|
||||
DataProvider.saveStable(cache, encoded, path);
|
||||
futuresBuilder.add(DataProvider.saveStable(cache, encoded, path));
|
||||
}));
|
||||
|
||||
return CompletableFuture.allOf(futuresBuilder.build().toArray(CompletableFuture[]::new));
|
||||
}
|
||||
|
||||
protected void gather(BiConsumer<ResourceLocation, T> consumer)
|
||||
|
||||
@@ -5,36 +5,24 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.google.common.hash.Hashing;
|
||||
import com.google.gson.JsonObject;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import org.apache.commons.lang3.text.translate.JavaUnicodeEscaper;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.HashCache;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.entity.EntityType;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.effect.MobEffect;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public abstract class LanguageProvider implements DataProvider {
|
||||
private static final Gson GSON = (new GsonBuilder()).setPrettyPrinting().disableHtmlEscaping().setLenient().create();
|
||||
private final Map<String, String> data = new TreeMap<>();
|
||||
private final DataGenerator gen;
|
||||
private final String modid;
|
||||
@@ -49,10 +37,13 @@ public abstract class LanguageProvider implements DataProvider {
|
||||
protected abstract void addTranslations();
|
||||
|
||||
@Override
|
||||
public void run(CachedOutput cache) throws IOException {
|
||||
public CompletableFuture<?> run(CachedOutput cache) {
|
||||
addTranslations();
|
||||
|
||||
if (!data.isEmpty())
|
||||
save(cache, data, this.gen.getOutputFolder().resolve("assets/" + modid + "/lang/" + locale + ".json"));
|
||||
return save(cache, this.gen.getPackOutput().getOutputFolder(PackOutput.Target.RESOURCE_PACK).resolve(this.modid).resolve("lang").resolve(this.locale + ".json"));
|
||||
|
||||
return CompletableFuture.allOf();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -60,14 +51,12 @@ public abstract class LanguageProvider implements DataProvider {
|
||||
return "Languages: " + locale;
|
||||
}
|
||||
|
||||
private void save(CachedOutput cache, Object object, Path target) throws IOException {
|
||||
private CompletableFuture<?> save(CachedOutput cache, Path target) {
|
||||
// TODO: DataProvider.saveStable handles the caching and hashing already, but creating the JSON Object this way seems unreliable. -C
|
||||
JsonObject json = new JsonObject();
|
||||
for (Map.Entry<String, String> pair : data.entrySet()) {
|
||||
json.addProperty(pair.getKey(), pair.getValue());
|
||||
}
|
||||
this.data.forEach(json::addProperty);
|
||||
|
||||
DataProvider.saveStable(cache, json, target);
|
||||
return DataProvider.saveStable(cache, json, target);
|
||||
}
|
||||
|
||||
public void addBlock(Supplier<? extends Block> key, String name) {
|
||||
|
||||
@@ -5,13 +5,17 @@
|
||||
|
||||
package net.minecraftforge.common.data;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonObject;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Supplier;
|
||||
import net.minecraft.data.CachedOutput;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraft.data.HashCache;
|
||||
import net.minecraft.data.DataProvider;
|
||||
import net.minecraft.data.PackOutput;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
@@ -19,14 +23,6 @@ import net.minecraftforge.registries.ForgeRegistries;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Data provider for the {@code sounds.json} file, which identifies sound definitions
|
||||
* for the various sound events in Minecraft.
|
||||
@@ -34,7 +30,6 @@ import java.util.stream.Collectors;
|
||||
public abstract class SoundDefinitionsProvider implements DataProvider
|
||||
{
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().disableHtmlEscaping().create();
|
||||
private final DataGenerator generator;
|
||||
private final String modId;
|
||||
private final ExistingFileHelper helper;
|
||||
@@ -61,15 +56,17 @@ public abstract class SoundDefinitionsProvider implements DataProvider
|
||||
public abstract void registerSounds();
|
||||
|
||||
@Override
|
||||
public void run(CachedOutput cache) throws IOException
|
||||
public CompletableFuture<?> run(CachedOutput cache)
|
||||
{
|
||||
this.sounds.clear();
|
||||
this.registerSounds();
|
||||
this.validate();
|
||||
if (!this.sounds.isEmpty())
|
||||
{
|
||||
this.save(cache, this.generator.getOutputFolder().resolve("assets/" + this.modId + "/sounds.json"));
|
||||
return this.save(cache, this.generator.getPackOutput().getOutputFolder(PackOutput.Target.RESOURCE_PACK).resolve(this.modId).resolve("sounds.json"));
|
||||
}
|
||||
|
||||
return CompletableFuture.allOf();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -208,7 +205,7 @@ public abstract class SoundDefinitionsProvider implements DataProvider
|
||||
.filter(it -> !this.validate(it.getKey(), it.getValue()))
|
||||
.map(Map.Entry::getKey)
|
||||
.map(it -> this.modId + ":" + it)
|
||||
.collect(Collectors.toList());
|
||||
.toList();
|
||||
if (!notValid.isEmpty())
|
||||
{
|
||||
throw new IllegalStateException("Found invalid sound events: " + notValid);
|
||||
@@ -228,7 +225,7 @@ public abstract class SoundDefinitionsProvider implements DataProvider
|
||||
case EVENT: return this.validateEvent(name, sound.name());
|
||||
}
|
||||
// Differently from all the other errors, this is not a 'missing sound' but rather something completely different
|
||||
// that has broken the invariants of this sound definitions provider. In fact, a sound may only be either of
|
||||
// that has broken the invariants of this sound definition's provider. In fact, a sound may only be either of
|
||||
// SOUND or EVENT type. Any other values is somebody messing with the internals, reflectively adding something
|
||||
// to an enum or passing `null` to a parameter annotated with `@NotNull`.
|
||||
throw new IllegalArgumentException("The given sound '" + sound.name() + "' does not have a valid type: expected either SOUND or EVENT, but found " + sound.type());
|
||||
@@ -255,9 +252,9 @@ public abstract class SoundDefinitionsProvider implements DataProvider
|
||||
return valid;
|
||||
}
|
||||
|
||||
private void save(final CachedOutput cache, final Path targetFile) throws IOException
|
||||
private CompletableFuture<?> save(final CachedOutput cache, final Path targetFile)
|
||||
{
|
||||
DataProvider.saveStable(cache, this.mapToJson(this.sounds), targetFile);
|
||||
return DataProvider.saveStable(cache, this.mapToJson(this.sounds), targetFile);
|
||||
}
|
||||
|
||||
private JsonObject mapToJson(final Map<String, SoundDefinition> map)
|
||||
|
||||
@@ -205,7 +205,7 @@ public interface IForgeBlock
|
||||
{
|
||||
if (isBed(state, levelReader, pos, entity) && levelReader instanceof Level level && BedBlock.canSetSpawn(level))
|
||||
{
|
||||
return BedBlock.findStandUpPosition(type, levelReader, pos, orientation);
|
||||
return BedBlock.findStandUpPosition(type, levelReader, pos, state.getValue(BedBlock.FACING), orientation);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentCategory;
|
||||
import java.util.Set;
|
||||
|
||||
public interface IForgeEnchantment
|
||||
{
|
||||
@@ -31,25 +33,15 @@ public interface IForgeEnchantment
|
||||
return self().getDamageBonus(level, mobType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines what creative tabs this enchantment's variant of an enchanted book or similar item should appear in.
|
||||
* @param book The item being added to the creative tab
|
||||
* @param tab The creative tab that items are being added to
|
||||
* @return whether the given Item's variant for this enchantment should appear in the respective creative tab
|
||||
*/
|
||||
default boolean allowedInCreativeTab(Item book, CreativeModeTab tab)
|
||||
{
|
||||
if (!self().isAllowedOnBooks())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (tab == CreativeModeTab.TAB_SEARCH)
|
||||
{
|
||||
return self().category != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tab.hasEnchantmentCategory(self().category);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Determines whether item variants of this enchantment can be added to a given creative tab with the allowed categories.
|
||||
*
|
||||
* @param book the item being added to the creative tab
|
||||
* @param allowedCategories the enchantment categories allowed in the creative tab
|
||||
* @return whether item variants of this enchantment can be added to a given creative tab with the allowed categories
|
||||
*/
|
||||
default boolean allowedInCreativeTab(Item book, Set<EnchantmentCategory> allowedCategories)
|
||||
{
|
||||
return self().isAllowedOnBooks() && allowedCategories.contains(self().category);
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.vehicle.Boat;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
@@ -72,13 +73,13 @@ public interface IForgeFluid
|
||||
* Returns whether the fluid can create a source.
|
||||
*
|
||||
* @param state the state of the fluid
|
||||
* @param reader the reader that can get the fluid
|
||||
* @param level the level that can get the fluid
|
||||
* @param pos the location of the fluid
|
||||
* @return {@code true} if the fluid can create a source, {@code false} otherwise
|
||||
*/
|
||||
default boolean canConvertToSource(FluidState state, LevelReader reader, BlockPos pos)
|
||||
default boolean canConvertToSource(FluidState state, Level level, BlockPos pos)
|
||||
{
|
||||
return getFluidType().canConvertToSource(state, reader, pos);
|
||||
return getFluidType().canConvertToSource(state, level, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,6 +11,7 @@ import net.minecraft.world.entity.Mob;
|
||||
import net.minecraft.world.entity.vehicle.Boat;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.level.Explosion;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.LevelReader;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
@@ -67,13 +68,13 @@ public interface IForgeFluidState
|
||||
/**
|
||||
* Returns whether the fluid can create a source.
|
||||
*
|
||||
* @param reader the reader that can get the fluid
|
||||
* @param level the level that can get the fluid
|
||||
* @param pos the location of the fluid
|
||||
* @return {@code true} if the fluid can create a source, {@code false} otherwise
|
||||
*/
|
||||
default boolean canConvertToSource(LevelReader reader, BlockPos pos)
|
||||
default boolean canConvertToSource(Level level, BlockPos pos)
|
||||
{
|
||||
return self().getType().canConvertToSource(self(), reader, pos);
|
||||
return self().getType().canConvertToSource(self(), level, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.data.tags.IntrinsicHolderTagsProvider;
|
||||
import net.minecraft.data.tags.TagsProvider;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
|
||||
public interface IForgeIntrinsicHolderTagAppender<T> extends IForgeTagAppender<T>
|
||||
{
|
||||
private IntrinsicHolderTagsProvider.IntrinsicTagAppender<T> self() {
|
||||
return (IntrinsicHolderTagsProvider.IntrinsicTagAppender<T>) this;
|
||||
}
|
||||
|
||||
ResourceKey<T> getKey(T value);
|
||||
|
||||
/**
|
||||
* Adds a registry entry to the tag json's remove list. Callable during datageneration.
|
||||
*
|
||||
* @param entry The entry to remove
|
||||
* @return The builder for chaining
|
||||
*/
|
||||
default TagsProvider.TagAppender<T> remove(final T entry)
|
||||
{
|
||||
return remove(this.getKey(entry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple registry entries to the tag json's remove list. Callable during datageneration.
|
||||
*
|
||||
* @param entries The entries to remove
|
||||
* @return The builder for chaining
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default TagsProvider.TagAppender<T> remove(final T first, final T...entries)
|
||||
{
|
||||
this.remove(first);
|
||||
for (T entry : entries)
|
||||
{
|
||||
this.remove(entry);
|
||||
}
|
||||
return self();
|
||||
}
|
||||
}
|
||||
@@ -303,18 +303,6 @@ public interface IForgeItem
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of tabs that items belonging to this class can display on,
|
||||
* combined properly with getSubItems allows for a single item to span many
|
||||
* sub-items across many tabs.
|
||||
*
|
||||
* @return A list of all tabs that this item could possibly be one.
|
||||
*/
|
||||
default java.util.Collection<CreativeModeTab> getCreativeTabs()
|
||||
{
|
||||
return java.util.Collections.singletonList(self().getItemCategory());
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Should this item, when held, allow sneak-clicks to pass through to the
|
||||
@@ -616,7 +604,7 @@ public interface IForgeItem
|
||||
*/
|
||||
default boolean canContinueUsing(ItemStack oldStack, ItemStack newStack)
|
||||
{
|
||||
return ItemStack.isSameIgnoreDurability(oldStack, newStack);
|
||||
return ItemStack.isSame(oldStack, newStack);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.registries.Registries;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.monster.EnderMan;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
@@ -85,7 +86,7 @@ public interface IForgeItemStack extends ICapabilitySerializable<CompoundTag>
|
||||
Player entityplayer = context.getPlayer();
|
||||
BlockPos blockpos = context.getClickedPos();
|
||||
BlockInWorld blockworldstate = new BlockInWorld(context.getLevel(), blockpos, false);
|
||||
Registry<Block> registry = entityplayer.level.registryAccess().registryOrThrow(Registry.BLOCK_REGISTRY);
|
||||
Registry<Block> registry = entityplayer.level.registryAccess().registryOrThrow(Registries.BLOCK);
|
||||
if (entityplayer != null && !entityplayer.getAbilities().mayBuild && !self().hasAdventureModePlaceTagForBlock(registry, blockworldstate)) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
|
||||
@@ -9,6 +9,9 @@ import net.minecraft.server.packs.PackType;
|
||||
|
||||
public interface IForgePackResources
|
||||
{
|
||||
/**
|
||||
* {@return {@code true} if the pack should be hidden from any user interfaces}
|
||||
*/
|
||||
default boolean isHidden()
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.alchemy.Potion;
|
||||
import net.minecraft.world.item.alchemy.PotionUtils;
|
||||
@@ -18,18 +16,6 @@ public interface IForgePotion
|
||||
return (Potion) this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines what creative tabs this potion's variant of a potion-related item (e.g. bottles, tipped arrows) should appear in.
|
||||
* @param item The item being added to a creative tab
|
||||
* @param tab The creative tab that items are being added to
|
||||
* @param isDefaultTab whether the tab is the default tab for this item (e.g. Brewing for bottles, Combat for tipped arrows)
|
||||
* @return whether the given Item's variant for this enchantment should appear in the respective creative tab
|
||||
*/
|
||||
default boolean allowedInCreativeTab(Item item, CreativeModeTab tab, boolean isDefaultTab)
|
||||
{
|
||||
return isDefaultTab;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the potion bottle item should be enchanted.
|
||||
* Not called for tipped arrows or if the item is already enchanted.
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.common.extensions;
|
||||
|
||||
import net.minecraft.data.tags.TagsProvider;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.tags.TagKey;
|
||||
|
||||
@@ -33,32 +34,6 @@ public interface IForgeTagAppender<T>
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a registry entry to the tag json's remove list. Callable during datageneration.
|
||||
* @param entry The entry to remove
|
||||
* @return The builder for chaining
|
||||
*/
|
||||
default TagsProvider.TagAppender<T> remove(final T entry)
|
||||
{
|
||||
return remove(this.self().registry.getKey(entry));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple registry entries to the tag json's remove list. Callable during datageneration.
|
||||
* @param entries The entries to remove
|
||||
* @return The builder for chaining
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
default TagsProvider.TagAppender<T> remove(final T first, final T...entries)
|
||||
{
|
||||
this.remove(first);
|
||||
for (T entry : entries)
|
||||
{
|
||||
this.remove(entry);
|
||||
}
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a single element's ID to the tag json's remove list. Callable during datageneration.
|
||||
* @param location The ID of the element to remove
|
||||
@@ -86,6 +61,34 @@ public interface IForgeTagAppender<T>
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a resource key to the tag json's remove list. Callable during datageneration.
|
||||
*
|
||||
* @param resourceKey The resource key of the element to remove
|
||||
* @return The appender for chaining
|
||||
*/
|
||||
default TagsProvider.TagAppender<T> remove(final ResourceKey<T> resourceKey)
|
||||
{
|
||||
this.remove(resourceKey.location());
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds multiple resource keys to the tag json's remove list. Callable during datageneration.
|
||||
*
|
||||
* @param resourceKeys The resource keys of the elements to remove
|
||||
* @return The appender for chaining
|
||||
*/
|
||||
default TagsProvider.TagAppender<T> remove(final ResourceKey<T> firstResourceKey, final ResourceKey<T>... resourceKeys)
|
||||
{
|
||||
this.remove(firstResourceKey.location());
|
||||
for (ResourceKey<T> resourceKey : resourceKeys)
|
||||
{
|
||||
this.remove(resourceKey.location());
|
||||
}
|
||||
return self();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a tag to the tag json's remove list. Callable during datageneration.
|
||||
* @param tag The ID of the tag to remove
|
||||
|
||||
@@ -20,6 +20,12 @@ import java.util.function.Supplier;
|
||||
*/
|
||||
public class ConcatenatedListView<T> implements List<T>
|
||||
{
|
||||
@SafeVarargs
|
||||
public static <T> ConcatenatedListView<T> of(List<T>... lists)
|
||||
{
|
||||
return new ConcatenatedListView<>(List.of(lists));
|
||||
}
|
||||
|
||||
public static <T> List<T> of(List<? extends List<? extends T>> members)
|
||||
{
|
||||
return switch (members.size()) {
|
||||
|
||||
@@ -8,17 +8,21 @@ package net.minecraftforge.common.util;
|
||||
import com.mojang.authlib.GameProfile;
|
||||
import java.util.Set;
|
||||
import javax.annotation.ParametersAreNonnullByDefault;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.Connection;
|
||||
import net.minecraft.network.PacketSendListener;
|
||||
import net.minecraft.network.chat.ChatType;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.PlayerChatMessage;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
import net.minecraft.network.protocol.PacketFlow;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundAcceptTeleportationPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundBlockEntityTagQuery;
|
||||
import net.minecraft.network.protocol.game.ServerboundChangeDifficultyPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatAckPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatCommandPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatSessionUpdatePacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundClientCommandPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundClientInformationPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundCommandSuggestionPacket;
|
||||
@@ -66,7 +70,6 @@ import net.minecraft.server.network.ServerGamePacketListenerImpl;
|
||||
import net.minecraft.stats.Stat;
|
||||
import net.minecraft.world.damagesource.DamageSource;
|
||||
import net.minecraft.world.entity.player.Player;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraftforge.server.ServerLifecycleHooks;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -77,7 +80,7 @@ public class FakePlayer extends ServerPlayer
|
||||
{
|
||||
public FakePlayer(ServerLevel level, GameProfile name)
|
||||
{
|
||||
super(level.getServer(), level, name, null);
|
||||
super(level.getServer(), level, name);
|
||||
this.connection = new FakePlayerNetHandler(level.getServer(), this);
|
||||
}
|
||||
|
||||
@@ -150,5 +153,14 @@ public class FakePlayer extends ServerPlayer
|
||||
@Override public void handleCustomPayload(ServerboundCustomPayloadPacket packet) { }
|
||||
@Override public void handleChangeDifficulty(ServerboundChangeDifficultyPacket packet) { }
|
||||
@Override public void handleLockDifficulty(ServerboundLockDifficultyPacket packet) { }
|
||||
@Override public void dismount(double x, double y, double z, float yaw, float pitch) { }
|
||||
@Override public void teleport(double x, double y, double z, float yaw, float pitch, Set<ClientboundPlayerPositionPacket.RelativeArgument> relativeSet, boolean dismountVehicle) { }
|
||||
@Override public void ackBlockChangesUpTo(int sequence) { }
|
||||
@Override public void handleChatCommand(ServerboundChatCommandPacket packet) { }
|
||||
@Override public void handleChatAck(ServerboundChatAckPacket packet) { }
|
||||
@Override public void addPendingMessage(PlayerChatMessage message) { }
|
||||
@Override public void sendPlayerChatMessage(PlayerChatMessage message, ChatType.Bound boundChatType) { }
|
||||
@Override public void sendDisguisedChatMessage(Component content, ChatType.Bound boundChatType) { }
|
||||
@Override public void handleChatSessionUpdate(ServerboundChatSessionUpdatePacket packet) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.common.util;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenCustomHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenCustomHashMap;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.ItemStackLinkedSet;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class ItemStackMap {
|
||||
|
||||
public static <V> Map<ItemStack, V> createTypeAndTagLinkedMap() {
|
||||
return new Object2ObjectLinkedOpenCustomHashMap<>(ItemStackLinkedSet.TYPE_AND_TAG);
|
||||
}
|
||||
|
||||
public static <V> Map<ItemStack, V> createTypeAndTagMap() {
|
||||
return new Object2ObjectOpenCustomHashMap<>(ItemStackLinkedSet.TYPE_AND_TAG);
|
||||
}
|
||||
}
|
||||
@@ -5,47 +5,58 @@
|
||||
|
||||
package net.minecraftforge.common.util;
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.mojang.math.Axis;
|
||||
import com.mojang.math.Transformation;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.gson.*;
|
||||
import net.minecraft.util.Mth;
|
||||
|
||||
import com.mojang.math.Matrix4f;
|
||||
import com.mojang.math.Quaternion;
|
||||
import com.mojang.math.Transformation;
|
||||
import com.mojang.math.Vector3f;
|
||||
import com.mojang.math.Vector4f;
|
||||
import net.minecraftforge.client.model.generators.BlockModelBuilder.RootTransformBuilder.TransformOrigin;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Quaternionf;
|
||||
import org.joml.Quaternionfc;
|
||||
import org.joml.Vector3f;
|
||||
import org.joml.Vector4f;
|
||||
|
||||
public final class TransformationHelper
|
||||
{
|
||||
public static Quaternion quatFromXYZ(Vector3f xyz, boolean degrees)
|
||||
public static Quaternionf quatFromXYZ(Vector3f xyz, boolean degrees)
|
||||
{
|
||||
return new Quaternion(xyz.x(), xyz.y(), xyz.z(), degrees);
|
||||
return quatFromXYZ(xyz.x, xyz.y, xyz.z, degrees);
|
||||
}
|
||||
|
||||
public static Quaternion quatFromXYZ(float[] xyz, boolean degrees)
|
||||
public static Quaternionf quatFromXYZ(float[] xyz, boolean degrees)
|
||||
{
|
||||
return new Quaternion(xyz[0], xyz[1], xyz[2], degrees);
|
||||
return quatFromXYZ(xyz[0], xyz[1], xyz[2], degrees);
|
||||
}
|
||||
|
||||
public static Quaternion makeQuaternion(float[] values)
|
||||
public static Quaternionf quatFromXYZ(float x, float y, float z, boolean degrees)
|
||||
{
|
||||
return new Quaternion(values[0], values[1], values[2], values[3]);
|
||||
float conversionFactor = degrees ? (float) Math.PI / 180 : 1;
|
||||
return new Quaternionf().rotationXYZ(x * conversionFactor, y * conversionFactor, z * conversionFactor);
|
||||
}
|
||||
|
||||
public static Quaternionf makeQuaternion(float[] values)
|
||||
{
|
||||
return new Quaternionf(values[0], values[1], values[2], values[3]);
|
||||
}
|
||||
|
||||
public static Vector3f lerp(Vector3f from, Vector3f to, float progress)
|
||||
{
|
||||
Vector3f res = from.copy();
|
||||
Vector3f res = new Vector3f(from);
|
||||
res.lerp(to, progress);
|
||||
return res;
|
||||
}
|
||||
|
||||
private static final double THRESHOLD = 0.9995;
|
||||
public static Quaternion slerp(Quaternion v0, Quaternion v1, float t)
|
||||
public static Quaternionf slerp(Quaternionfc v0, Quaternionfc v1, float t)
|
||||
{
|
||||
// From https://en.wikipedia.org/w/index.php?title=Slerp&oldid=928959428
|
||||
// License: CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0/
|
||||
@@ -55,20 +66,20 @@ public final class TransformationHelper
|
||||
// the shorter path. Note that v1 and -v1 are equivalent when
|
||||
// the negation is applied to all four components. Fix by
|
||||
// reversing one quaternion.
|
||||
float dot = v0.i() * v1.i() + v0.j() * v1.j() + v0.k() * v1.k() + v0.r() * v1.r();
|
||||
float dot = v0.x() * v1.x() + v0.y() * v1.y() + v0.z() * v1.z() + v0.w() * v1.w();
|
||||
if (dot < 0.0f) {
|
||||
v1 = new Quaternion(-v1.i(), -v1.j(), -v1.k(), -v1.r());
|
||||
v1 = new Quaternionf(-v1.x(), -v1.y(), -v1.z(), -v1.w());
|
||||
dot = -dot;
|
||||
}
|
||||
|
||||
// If the inputs are too close for comfort, linearly interpolate
|
||||
// and normalize the result.
|
||||
if (dot > THRESHOLD) {
|
||||
float x = Mth.lerp(t, v0.i(), v1.i());
|
||||
float y = Mth.lerp(t, v0.j(), v1.j());
|
||||
float z = Mth.lerp(t, v0.k(), v1.k());
|
||||
float w = Mth.lerp(t, v0.r(), v1.r());
|
||||
return new Quaternion(x,y,z,w);
|
||||
float x = Mth.lerp(t, v0.x(), v1.x());
|
||||
float y = Mth.lerp(t, v0.y(), v1.y());
|
||||
float z = Mth.lerp(t, v0.z(), v1.z());
|
||||
float w = Mth.lerp(t, v0.w(), v1.w());
|
||||
return new Quaternionf(x,y,z,w);
|
||||
}
|
||||
|
||||
// Since dot is in range [0, DOT_THRESHOLD], acos is safe
|
||||
@@ -81,11 +92,11 @@ public final class TransformationHelper
|
||||
float s1 = sin0t / sin01;
|
||||
float s0 = sin1t / sin01;
|
||||
|
||||
return new Quaternion(
|
||||
s0 * v0.i() + s1 * v1.i(),
|
||||
s0 * v0.j() + s1 * v1.j(),
|
||||
s0 * v0.k() + s1 * v1.k(),
|
||||
s0 * v0.r() + s1 * v1.r()
|
||||
return new Quaternionf(
|
||||
s0 * v0.x() + s1 * v1.x(),
|
||||
s0 * v0.y() + s1 * v1.y(),
|
||||
s0 * v0.z() + s1 * v1.z(),
|
||||
s0 * v0.w() + s1 * v1.w()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -143,9 +154,9 @@ public final class TransformationHelper
|
||||
return ret;
|
||||
}
|
||||
Vector3f translation = null;
|
||||
Quaternion leftRot = null;
|
||||
Quaternionf leftRot = null;
|
||||
Vector3f scale = null;
|
||||
Quaternion rightRot = null;
|
||||
Quaternionf rightRot = null;
|
||||
// TODO: Default origin is opposing corner, due to a mistake.
|
||||
// This should probably be replaced with center in future versions.
|
||||
Vector3f origin = TransformOrigin.OPPOSING_CORNER.getVector(); // TODO: Changing this to ORIGIN_CENTER breaks models, function content needs changing too -C
|
||||
@@ -206,7 +217,7 @@ public final class TransformationHelper
|
||||
// Use a different origin if needed.
|
||||
if (!TransformOrigin.CENTER.getVector().equals(origin))
|
||||
{
|
||||
Vector3f originFromCenter = origin.copy();
|
||||
Vector3f originFromCenter = new Vector3f(origin);
|
||||
originFromCenter.sub(TransformOrigin.CENTER.getVector());
|
||||
matrix = matrix.applyOrigin(originFromCenter);
|
||||
}
|
||||
@@ -244,25 +255,25 @@ public final class TransformationHelper
|
||||
if (!e.isJsonArray()) throw new JsonParseException("Matrix: expected an array, got: " + e);
|
||||
JsonArray m = e.getAsJsonArray();
|
||||
if (m.size() != 3) throw new JsonParseException("Matrix: expected an array of length 3, got: " + m.size());
|
||||
float[] values = new float[16];
|
||||
for (int i = 0; i < 3; i++)
|
||||
Matrix4f matrix = new Matrix4f().zero();
|
||||
for (int rowIdx = 0; rowIdx < 3; rowIdx++)
|
||||
{
|
||||
if (!m.get(i).isJsonArray()) throw new JsonParseException("Matrix row: expected an array, got: " + m.get(i));
|
||||
JsonArray r = m.get(i).getAsJsonArray();
|
||||
if (!m.get(rowIdx).isJsonArray()) throw new JsonParseException("Matrix row: expected an array, got: " + m.get(rowIdx));
|
||||
JsonArray r = m.get(rowIdx).getAsJsonArray();
|
||||
if (r.size() != 4) throw new JsonParseException("Matrix row: expected an array of length 4, got: " + r.size());
|
||||
for (int j = 0; j < 4; j++)
|
||||
for (int columnIdx = 0; columnIdx < 4; columnIdx++)
|
||||
{
|
||||
try
|
||||
{
|
||||
values[j*4+i] = r.get(j).getAsNumber().floatValue();
|
||||
matrix.set(columnIdx, rowIdx, r.get(columnIdx).getAsNumber().floatValue());
|
||||
}
|
||||
catch (ClassCastException ex)
|
||||
{
|
||||
throw new JsonParseException("Matrix element: expected number, got: " + r.get(j));
|
||||
throw new JsonParseException("Matrix element: expected number, got: " + r.get(columnIdx));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new Matrix4f(values);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
public static float[] parseFloatArray(JsonElement e, int length, String prefix)
|
||||
@@ -285,26 +296,26 @@ public final class TransformationHelper
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Quaternion parseAxisRotation(JsonElement e)
|
||||
public static Quaternionf parseAxisRotation(JsonElement e)
|
||||
{
|
||||
if (!e.isJsonObject()) throw new JsonParseException("Axis rotation: object expected, got: " + e);
|
||||
JsonObject obj = e.getAsJsonObject();
|
||||
if (obj.entrySet().size() != 1) throw new JsonParseException("Axis rotation: expected single axis object, got: " + e);
|
||||
Map.Entry<String, JsonElement> entry = obj.entrySet().iterator().next();
|
||||
Quaternion ret;
|
||||
Quaternionf ret;
|
||||
try
|
||||
{
|
||||
if (entry.getKey().equals("x"))
|
||||
{
|
||||
ret = Vector3f.XP.rotationDegrees(entry.getValue().getAsNumber().floatValue());
|
||||
ret = Axis.XP.rotationDegrees(entry.getValue().getAsNumber().floatValue());
|
||||
}
|
||||
else if (entry.getKey().equals("y"))
|
||||
{
|
||||
ret = Vector3f.YP.rotationDegrees(entry.getValue().getAsNumber().floatValue());
|
||||
ret = Axis.YP.rotationDegrees(entry.getValue().getAsNumber().floatValue());
|
||||
}
|
||||
else if (entry.getKey().equals("z"))
|
||||
{
|
||||
ret = Vector3f.ZP.rotationDegrees(entry.getValue().getAsNumber().floatValue());
|
||||
ret = Axis.ZP.rotationDegrees(entry.getValue().getAsNumber().floatValue());
|
||||
}
|
||||
else throw new JsonParseException("Axis rotation: expected single axis key, got: " + entry.getKey());
|
||||
}
|
||||
@@ -315,13 +326,13 @@ public final class TransformationHelper
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static Quaternion parseRotation(JsonElement e)
|
||||
public static Quaternionf parseRotation(JsonElement e)
|
||||
{
|
||||
if (e.isJsonArray())
|
||||
{
|
||||
if (e.getAsJsonArray().get(0).isJsonObject())
|
||||
{
|
||||
Quaternion ret = Quaternion.ONE.copy();
|
||||
Quaternionf ret = new Quaternionf();
|
||||
for (JsonElement a : e.getAsJsonArray())
|
||||
{
|
||||
ret.mul(parseAxisRotation(a));
|
||||
|
||||
@@ -5,18 +5,15 @@
|
||||
|
||||
package net.minecraftforge.common.world;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.core.HolderSet;
|
||||
import net.minecraft.world.level.biome.BiomeGenerationSettings;
|
||||
import net.minecraft.world.level.levelgen.GenerationStep;
|
||||
import net.minecraft.world.level.levelgen.carver.ConfiguredWorldCarver;
|
||||
import net.minecraft.world.level.levelgen.placement.PlacedFeature;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class BiomeGenerationSettingsBuilder extends BiomeGenerationSettings.Builder
|
||||
public class BiomeGenerationSettingsBuilder extends BiomeGenerationSettings.PlainBuilder
|
||||
{
|
||||
public BiomeGenerationSettingsBuilder(BiomeGenerationSettings orig)
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@ package net.minecraftforge.common.world;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.sounds.Music;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.world.level.biome.AmbientAdditionsSettings;
|
||||
@@ -33,12 +34,12 @@ public class BiomeSpecialEffectsBuilder extends BiomeSpecialEffects.Builder
|
||||
baseEffects.getBackgroundMusic().ifPresent(builder::backgroundMusic);
|
||||
return builder;
|
||||
}
|
||||
|
||||
|
||||
public static BiomeSpecialEffectsBuilder create(int fogColor, int waterColor, int waterFogColor, int skyColor)
|
||||
{
|
||||
return new BiomeSpecialEffectsBuilder(fogColor, waterColor, waterFogColor, skyColor);
|
||||
}
|
||||
|
||||
|
||||
protected BiomeSpecialEffectsBuilder(int fogColor, int waterColor, int waterFogColor, int skyColor)
|
||||
{
|
||||
super();
|
||||
@@ -47,62 +48,62 @@ public class BiomeSpecialEffectsBuilder extends BiomeSpecialEffects.Builder
|
||||
this.waterFogColor(waterFogColor);
|
||||
this.skyColor(skyColor);
|
||||
}
|
||||
|
||||
|
||||
public int getFogColor()
|
||||
{
|
||||
return this.fogColor.getAsInt();
|
||||
}
|
||||
|
||||
|
||||
public int waterColor()
|
||||
{
|
||||
return this.waterColor.getAsInt();
|
||||
}
|
||||
|
||||
|
||||
public int getWaterFogColor()
|
||||
{
|
||||
return this.waterFogColor.getAsInt();
|
||||
}
|
||||
|
||||
|
||||
public int getSkyColor()
|
||||
{
|
||||
return this.skyColor.getAsInt();
|
||||
}
|
||||
|
||||
|
||||
public BiomeSpecialEffects.GrassColorModifier getGrassColorModifier()
|
||||
{
|
||||
return this.grassColorModifier;
|
||||
}
|
||||
|
||||
|
||||
public Optional<Integer> getFoliageColorOverride()
|
||||
{
|
||||
return this.foliageColorOverride;
|
||||
}
|
||||
|
||||
|
||||
public Optional<Integer> getGrassColorOverride()
|
||||
{
|
||||
return this.grassColorOverride;
|
||||
}
|
||||
|
||||
|
||||
public Optional<AmbientParticleSettings> getAmbientParticle()
|
||||
{
|
||||
return this.ambientParticle;
|
||||
}
|
||||
|
||||
public Optional<SoundEvent> getAmbientLoopSound()
|
||||
|
||||
public Optional<Holder<SoundEvent>> getAmbientLoopSound()
|
||||
{
|
||||
return this.ambientLoopSoundEvent;
|
||||
}
|
||||
|
||||
|
||||
public Optional<AmbientMoodSettings> getAmbientMoodSound()
|
||||
{
|
||||
return this.ambientMoodSettings;
|
||||
}
|
||||
|
||||
|
||||
public Optional<AmbientAdditionsSettings> getAmbientAdditionsSound()
|
||||
{
|
||||
return this.ambientAdditionsSettings;
|
||||
}
|
||||
|
||||
|
||||
public Optional<Music> getBackgroundMusic()
|
||||
{
|
||||
return this.backgroundMusic;
|
||||
|
||||
@@ -26,7 +26,7 @@ import net.minecraftforge.registries.ForgeRegistries;
|
||||
public final class ForgeBiomeModifiers
|
||||
{
|
||||
private ForgeBiomeModifiers() {} // Utility class.
|
||||
|
||||
|
||||
/**
|
||||
* <p>Stock biome modifier that adds features to biomes. Has the following json format:</p>
|
||||
* <pre>
|
||||
@@ -38,7 +38,7 @@ public final class ForgeBiomeModifiers
|
||||
* }
|
||||
* </pre>
|
||||
* <p>Be wary of using this to add vanilla PlacedFeatures to biomes, as doing so may cause a feature cycle violation.</p>
|
||||
*
|
||||
*
|
||||
* @param biomes Biomes to add features to.
|
||||
* @param features PlacedFeatures to add to biomes.
|
||||
* @param step Decoration step to run features in.
|
||||
@@ -62,7 +62,6 @@ public final class ForgeBiomeModifiers
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Stock biome modifier that removes features from biomes. Has the following json format:</p>
|
||||
* <pre>
|
||||
@@ -73,7 +72,7 @@ public final class ForgeBiomeModifiers
|
||||
* "steps": "underground_ores" OR ["underground_ores", "vegetal_decoration"] // one or more decoration steps; optional field, defaults to all steps if not specified
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param biomes Biomes to remove features from.
|
||||
* @param features PlacedFeatures to remove from biomes.
|
||||
* @param steps Decoration steps to remove features from.
|
||||
@@ -89,7 +88,7 @@ public final class ForgeBiomeModifiers
|
||||
{
|
||||
return new RemoveFeaturesBiomeModifier(biomes, features, EnumSet.allOf(Decoration.class));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, Builder builder)
|
||||
{
|
||||
@@ -109,7 +108,7 @@ public final class ForgeBiomeModifiers
|
||||
return ForgeMod.REMOVE_FEATURES_BIOME_MODIFIER_TYPE.get();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* <p>Stock biome modifier that adds a mob spawn to a biome. Has the following json format:</p>
|
||||
* <pre>
|
||||
@@ -144,7 +143,7 @@ public final class ForgeBiomeModifiers
|
||||
* ]
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param biomes Biomes to add mob spawns to.
|
||||
* @param spawners List of SpawnerDatas specifying EntityType, weight, and pack size.
|
||||
*/
|
||||
@@ -160,7 +159,7 @@ public final class ForgeBiomeModifiers
|
||||
{
|
||||
return new AddSpawnsBiomeModifier(biomes, List.of(spawner));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void modify(Holder<Biome> biome, Phase phase, Builder builder)
|
||||
{
|
||||
@@ -191,7 +190,7 @@ public final class ForgeBiomeModifiers
|
||||
* "entity_types": #namespace:entitytype_tag // Accepts an entity type, [list of entity types], or #namespace:entitytype_tag
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
*
|
||||
* @param biomes Biomes to add mob spawns to.
|
||||
* @param entityTypes EntityTypes to remove from spawn lists.
|
||||
*/
|
||||
|
||||
@@ -7,6 +7,7 @@ package net.minecraftforge.data.event;
|
||||
|
||||
import cpw.mods.modlauncher.api.LamdbaExceptionUtils;
|
||||
import net.minecraft.DetectedVersion;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.DataGenerator;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
@@ -20,6 +21,7 @@ import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -44,6 +46,7 @@ public class GatherDataEvent extends Event implements IModBusEvent
|
||||
|
||||
public DataGenerator getGenerator() { return this.dataGenerator; }
|
||||
public ExistingFileHelper getExistingFileHelper() { return existingFileHelper; }
|
||||
public CompletableFuture<HolderLookup.Provider> getLookupProvider() { return this.config.lookupProvider; }
|
||||
public boolean includeServer() { return this.config.server; }
|
||||
public boolean includeClient() { return this.config.client; }
|
||||
public boolean includeDev() { return this.config.dev; }
|
||||
@@ -54,18 +57,21 @@ public class GatherDataEvent extends Event implements IModBusEvent
|
||||
private final Set<String> mods;
|
||||
private final Path path;
|
||||
private final Collection<Path> inputs;
|
||||
private final CompletableFuture<HolderLookup.Provider> lookupProvider;
|
||||
private final boolean server;
|
||||
private final boolean client;
|
||||
private final boolean dev;
|
||||
private final boolean reports;
|
||||
private final boolean validate;
|
||||
private final boolean flat;
|
||||
private List<DataGenerator> generators = new ArrayList<>();
|
||||
private final List<DataGenerator> generators = new ArrayList<>();
|
||||
|
||||
public DataGeneratorConfig(final Set<String> mods, final Path path, final Collection<Path> inputs, final boolean server, final boolean client, final boolean dev, final boolean reports, final boolean validate, final boolean flat) {
|
||||
public DataGeneratorConfig(final Set<String> mods, final Path path, final Collection<Path> inputs, final CompletableFuture<HolderLookup.Provider> lookupProvider,
|
||||
final boolean server, final boolean client, final boolean dev, final boolean reports, final boolean validate, final boolean flat) {
|
||||
this.mods = mods;
|
||||
this.path = path;
|
||||
this.inputs = inputs;
|
||||
this.lookupProvider = lookupProvider;
|
||||
this.server = server;
|
||||
this.client = client;
|
||||
this.dev = dev;
|
||||
@@ -75,6 +81,10 @@ public class GatherDataEvent extends Event implements IModBusEvent
|
||||
|
||||
}
|
||||
|
||||
public Collection<Path> getInputs() {
|
||||
return this.inputs;
|
||||
}
|
||||
|
||||
public Set<String> getMods() {
|
||||
return mods;
|
||||
}
|
||||
@@ -84,19 +94,19 @@ public class GatherDataEvent extends Event implements IModBusEvent
|
||||
}
|
||||
|
||||
public DataGenerator makeGenerator(final Function<Path,Path> pathEnhancer, final boolean shouldExecute) {
|
||||
final DataGenerator generator = new DataGenerator(pathEnhancer.apply(path), inputs, DetectedVersion.tryDetectVersion(), shouldExecute);
|
||||
final DataGenerator generator = new DataGenerator(pathEnhancer.apply(path), DetectedVersion.tryDetectVersion(), shouldExecute);
|
||||
if (shouldExecute)
|
||||
generators.add(generator);
|
||||
return generator;
|
||||
}
|
||||
|
||||
public void runAll() {
|
||||
Map<Path, List<DataGenerator>> paths = generators.stream().collect(Collectors.groupingBy(DataGenerator::getOutputFolder, LinkedHashMap::new, Collectors.toList()));
|
||||
Map<Path, List<DataGenerator>> paths = generators.stream().collect(Collectors.groupingBy(gen -> gen.getPackOutput().getOutputFolder(), LinkedHashMap::new, Collectors.toList()));
|
||||
|
||||
paths.values().forEach(LamdbaExceptionUtils.rethrowConsumer(lst -> {
|
||||
DataGenerator parent = lst.get(0);
|
||||
for (int x = 1; x < lst.size(); x++)
|
||||
lst.get(x).getProviders().forEach(i -> parent.addProvider(true, i));
|
||||
lst.get(x).getProvidersView().forEach((name, provider) -> parent.addProvider(true, provider));
|
||||
parent.run();
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
|
||||
package net.minecraftforge.data.loading;
|
||||
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.core.HolderLookup;
|
||||
import net.minecraft.data.registries.VanillaRegistries;
|
||||
import net.minecraft.server.Bootstrap;
|
||||
import net.minecraftforge.common.data.ExistingFileHelper;
|
||||
import net.minecraftforge.fml.ModLoader;
|
||||
@@ -17,6 +20,7 @@ import java.io.File;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
public class DatagenModLoader {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
@@ -28,19 +32,25 @@ public class DatagenModLoader {
|
||||
return runningDataGen;
|
||||
}
|
||||
|
||||
public static void begin(final Set<String> mods, final Path path, final Collection<Path> inputs, Collection<Path> existingPacks, Set<String> existingMods, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator, final boolean structureValidator, final boolean flat, final String assetIndex, final File assetsDir) {
|
||||
if (mods.contains("minecraft") && mods.size() == 1) return;
|
||||
public static void begin(final Set<String> mods, final Path path, final Collection<Path> inputs, Collection<Path> existingPacks,
|
||||
Set<String> existingMods, final boolean serverGenerators, final boolean clientGenerators, final boolean devToolGenerators, final boolean reportsGenerator,
|
||||
final boolean structureValidator, final boolean flat, final String assetIndex, final File assetsDir) {
|
||||
if (mods.contains("minecraft") && mods.size() == 1)
|
||||
return;
|
||||
LOGGER.info("Initializing Data Gatherer for mods {}", mods);
|
||||
runningDataGen = true;
|
||||
Bootstrap.bootStrap();
|
||||
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, serverGenerators, clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat);
|
||||
CompletableFuture<HolderLookup.Provider> lookupProvider = CompletableFuture.supplyAsync(VanillaRegistries::createLookup, Util.backgroundExecutor());
|
||||
dataGeneratorConfig = new GatherDataEvent.DataGeneratorConfig(mods, path, inputs, lookupProvider, serverGenerators,
|
||||
clientGenerators, devToolGenerators, reportsGenerator, structureValidator, flat);
|
||||
ModLoader.get().gatherAndInitializeMods(ModWorkManager.syncExecutor(), ModWorkManager.parallelExecutor(), ()->{});
|
||||
if (!mods.contains("forge")) {
|
||||
//If we aren't generating data for forge, automatically add forge as an existing so mods can access forge's data
|
||||
// If we aren't generating data for forge, automatically add forge as an existing so mods can access forge's data
|
||||
existingMods.add("forge");
|
||||
}
|
||||
existingFileHelper = new ExistingFileHelper(existingPacks, existingMods, structureValidator, assetIndex, assetsDir);
|
||||
ModLoader.get().runEventGenerator(mc->new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p->dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()), dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper));
|
||||
ModLoader.get().runEventGenerator(mc -> new GatherDataEvent(mc, dataGeneratorConfig.makeGenerator(p -> dataGeneratorConfig.isFlat() ? p : p.resolve(mc.getModId()),
|
||||
dataGeneratorConfig.getMods().contains(mc.getModId())), dataGeneratorConfig, existingFileHelper));
|
||||
dataGeneratorConfig.runAll();
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package net.minecraftforge.entity;
|
||||
|
||||
import net.minecraft.network.protocol.game.ClientGamePacketListener;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.network.protocol.Packet;
|
||||
|
||||
@@ -21,7 +22,7 @@ public abstract class PartEntity<T extends Entity> extends Entity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Packet<?> getAddEntityPacket() {
|
||||
public Packet<ClientGamePacketListener> getAddEntityPacket() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.event;
|
||||
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.repository.PackRepository;
|
||||
import net.minecraft.server.packs.repository.RepositorySource;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
@@ -13,7 +14,7 @@ import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Fired on PackRepository creation to allow mods to add new pack finders.
|
||||
* Fired on {@link PackRepository} creation to allow mods to add new pack finders.
|
||||
*/
|
||||
public class AddPackFindersEvent extends Event implements IModBusEvent
|
||||
{
|
||||
@@ -36,7 +37,7 @@ public class AddPackFindersEvent extends Event implements IModBusEvent
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link PackType} of the resource manager being constructed.
|
||||
* @return the {@link PackType} of the pack repository being constructed.
|
||||
*/
|
||||
public PackType getPackType()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.minecraftforge.event;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.flag.FeatureFlagSet;
|
||||
import net.minecraft.world.item.CreativeModeTab;
|
||||
import net.minecraft.world.item.CreativeModeTabs;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.ItemLike;
|
||||
import net.minecraftforge.common.CreativeModeTabRegistry;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import net.minecraftforge.fml.event.IModBusEvent;
|
||||
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class CreativeModeTabEvent extends Event implements IModBusEvent
|
||||
{
|
||||
private static final List<Object> DEFAULT_AFTER_ENTRIES = List.of(CreativeModeTabs.SPAWN_EGGS);
|
||||
|
||||
@ApiStatus.Internal
|
||||
public CreativeModeTabEvent() {}
|
||||
|
||||
/**
|
||||
* A registrar which is capable of registering new tabs.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Registrar {
|
||||
|
||||
/**
|
||||
* Register a new tab.
|
||||
*
|
||||
* @param configurator The tab configurator to register
|
||||
* @param name The name of the tab.
|
||||
* @param afters A list of tab names (String, ResourceLocations) or tabs that need to appear before this tab in the creative mode menu.
|
||||
* @param befores A list of tab names (String, ResourceLocations) or tabs that need to appear after this tab in the creative mode menu.
|
||||
* @return The configured tab.
|
||||
*/
|
||||
@NotNull
|
||||
CreativeModeTab registerCreativeModeTab(@NotNull final Consumer<CreativeModeTab.Builder> configurator, @NotNull final ResourceLocation name, @NotNull final List<Object> afters, @NotNull final List<Object> befores);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when creative mode tabs can be registered.
|
||||
* <p>
|
||||
* This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* on both {@linkplain LogicalSide logical sides}.
|
||||
*/
|
||||
public static final class Register extends CreativeModeTabEvent
|
||||
{
|
||||
private final Registrar registrar;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public Register(Registrar registrar) {
|
||||
this.registrar = registrar;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers and configures a creative mode tab with the given name and returns the built instance.
|
||||
*
|
||||
* @param name the name of the tab. Must be unique.
|
||||
* @param beforeEntries the list of {@linkplain ResourceLocation tab names} or {@linkplain CreativeModeTab tabs} that should appear before this tab in the creative mode inventory screen
|
||||
* @param afterEntries the list of {@linkplain ResourceLocation tab names} or {@linkplain CreativeModeTab tabs} that should appear after this tab in the creative mode inventory screen
|
||||
* @param configurator the configurator which configures the builder
|
||||
* @return the configured creative mode tab
|
||||
* @see #registerCreativeModeTab(ResourceLocation, Consumer)
|
||||
*/
|
||||
public CreativeModeTab registerCreativeModeTab(ResourceLocation name, List<Object> beforeEntries, List<Object> afterEntries, Consumer<CreativeModeTab.Builder> configurator)
|
||||
{
|
||||
return registrar.registerCreativeModeTab(configurator, name, afterEntries, beforeEntries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers and configures a creative mode tab with the given name and returns the built instance.
|
||||
* The tab is sorted by default to be after {@link CreativeModeTabs#SPAWN_EGGS}.
|
||||
*
|
||||
* @param name the name of the tab. Must be unique.
|
||||
* @param configurator the configurator which configures the builder
|
||||
* @return the configured creative mode tab
|
||||
* @see #registerCreativeModeTab(ResourceLocation, List, List, Consumer)
|
||||
*/
|
||||
public CreativeModeTab registerCreativeModeTab(ResourceLocation name, Consumer<CreativeModeTab.Builder> configurator)
|
||||
{
|
||||
return registrar.registerCreativeModeTab(configurator, name, DEFAULT_AFTER_ENTRIES, List.of());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fired when the contents of a specific creative mode tab are being populated.
|
||||
* This event may be fired multiple times if the operator status of the local player or enabled feature flags changes.
|
||||
* <p>
|
||||
* This event is not {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain FMLJavaModLoadingContext#getModEventBus() mod-specific event bus},
|
||||
* only on the {@linkplain LogicalSide#CLIENT logical client}.
|
||||
*/
|
||||
public static final class BuildContents extends CreativeModeTabEvent
|
||||
{
|
||||
private final CreativeModeTab tab;
|
||||
private final Set<DisplayItemsAdapter> customGenerators;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public BuildContents(CreativeModeTab tab, Set<DisplayItemsAdapter> customGenerators)
|
||||
{
|
||||
this.tab = tab;
|
||||
this.customGenerators = customGenerators;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given generator.
|
||||
*/
|
||||
public void register(DisplayItemsAdapter generator)
|
||||
{
|
||||
this.customGenerators.add(generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given generator if the provided creative mode tab matches this event's currently populating tab.
|
||||
*/
|
||||
public void register(CreativeModeTab tab, DisplayItemsAdapter generator)
|
||||
{
|
||||
if (this.tab == tab)
|
||||
this.customGenerators.add(generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given generator if the provided tab name matches this event's currently populating tab's name.
|
||||
*/
|
||||
public void register(ResourceLocation tabName, DisplayItemsAdapter generator)
|
||||
{
|
||||
if (this.tab == CreativeModeTabRegistry.getTab(tabName))
|
||||
this.customGenerators.add(generator);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given item if the provided creative mode tab matches this event's currently populating tab.
|
||||
*/
|
||||
public void registerSimple(CreativeModeTab tab, ItemLike item)
|
||||
{
|
||||
this.register(tab, (enabledFlags, output, permissions) -> output.accept(item));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given items if the provided creative mode tab matches this event's currently populating tab.
|
||||
*/
|
||||
public void registerSimple(CreativeModeTab tab, ItemLike... items)
|
||||
{
|
||||
this.register(tab, (enabledFlags, output, permissions) -> output.acceptAll(items));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the creative mode tab currently populating its contents}
|
||||
*/
|
||||
public CreativeModeTab getTab()
|
||||
{
|
||||
return this.tab;
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface DisplayItemsAdapter
|
||||
{
|
||||
void accept(FeatureFlagSet enabledFlags, CreativeModeTabPopulator populator, boolean hasPermissions);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface CreativeModeTabPopulator
|
||||
{
|
||||
void accept(ItemStack stack, CreativeModeTab.TabVisibility visibility, ItemStack before, ItemStack after);
|
||||
|
||||
default void accept(ItemStack stack, ItemStack before, ItemStack after)
|
||||
{
|
||||
accept(stack, CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS, before, after);
|
||||
}
|
||||
|
||||
default void accept(ItemLike stack, CreativeModeTab.TabVisibility visibility, ItemStack before, ItemStack after)
|
||||
{
|
||||
accept(new ItemStack(stack), visibility, before, after);
|
||||
}
|
||||
|
||||
default void accept(ItemLike stack, ItemStack before, ItemStack after)
|
||||
{
|
||||
accept(stack, CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS, before, after);
|
||||
}
|
||||
|
||||
default void accept(ItemStack stack, CreativeModeTab.TabVisibility visibility)
|
||||
{
|
||||
accept(stack, visibility, ItemStack.EMPTY, ItemStack.EMPTY);
|
||||
}
|
||||
|
||||
default void accept(ItemStack stack)
|
||||
{
|
||||
this.accept(stack, CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
}
|
||||
|
||||
default void accept(ItemLike itemLike, CreativeModeTab.TabVisibility visibility)
|
||||
{
|
||||
this.accept(new ItemStack(itemLike), visibility);
|
||||
}
|
||||
|
||||
default void accept(ItemLike itemLike)
|
||||
{
|
||||
this.accept(new ItemStack(itemLike), CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
}
|
||||
|
||||
default void acceptAll(Collection<ItemStack> stacks, CreativeModeTab.TabVisibility visibility)
|
||||
{
|
||||
stacks.forEach(stack -> this.accept(stack, visibility));
|
||||
}
|
||||
|
||||
default void acceptAll(Collection<ItemStack> stacks)
|
||||
{
|
||||
this.acceptAll(stacks, CreativeModeTab.TabVisibility.PARENT_AND_SEARCH_TABS);
|
||||
}
|
||||
|
||||
default void acceptAll(ItemLike... items)
|
||||
{
|
||||
for (ItemLike item : items)
|
||||
{
|
||||
this.accept(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -362,7 +362,7 @@ public class ForgeEventFactory
|
||||
return null;
|
||||
}
|
||||
|
||||
public static PlayLevelSoundEvent.AtEntity onPlaySoundAtEntity(Entity entity, SoundEvent name, SoundSource category, float volume, float pitch)
|
||||
public static PlayLevelSoundEvent.AtEntity onPlaySoundAtEntity(Entity entity, Holder<SoundEvent> name, SoundSource category, float volume, float pitch)
|
||||
{
|
||||
PlayLevelSoundEvent.AtEntity event = new PlayLevelSoundEvent.AtEntity(entity, name, category, volume, pitch);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
@@ -370,7 +370,7 @@ public class ForgeEventFactory
|
||||
}
|
||||
|
||||
|
||||
public static PlayLevelSoundEvent.AtPosition onPlaySoundAtPosition(Level level, double x, double y, double z, SoundEvent name, SoundSource category, float volume, float pitch)
|
||||
public static PlayLevelSoundEvent.AtPosition onPlaySoundAtPosition(Level level, double x, double y, double z, Holder<SoundEvent> name, SoundSource category, float volume, float pitch)
|
||||
{
|
||||
PlayLevelSoundEvent.AtPosition event = new PlayLevelSoundEvent.AtPosition(level, new Vec3(x, y, z), name, category, volume, pitch);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
@@ -579,7 +579,7 @@ public class ForgeEventFactory
|
||||
return event.getTable();
|
||||
}
|
||||
|
||||
public static boolean canCreateFluidSource(LevelReader level, BlockPos pos, BlockState state, boolean def)
|
||||
public static boolean canCreateFluidSource(Level level, BlockPos pos, BlockState state, boolean def)
|
||||
{
|
||||
CreateFluidSourceEvent evt = new CreateFluidSourceEvent(level, pos, state);
|
||||
MinecraftForge.EVENT_BUS.post(evt);
|
||||
@@ -606,8 +606,11 @@ public class ForgeEventFactory
|
||||
return !MinecraftForge.EVENT_BUS.post(new LivingDestroyBlockEvent(entity, pos, state));
|
||||
}
|
||||
|
||||
public static boolean getMobGriefingEvent(Level level, Entity entity)
|
||||
public static boolean getMobGriefingEvent(Level level, @Nullable Entity entity)
|
||||
{
|
||||
if (entity == null)
|
||||
return level.getGameRules().getBoolean(GameRules.RULE_MOBGRIEFING);
|
||||
|
||||
EntityMobGriefingEvent event = new EntityMobGriefingEvent(entity);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
|
||||
@@ -621,7 +624,7 @@ public class ForgeEventFactory
|
||||
return !blockGrowFeature(level, randomSource, pos, null).getResult().equals(Result.DENY);
|
||||
}
|
||||
|
||||
public static SaplingGrowTreeEvent blockGrowFeature(LevelAccessor level, RandomSource randomSource, BlockPos pos, Holder<? extends ConfiguredFeature<?, ?>> holder)
|
||||
public static SaplingGrowTreeEvent blockGrowFeature(LevelAccessor level, RandomSource randomSource, BlockPos pos, @Nullable Holder<? extends ConfiguredFeature<?, ?>> holder)
|
||||
{
|
||||
SaplingGrowTreeEvent event = new SaplingGrowTreeEvent(level, randomSource, pos, holder);
|
||||
MinecraftForge.EVENT_BUS.post(event);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package net.minecraftforge.event;
|
||||
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.sounds.SoundEvent;
|
||||
import net.minecraft.sounds.SoundSource;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -42,12 +43,12 @@ public class PlayLevelSoundEvent extends Event
|
||||
private final Level level;
|
||||
private final float originalVolume;
|
||||
private final float originalPitch;
|
||||
private SoundEvent sound;
|
||||
private Holder<SoundEvent> sound;
|
||||
private SoundSource source;
|
||||
private float newVolume;
|
||||
private float newPitch;
|
||||
|
||||
public PlayLevelSoundEvent(@NotNull Level level, @NotNull SoundEvent sound, @NotNull SoundSource source, float volume, float pitch)
|
||||
public PlayLevelSoundEvent(@NotNull Level level, @NotNull Holder<SoundEvent> sound, @NotNull SoundSource source, float volume, float pitch)
|
||||
{
|
||||
this.level = level;
|
||||
this.sound = sound;
|
||||
@@ -71,7 +72,7 @@ public class PlayLevelSoundEvent extends Event
|
||||
* {@return the sound event to be played}
|
||||
*/
|
||||
@Nullable
|
||||
public SoundEvent getSound()
|
||||
public Holder<SoundEvent> getSound()
|
||||
{
|
||||
return this.sound;
|
||||
}
|
||||
@@ -79,7 +80,7 @@ public class PlayLevelSoundEvent extends Event
|
||||
/**
|
||||
* Sets the sound event to be played.
|
||||
*/
|
||||
public void setSound(@Nullable SoundEvent sound)
|
||||
public void setSound(@Nullable Holder<SoundEvent> sound)
|
||||
{
|
||||
this.sound = sound;
|
||||
}
|
||||
@@ -165,7 +166,7 @@ public class PlayLevelSoundEvent extends Event
|
||||
{
|
||||
private final Entity entity;
|
||||
|
||||
public AtEntity(Entity entity, SoundEvent sound, SoundSource source, float volume, float pitch)
|
||||
public AtEntity(Entity entity, Holder<SoundEvent> sound, SoundSource source, float volume, float pitch)
|
||||
{
|
||||
super(entity.level, sound, source, volume, pitch);
|
||||
this.entity = entity;
|
||||
@@ -195,7 +196,7 @@ public class PlayLevelSoundEvent extends Event
|
||||
{
|
||||
private final Vec3 position;
|
||||
|
||||
public AtPosition(Level level, Vec3 position, SoundEvent sound, SoundSource source, float volume, float pitch)
|
||||
public AtPosition(Level level, Vec3 position, Holder<SoundEvent> sound, SoundSource source, float volume, float pitch)
|
||||
{
|
||||
super(level, sound, source, volume, pitch);
|
||||
this.position = position;
|
||||
|
||||
@@ -6,35 +6,24 @@
|
||||
package net.minecraftforge.event;
|
||||
|
||||
import java.util.Objects;
|
||||
import net.minecraft.client.Options;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatPacket;
|
||||
import net.minecraft.network.protocol.game.ServerboundChatPreviewPacket;
|
||||
import net.minecraft.server.level.ServerPlayer;
|
||||
import net.minecraftforge.common.ForgeMod;
|
||||
import net.minecraftforge.common.MinecraftForge;
|
||||
import net.minecraftforge.eventbus.api.Cancelable;
|
||||
import net.minecraftforge.eventbus.api.Event;
|
||||
import net.minecraftforge.fml.LogicalSide;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* This event is fired whenever a {@link ServerboundChatPreviewPacket} or {@link ServerboundChatPacket} is received.
|
||||
* <p>
|
||||
* Mods that modify chat messages from this event should call {@link ForgeMod#enableServerChatPreview()}
|
||||
* from their mod constructor to enable the chat preview and allow signing by clients.
|
||||
* It is recommended to listen to this event class when modifying chat messages
|
||||
* rather than a subclass to ensure clients with {@link Options#onlyShowSecureChat()}
|
||||
* enabled can see the modified messages.
|
||||
* This event is fired whenever a {@link ServerboundChatPacket} is received from a client
|
||||
* who has submitted their chat message.
|
||||
* <p>
|
||||
* This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If the event is cancelled, the message will not be sent to clients.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#SERVER logical server}.
|
||||
*
|
||||
* @see ForgeMod#enableServerChatPreview()
|
||||
**/
|
||||
@Cancelable
|
||||
public class ServerChatEvent extends Event
|
||||
@@ -42,16 +31,14 @@ public class ServerChatEvent extends Event
|
||||
private final ServerPlayer player;
|
||||
private final String username;
|
||||
private final String rawText;
|
||||
private final boolean canChangeMessage;
|
||||
private Component message;
|
||||
|
||||
@ApiStatus.Internal
|
||||
protected ServerChatEvent(ServerPlayer player, String rawText, Component message, boolean canChangeMessage)
|
||||
public ServerChatEvent(ServerPlayer player, String rawText, Component message)
|
||||
{
|
||||
this.player = player;
|
||||
this.username = player.getGameProfile().getName();
|
||||
this.rawText = rawText;
|
||||
this.canChangeMessage = canChangeMessage;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
@@ -79,33 +66,11 @@ public class ServerChatEvent extends Event
|
||||
return this.rawText;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return whether the message can be changed or not}.
|
||||
* In vanilla, this will be false if a {@link ServerboundChatPacket} is received
|
||||
* with signed decorated content already included by the sending player.
|
||||
* Players who submit a chat message with chat previews disabled will cause this to be true.
|
||||
*/
|
||||
public boolean canChangeMessage()
|
||||
{
|
||||
return this.canChangeMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the message to be sent to the relevant clients.
|
||||
* <p>
|
||||
* If {@link #canChangeMessage()} is false, this call will be ignored.
|
||||
* <p>
|
||||
* It is recommended to listen to {@link ServerChatEvent} when modifying chat messages
|
||||
* rather than a subclass to ensure clients with {@link Options#onlyShowSecureChat()}
|
||||
* enabled can see the modified messages.
|
||||
*
|
||||
* @see ForgeMod#enableServerChatPreview()
|
||||
*/
|
||||
public void setMessage(Component message)
|
||||
{
|
||||
if (!this.canChangeMessage)
|
||||
return;
|
||||
|
||||
this.message = Objects.requireNonNull(message);
|
||||
}
|
||||
|
||||
@@ -116,59 +81,4 @@ public class ServerChatEvent extends Event
|
||||
{
|
||||
return this.message;
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired whenever a {@link ServerboundChatPreviewPacket} is received from a client typing a message.
|
||||
* <p>
|
||||
* This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If the event is cancelled, the chat preview sent back to the client will match the original message.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#SERVER logical server}.
|
||||
**/
|
||||
public static class Preview extends ServerChatEvent
|
||||
{
|
||||
@ApiStatus.Internal
|
||||
public Preview(ServerPlayer player, String rawText, Component message)
|
||||
{
|
||||
super(player, rawText, message, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the chat preview to be sent back to the client.
|
||||
*/
|
||||
@Override
|
||||
public void setMessage(Component message)
|
||||
{
|
||||
super.setMessage(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@return the chat preview that will be sent back to the client, if the event is not cancelled}
|
||||
*/
|
||||
@Override
|
||||
public Component getMessage()
|
||||
{
|
||||
return super.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired whenever a {@link ServerboundChatPacket} is received from a client
|
||||
* who has submitted their chat message.
|
||||
* <p>
|
||||
* This event is {@linkplain Cancelable cancellable}, and does not {@linkplain HasResult have a result}.
|
||||
* If the event is cancelled, the message will not be sent to clients.
|
||||
* <p>
|
||||
* This event is fired on the {@linkplain MinecraftForge#EVENT_BUS main Forge event bus},
|
||||
* only on the {@linkplain LogicalSide#SERVER logical server}.
|
||||
**/
|
||||
public static class Submitted extends ServerChatEvent
|
||||
{
|
||||
@ApiStatus.Internal
|
||||
public Submitted(ServerPlayer player, String rawText, Component message, boolean canChangeMessage)
|
||||
{
|
||||
super(player, rawText, message, canChangeMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -230,18 +230,18 @@ public class BlockEvent extends Event
|
||||
@HasResult
|
||||
public static class CreateFluidSourceEvent extends Event
|
||||
{
|
||||
private final LevelReader level;
|
||||
private final Level level;
|
||||
private final BlockPos pos;
|
||||
private final BlockState state;
|
||||
|
||||
public CreateFluidSourceEvent(LevelReader level, BlockPos pos, BlockState state)
|
||||
public CreateFluidSourceEvent(Level level, BlockPos pos, BlockState state)
|
||||
{
|
||||
this.level = level;
|
||||
this.pos = pos;
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
public LevelReader getLevel()
|
||||
public Level getLevel()
|
||||
{
|
||||
return level;
|
||||
}
|
||||
|
||||
Loaded 100 of 726 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user