started lotus, seashell, giant lilypad, improved krakens grasp
This commit is contained in:
1 parent
361bf005f3
commit
c91590b553
11 files changed
-923
No files matched your search
@@ -1,146 +0,0 @@
|
||||
package software.bernie.geckolib.animatable;
|
||||
|
||||
import net.minecraft.class_1937;
|
||||
import net.minecraft.class_2586;
|
||||
import net.minecraft.class_3218;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import software.bernie.geckolib.GeckoLibConstants;
|
||||
import software.bernie.geckolib.GeckoLibServices;
|
||||
import software.bernie.geckolib.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.animation.AnimationController;
|
||||
import software.bernie.geckolib.constant.dataticket.SerializableDataTicket;
|
||||
import software.bernie.geckolib.util.RenderUtil;
|
||||
|
||||
/**
|
||||
* The {@link GeoAnimatable} interface specific to {@link class_2586 BlockEntities}
|
||||
*
|
||||
* @see <a href="https://github.com/bernie-g/geckolib/wiki/Block-Animations">GeckoLib Wiki - Block Animations</a>
|
||||
*/
|
||||
public interface GeoBlockEntity extends GeoAnimatable {
|
||||
/**
|
||||
* Get server-synced animation data via its relevant {@link SerializableDataTicket}.
|
||||
* <p>
|
||||
* Should only be used on the <u>client-side</u>
|
||||
* <p>
|
||||
* <b><u>DO NOT OVERRIDE</u></b>
|
||||
*
|
||||
* @param dataTicket The data ticket for the data to retrieve
|
||||
* @return The synced data, or null if no data of that type has been synced
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
@Nullable
|
||||
default <D> D getAnimData(SerializableDataTicket<D> dataTicket) {
|
||||
return getAnimatableInstanceCache().getManagerForId(0).getData(dataTicket);
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves an arbitrary piece of data to this animatable's {@link AnimatableManager}
|
||||
* <p>
|
||||
* <b><u>DO NOT OVERRIDE</u></b>
|
||||
*
|
||||
* @param dataTicket The DataTicket to sync the data for
|
||||
* @param data The data to sync
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
default <D> void setAnimData(SerializableDataTicket<D> dataTicket, D data) {
|
||||
class_2586 blockEntity = (class_2586)this;
|
||||
class_1937 level = blockEntity.method_10997();
|
||||
|
||||
if (level == null) {
|
||||
GeckoLibConstants.LOGGER.error("Attempting to set animation data for BlockEntity too early! Must wait until after the BlockEntity has been set in the world. (" + blockEntity.getClass().toString() + ")");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (level.method_8608()) {
|
||||
getAnimatableInstanceCache().getManagerForId(0).setData(dataTicket, data);
|
||||
}
|
||||
else {
|
||||
GeckoLibServices.NETWORK.syncBlockEntityAnimData(blockEntity.method_11016(), dataTicket, data, (class_3218)level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger an animation for this BlockEntity, based on the controller name and animation name
|
||||
* <p>
|
||||
* This can be fired from either the client or the server, but optimally you would call it from the server
|
||||
* <p>
|
||||
* <b><u>DO NOT OVERRIDE</u></b>
|
||||
*
|
||||
* @param controllerName The name of the controller name the animation belongs to, or null to do an inefficient lazy search
|
||||
* @param animName The name of animation to trigger. This needs to have been registered with the controller via {@link AnimationController#triggerableAnim AnimationController.triggerableAnim}
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
default void triggerAnim(@Nullable String controllerName, String animName) {
|
||||
class_2586 blockEntity = (class_2586)this;
|
||||
class_1937 level = blockEntity.method_10997();
|
||||
|
||||
if (level == null) {
|
||||
GeckoLibConstants.LOGGER.error("Attempting to trigger an animation for a BlockEntity too early! Must wait until after the BlockEntity has been set in the world. (" + blockEntity.getClass().toString() + ")");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (level.method_8608()) {
|
||||
if (controllerName != null) {
|
||||
getAnimatableInstanceCache().getManagerForId(0).tryTriggerAnimation(controllerName, animName);
|
||||
}
|
||||
else {
|
||||
getAnimatableInstanceCache().getManagerForId(0).tryTriggerAnimation(animName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GeckoLibServices.NETWORK.triggerBlockEntityAnim(blockEntity.method_11016(), controllerName, animName, (class_3218)level);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop a previously triggered animation for this BlockEntity for the given controller name and animation name
|
||||
* <p>
|
||||
* This can be fired from either the client or the server, but optimally you would call it from the server
|
||||
* <p>
|
||||
* <b><u>DO NOT OVERRIDE</u></b>
|
||||
*
|
||||
* @param controllerName The name of the controller name the animation belongs to, or null to do an inefficient lazy search
|
||||
* @param animName The name of the triggered animation to stop, or null to stop any currently playing triggered animation
|
||||
*/
|
||||
@ApiStatus.NonExtendable
|
||||
default void stopTriggeredAnim(@Nullable String controllerName, @Nullable String animName) {
|
||||
class_2586 blockEntity = (class_2586)this;
|
||||
class_1937 level = blockEntity.method_10997();
|
||||
|
||||
if (level == null) {
|
||||
GeckoLibConstants.LOGGER.error("Attempting to stop a triggered animation for a BlockEntity too early! Must wait until after the BlockEntity has been set in the world. (" + blockEntity.getClass().toString() + ")");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (level.method_8608()) {
|
||||
AnimatableManager<GeoAnimatable> animatableManager = getAnimatableInstanceCache().getManagerForId(0);
|
||||
|
||||
if (controllerName != null) {
|
||||
animatableManager.stopTriggeredAnimation(controllerName, animName);
|
||||
}
|
||||
else {
|
||||
animatableManager.stopTriggeredAnimation(animName);
|
||||
}
|
||||
}
|
||||
else {
|
||||
GeckoLibServices.NETWORK.stopTriggeredBlockEntityAnim(blockEntity.method_11016(), (class_3218)level, controllerName, animName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the current age/tick of the animatable instance
|
||||
* <p>
|
||||
* By default this is just the animatable's age in ticks, but this method allows for non-ticking custom animatables to provide their own values
|
||||
*
|
||||
* @param blockEntity The BlockEntity representing this animatable
|
||||
* @return The current tick/age of the animatable, for animation purposes
|
||||
*/
|
||||
@Override
|
||||
default double getTick(Object blockEntity) {
|
||||
return RenderUtil.getCurrentTick();
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
package software.bernie.geckolib.model;
|
||||
|
||||
import net.minecraft.class_2960;
|
||||
import software.bernie.geckolib.animatable.GeoAnimatable;
|
||||
|
||||
/**
|
||||
* {@link DefaultedGeoModel} specific to {@link net.minecraft.class_2248 Blocks}
|
||||
* <p>
|
||||
* Using this class pre-sorts provided asset paths into the "block" subdirectory
|
||||
*/
|
||||
public class DefaultedBlockGeoModel<T extends GeoAnimatable> extends DefaultedGeoModel<T> {
|
||||
/**
|
||||
* Create a new instance of this model class
|
||||
* <p>
|
||||
* The asset path should be the truncated relative path from the base folder
|
||||
* <p>
|
||||
* E.G.
|
||||
* <pre>{@code
|
||||
* new ResourceLocation("myMod", "workbench/sawmill")
|
||||
* }</pre>
|
||||
*/
|
||||
public DefaultedBlockGeoModel(class_2960 assetSubpath) {
|
||||
super(assetSubpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subtype string for this type of model
|
||||
* <p>
|
||||
* This allows for sorting of asset files into neat subdirectories for clean management.
|
||||
*/
|
||||
@Override
|
||||
protected String subtype() {
|
||||
return "block";
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the constructor-defined model path for this model to an alternate
|
||||
* <p>
|
||||
* This is useful if your animatable shares a model path with another animatable that differs in path to the texture and animations for this model
|
||||
*/
|
||||
@Override
|
||||
public DefaultedBlockGeoModel<T> withAltModel(class_2960 altPath) {
|
||||
return (DefaultedBlockGeoModel<T>)super.withAltModel(altPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the constructor-defined animations path for this model to an alternate
|
||||
* <p>
|
||||
* This is useful if your animatable shares an animations path with another animatable that differs in path to the model and texture for this model
|
||||
*/
|
||||
@Override
|
||||
public DefaultedBlockGeoModel<T> withAltAnimations(class_2960 altPath) {
|
||||
return (DefaultedBlockGeoModel<T>)super.withAltAnimations(altPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the constructor-defined texture path for this model to an alternate
|
||||
* <p>
|
||||
* This is useful if your animatable shares a texture path with another animatable that differs in path to the model and animations for this model
|
||||
*/
|
||||
@Override
|
||||
public DefaultedBlockGeoModel<T> withAltTexture(class_2960 altPath) {
|
||||
return (DefaultedBlockGeoModel<T>)super.withAltTexture(altPath);
|
||||
}
|
||||
}
|
||||
@@ -1,250 +0,0 @@
|
||||
package software.bernie.geckolib.model;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import software.bernie.geckolib.GeckoLibConstants;
|
||||
import software.bernie.geckolib.animatable.GeoAnimatable;
|
||||
import software.bernie.geckolib.animatable.GeoReplacedEntity;
|
||||
import software.bernie.geckolib.animation.AnimatableManager;
|
||||
import software.bernie.geckolib.animation.Animation;
|
||||
import software.bernie.geckolib.animation.AnimationProcessor;
|
||||
import software.bernie.geckolib.animation.AnimationState;
|
||||
import software.bernie.geckolib.cache.GeckoLibCache;
|
||||
import software.bernie.geckolib.cache.object.BakedGeoModel;
|
||||
import software.bernie.geckolib.cache.object.GeoBone;
|
||||
import software.bernie.geckolib.constant.DataTickets;
|
||||
import software.bernie.geckolib.constant.dataticket.DataTicket;
|
||||
import software.bernie.geckolib.loading.object.BakedAnimations;
|
||||
import software.bernie.geckolib.renderer.GeoRenderer;
|
||||
import software.bernie.geckolib.util.RenderUtil;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.DoubleSupplier;
|
||||
import net.minecraft.class_1297;
|
||||
import net.minecraft.class_1921;
|
||||
import net.minecraft.class_2960;
|
||||
import net.minecraft.class_310;
|
||||
|
||||
/**
|
||||
* Base class for all code-based model objects
|
||||
* <p>
|
||||
* All models registered to a {@link GeoRenderer} must be an instance of this or one of its subclasses
|
||||
*
|
||||
* @see <a href="https://github.com/bernie-g/geckolib/wiki/Models">GeckoLib Wiki - Models</a>
|
||||
*/
|
||||
public abstract class GeoModel<T extends GeoAnimatable> {
|
||||
private final AnimationProcessor<T> processor = new AnimationProcessor<>(this);
|
||||
|
||||
private BakedGeoModel currentModel = null;
|
||||
private double animTime;
|
||||
private double lastGameTickTime;
|
||||
private long lastRenderedInstance = -1;
|
||||
|
||||
/**
|
||||
* Returns the resource path for the {@link BakedGeoModel} (model json file) to render based on the provided animatable
|
||||
*/
|
||||
public class_2960 getModelResource(T animatable, @Nullable GeoRenderer<T> renderer) {
|
||||
return getModelResource(animatable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource path for the {@link BakedGeoModel} (model json file) to render based on the provided animatable
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class_2960 getModelResource(T animatable);
|
||||
|
||||
/**
|
||||
* Returns the resource path for the texture file to render based on the provided animatable
|
||||
*/
|
||||
public class_2960 getTextureResource(T animatable, @Nullable GeoRenderer<T> renderer) {
|
||||
return getTextureResource(animatable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource path for the texture file to render based on the provided animatable
|
||||
*/
|
||||
@Deprecated
|
||||
public abstract class_2960 getTextureResource(T animatable);
|
||||
|
||||
/**
|
||||
* Returns the resource path for the {@link BakedAnimations} (animation json file) to use for animations based on the provided animatable
|
||||
*/
|
||||
public abstract class_2960 getAnimationResource(T animatable);
|
||||
|
||||
/**
|
||||
* Returns the resource path for the {@link BakedAnimations} (animation json file) fallback locations in the event
|
||||
* your animation isn't present in the {@link #getAnimationResource(GeoAnimatable) primary resource}.
|
||||
* <p>
|
||||
* Should <b><u>NOT</u></b> be used as the primary animation resource path, and in general shouldn't be used
|
||||
* at all unless you know what you are doing
|
||||
*/
|
||||
public class_2960[] getAnimationResourceFallbacks(T animatable) {
|
||||
return new class_2960[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Override this and return true if Geckolib should crash when attempting to animate the model, but fails to find a bone
|
||||
* <p>
|
||||
* By default, GeckoLib will just gracefully ignore a missing bone, which might cause oddities with incorrect models or mismatching variables
|
||||
*/
|
||||
public boolean crashIfBoneMissing() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default render type for this animatable, to be selected by default by the renderer using it
|
||||
*
|
||||
* @return Return the RenderType to use, or null to prevent the model rendering. Returning null will not prevent animation functions taking place
|
||||
*/
|
||||
@Nullable
|
||||
public class_1921 getRenderType(T animatable, class_2960 texture) {
|
||||
return class_1921.method_23578(texture);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the baked geo model object used for rendering from the given resource path
|
||||
*/
|
||||
public BakedGeoModel getBakedModel(class_2960 location) {
|
||||
BakedGeoModel model = GeckoLibCache.getBakedModels().get(location);
|
||||
|
||||
if (model == null) {
|
||||
if (!location.method_12832().contains("geo/"))
|
||||
throw GeckoLibConstants.exception(location, "Invalid model resource path provided - GeckoLib models must be placed in assets/<modid>/geo/");
|
||||
|
||||
throw GeckoLibConstants.exception(location, "Unable to find model");
|
||||
}
|
||||
|
||||
if (model != this.currentModel) {
|
||||
this.processor.setActiveModel(model);
|
||||
this.currentModel = model;
|
||||
}
|
||||
|
||||
return this.currentModel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a bone from this model by name
|
||||
*
|
||||
* @param name The name of the bone
|
||||
* @return An {@link Optional} containing the {@link software.bernie.geckolib.cache.object.GeoBone} if one matches, otherwise an empty Optional
|
||||
*/
|
||||
public Optional<GeoBone> getBone(String name) {
|
||||
return Optional.ofNullable(getAnimationProcessor().getBone(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the loaded {@link Animation} for the given animation {@code name}, if it exists
|
||||
*
|
||||
* @param animatable The {@code GeoAnimatable} instance being referred to
|
||||
* @param name The name of the animation to retrieve
|
||||
* @return The {@code Animation} instance for the provided {@code name}, or null if none match
|
||||
*/
|
||||
@Nullable
|
||||
public Animation getAnimation(T animatable, String name) {
|
||||
class_2960 location = getAnimationResource(animatable);
|
||||
BakedAnimations bakedAnimations = GeckoLibCache.getBakedAnimations().get(location);
|
||||
Animation animation = bakedAnimations != null ? bakedAnimations.getAnimation(name) : null;
|
||||
|
||||
if (animation != null)
|
||||
return animation;
|
||||
|
||||
for (class_2960 fallbackLocation : getAnimationResourceFallbacks(animatable)) {
|
||||
bakedAnimations = GeckoLibCache.getBakedAnimations().get(location = fallbackLocation);
|
||||
animation = bakedAnimations != null ? bakedAnimations.getAnimation(name) : null;
|
||||
|
||||
if (animation != null)
|
||||
return animation;
|
||||
}
|
||||
|
||||
if (bakedAnimations == null) {
|
||||
if (!location.method_12832().contains("animations/"))
|
||||
throw GeckoLibConstants.exception(location, "Invalid animation resource path provided - GeckoLib animations must be placed in assets/<modid>/animations/");
|
||||
|
||||
throw GeckoLibConstants.exception(location, "Unable to find animation file.");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link AnimationProcessor} for this model.
|
||||
*/
|
||||
public AnimationProcessor<T> getAnimationProcessor() {
|
||||
return this.processor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add additional {@link DataTicket DataTickets} to the {@link AnimationState} to be handled by your animation handler at render time
|
||||
*
|
||||
* @param animatable The animatable instance currently being animated
|
||||
* @param instanceId The unique instance id of the animatable being animated
|
||||
* @param dataConsumer The DataTicket + data consumer to be added to the AnimationEvent
|
||||
*/
|
||||
public void addAdditionalStateData(T animatable, long instanceId, BiConsumer<DataTicket<T>, T> dataConsumer) {}
|
||||
|
||||
/**
|
||||
* This method is called once per render-frame for each {@link GeoAnimatable} being rendered
|
||||
* <p>
|
||||
* It is an internal method for automated animation parsing. Use {@link GeoModel#setCustomAnimations(GeoAnimatable, long, AnimationState)} for custom animation work
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public void handleAnimations(T animatable, long instanceId, AnimationState<T> animationState, float partialTick) {
|
||||
class_310 mc = class_310.method_1551();
|
||||
AnimatableManager<T> animatableManager = animatable.getAnimatableInstanceCache().getManagerForId(instanceId);
|
||||
Double currentTick = animationState.getData(DataTickets.TICK);
|
||||
|
||||
if (currentTick == null)
|
||||
currentTick = animatable instanceof class_1297 entity ? (double)entity.field_6012 : RenderUtil.getCurrentTick();
|
||||
|
||||
if (animatableManager.getFirstTickTime() == -1)
|
||||
animatableManager.startedAt(currentTick + partialTick);
|
||||
|
||||
double currentFrameTime = animatable instanceof class_1297 || animatable instanceof GeoReplacedEntity ? currentTick + partialTick : currentTick - animatableManager.getFirstTickTime();
|
||||
boolean isReRender = !animatableManager.isFirstTick() && currentFrameTime == animatableManager.getLastUpdateTime();
|
||||
|
||||
if (isReRender && instanceId == this.lastRenderedInstance)
|
||||
return;
|
||||
|
||||
if (!mc.method_1493() || animatable.shouldPlayAnimsWhileGamePaused()) {
|
||||
animatableManager.updatedAt(currentFrameTime);
|
||||
|
||||
double lastUpdateTime = animatableManager.getLastUpdateTime();
|
||||
this.animTime += lastUpdateTime - this.lastGameTickTime;
|
||||
this.lastGameTickTime = lastUpdateTime;
|
||||
}
|
||||
|
||||
animationState.animationTick = this.animTime;
|
||||
this.lastRenderedInstance = instanceId;
|
||||
AnimationProcessor<T> processor = getAnimationProcessor();
|
||||
|
||||
processor.preAnimationSetup(animationState, this.animTime);
|
||||
|
||||
if (!processor.getRegisteredBones().isEmpty())
|
||||
processor.tickAnimation(animatable, this, animatableManager, this.animTime, animationState, crashIfBoneMissing());
|
||||
|
||||
setCustomAnimations(animatable, instanceId, animationState);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called once per render-frame for each {@link GeoAnimatable} being rendered
|
||||
* <p>
|
||||
* Override to set custom animations (such as head rotation, etc)
|
||||
*
|
||||
* @param animatable The {@code GeoAnimatable} instance currently being rendered
|
||||
* @param instanceId The instance id of the {@code GeoAnimatable}
|
||||
* @param animationState An {@link AnimationState} instance created to hold animation data for the {@code animatable} for this method call
|
||||
*/
|
||||
public void setCustomAnimations(T animatable, long instanceId, AnimationState<T> animationState) {}
|
||||
|
||||
/**
|
||||
* This method is called once per render-frame for each {@link GeoAnimatable} being rendered
|
||||
* <p>
|
||||
* Use this method to set custom {@link software.bernie.geckolib.loading.math.value.Variable Variable} values via
|
||||
* {@link software.bernie.geckolib.loading.math.MathParser#setVariable(String, DoubleSupplier) MathParser.setVariable}
|
||||
*
|
||||
* @param animationState The AnimationState data for the current render frame
|
||||
* @param animTime The internal tick counter kept by the {@link AnimatableManager manager} for this animatable
|
||||
*/
|
||||
public void applyMolangQueries(AnimationState<T> animationState, double animTime) {}
|
||||
}
|
||||
@@ -1,272 +0,0 @@
|
||||
package software.bernie.geckolib.renderer;
|
||||
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector3f;
|
||||
import software.bernie.geckolib.GeckoLibServices;
|
||||
import software.bernie.geckolib.animatable.GeoAnimatable;
|
||||
import software.bernie.geckolib.animation.AnimationState;
|
||||
import software.bernie.geckolib.cache.object.BakedGeoModel;
|
||||
import software.bernie.geckolib.cache.object.GeoBone;
|
||||
import software.bernie.geckolib.cache.texture.AnimatableTexture;
|
||||
import software.bernie.geckolib.constant.DataTickets;
|
||||
import software.bernie.geckolib.model.DefaultedBlockGeoModel;
|
||||
import software.bernie.geckolib.model.GeoModel;
|
||||
import software.bernie.geckolib.renderer.layer.GeoRenderLayer;
|
||||
import software.bernie.geckolib.renderer.layer.GeoRenderLayersContainer;
|
||||
import software.bernie.geckolib.util.RenderUtil;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraft.class_1921;
|
||||
import net.minecraft.class_2318;
|
||||
import net.minecraft.class_2338;
|
||||
import net.minecraft.class_2350;
|
||||
import net.minecraft.class_2383;
|
||||
import net.minecraft.class_2586;
|
||||
import net.minecraft.class_2591;
|
||||
import net.minecraft.class_2680;
|
||||
import net.minecraft.class_4587;
|
||||
import net.minecraft.class_4588;
|
||||
import net.minecraft.class_4597;
|
||||
import net.minecraft.class_7833;
|
||||
import net.minecraft.class_7923;
|
||||
import net.minecraft.class_827;
|
||||
|
||||
/**
|
||||
* Base {@link GeoRenderer} class for rendering {@link class_2586 Blocks} specifically
|
||||
* <p>
|
||||
* All blocks added to be rendered by GeckoLib should use an instance of this class.
|
||||
*/
|
||||
public class GeoBlockRenderer<T extends class_2586 & GeoAnimatable> implements GeoRenderer<T>, class_827<T> {
|
||||
protected final GeoRenderLayersContainer<T> renderLayers = new GeoRenderLayersContainer<>(this);
|
||||
protected final GeoModel<T> model;
|
||||
|
||||
protected T animatable;
|
||||
protected float scaleWidth = 1;
|
||||
protected float scaleHeight = 1;
|
||||
|
||||
protected Matrix4f blockRenderTranslations = new Matrix4f();
|
||||
protected Matrix4f modelRenderTranslations = new Matrix4f();
|
||||
|
||||
/**
|
||||
* Creates a new defaulted renderer instance, using the blockentity's registered id as the file name for its assets
|
||||
*/
|
||||
public GeoBlockRenderer(class_2591<? extends T> blockEntityType) {
|
||||
this(new DefaultedBlockGeoModel<>(class_7923.field_41181.method_10221(blockEntityType)));
|
||||
}
|
||||
|
||||
public GeoBlockRenderer(GeoModel<T> model) {
|
||||
this.model = model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the model instance for this renderer
|
||||
*/
|
||||
@Override
|
||||
public GeoModel<T> getGeoModel() {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link GeoAnimatable} instance currently being rendered
|
||||
*/
|
||||
@Override
|
||||
public T getAnimatable() {
|
||||
return this.animatable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the id that represents the current animatable's instance for animation purposes
|
||||
* <p>
|
||||
* This is mostly useful for things like items, which have a single registered instance for all objects
|
||||
*/
|
||||
@Override
|
||||
public long getInstanceId(T animatable) {
|
||||
return animatable.method_11016().hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of registered {@link GeoRenderLayer GeoRenderLayers} for this renderer
|
||||
*/
|
||||
@Override
|
||||
public List<GeoRenderLayer<T>> getRenderLayers() {
|
||||
return this.renderLayers.getRenderLayers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a {@link GeoRenderLayer} to this renderer, to be called after the main model is rendered each frame
|
||||
*/
|
||||
public GeoBlockRenderer<T> addRenderLayer(GeoRenderLayer<T> renderLayer) {
|
||||
this.renderLayers.addLayer(renderLayer);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a scale override for this renderer, telling GeckoLib to pre-scale the model
|
||||
*/
|
||||
public GeoBlockRenderer<T> withScale(float scale) {
|
||||
return withScale(scale, scale);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a scale override for this renderer, telling GeckoLib to pre-scale the model
|
||||
*/
|
||||
public GeoBlockRenderer<T> withScale(float scaleWidth, float scaleHeight) {
|
||||
this.scaleWidth = scaleWidth;
|
||||
this.scaleHeight = scaleHeight;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called before rendering the model to buffer. Allows for render modifications and preparatory work such as scaling and translating
|
||||
* <p>
|
||||
* {@link class_4587} translations made here are kept until the end of the render process
|
||||
*/
|
||||
@Override
|
||||
public void preRender(class_4587 poseStack, T animatable, BakedGeoModel model, @Nullable class_4597 bufferSource, @Nullable class_4588 buffer, boolean isReRender, float partialTick, int packedLight, int packedOverlay, int colour) {
|
||||
this.blockRenderTranslations = new Matrix4f(poseStack.method_23760().method_23761());
|
||||
|
||||
if (!isReRender)
|
||||
poseStack.method_22904(0.5, 0, 0.5);
|
||||
|
||||
scaleModelForRender(this.scaleWidth, this.scaleHeight, poseStack, animatable, model, isReRender, partialTick, packedLight, packedOverlay);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ApiStatus.Internal
|
||||
public void method_3569(T animatable, float partialTick, class_4587 poseStack, class_4597 bufferSource,
|
||||
int packedLight, int packedOverlay) {
|
||||
this.animatable = animatable;
|
||||
|
||||
defaultRender(poseStack, this.animatable, bufferSource, null, null, 0, partialTick, packedLight);
|
||||
}
|
||||
|
||||
/**
|
||||
* The actual render method that subtype renderers should override to handle their specific rendering tasks
|
||||
* <p>
|
||||
* {@link GeoRenderer#preRender} has already been called by this stage, and {@link GeoRenderer#postRender} will be called directly after
|
||||
*/
|
||||
@Override
|
||||
public void actuallyRender(class_4587 poseStack, T animatable, BakedGeoModel model, @Nullable class_1921 renderType,
|
||||
class_4597 bufferSource, @Nullable class_4588 buffer, boolean isReRender, float partialTick, int packedLight,
|
||||
int packedOverlay, int colour) {
|
||||
if (!isReRender) {
|
||||
AnimationState<T> animationState = new AnimationState<T>(animatable, 0, 0, partialTick, false);
|
||||
long instanceId = getInstanceId(animatable);
|
||||
GeoModel<T> currentModel = getGeoModel();
|
||||
|
||||
animationState.setData(DataTickets.TICK, animatable.getTick(animatable));
|
||||
animationState.setData(DataTickets.BLOCK_ENTITY, animatable);
|
||||
currentModel.addAdditionalStateData(animatable, instanceId, animationState::setData);
|
||||
rotateBlock(getFacing(animatable), poseStack);
|
||||
currentModel.handleAnimations(animatable, instanceId, animationState, partialTick);
|
||||
}
|
||||
|
||||
this.modelRenderTranslations = new Matrix4f(poseStack.method_23760().method_23761());
|
||||
|
||||
if (buffer != null)
|
||||
GeoRenderer.super.actuallyRender(poseStack, animatable, model, renderType, bufferSource, buffer, isReRender, partialTick,
|
||||
packedLight, packedOverlay, colour);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after all render operations are completed and the render pass is considered functionally complete.
|
||||
* <p>
|
||||
* Use this method to clean up any leftover persistent objects stored during rendering or any other post-render maintenance tasks as required
|
||||
*/
|
||||
@Override
|
||||
public void doPostRenderCleanup() {
|
||||
this.animatable = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the provided {@link GeoBone} and its associated child bones
|
||||
*/
|
||||
@Override
|
||||
public void renderRecursively(class_4587 poseStack, T animatable, GeoBone bone, class_1921 renderType, class_4597 bufferSource, class_4588 buffer, boolean isReRender, float partialTick, int packedLight,
|
||||
int packedOverlay, int colour) {
|
||||
if (bone.isTrackingMatrices()) {
|
||||
Matrix4f poseState = new Matrix4f(poseStack.method_23760().method_23761());
|
||||
Matrix4f localMatrix = RenderUtil.invertAndMultiplyMatrices(poseState, this.blockRenderTranslations);
|
||||
Matrix4f worldState = new Matrix4f(localMatrix);
|
||||
class_2338 pos = this.animatable.method_11016();
|
||||
|
||||
bone.setModelSpaceMatrix(RenderUtil.invertAndMultiplyMatrices(poseState, this.modelRenderTranslations));
|
||||
bone.setLocalSpaceMatrix(localMatrix);
|
||||
bone.setWorldSpaceMatrix(worldState.translate(new Vector3f(pos.method_10263(), pos.method_10264(), pos.method_10260())));
|
||||
}
|
||||
|
||||
GeoRenderer.super.renderRecursively(poseStack, animatable, bone, renderType, bufferSource, buffer, isReRender, partialTick, packedLight, packedOverlay,
|
||||
colour);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate the {@link class_4587} based on the determined {@link class_2350} the block is facing
|
||||
*/
|
||||
protected void rotateBlock(class_2350 facing, class_4587 poseStack) {
|
||||
switch (facing) {
|
||||
case field_11035 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(180));
|
||||
case field_11039 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(90));
|
||||
case field_11043 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(0));
|
||||
case field_11034 -> poseStack.method_22907(class_7833.field_40716.rotationDegrees(270));
|
||||
case field_11036 -> poseStack.method_22907(class_7833.field_40714.rotationDegrees(90));
|
||||
case field_11033 -> poseStack.method_22907(class_7833.field_40713.rotationDegrees(90));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to extract a direction from the block so that the model can be oriented correctly
|
||||
*/
|
||||
protected class_2350 getFacing(T block) {
|
||||
class_2680 blockState = block.method_11010();
|
||||
|
||||
if (blockState.method_28498(class_2383.field_11177))
|
||||
return blockState.method_11654(class_2383.field_11177);
|
||||
|
||||
if (blockState.method_28498(class_2318.field_10927))
|
||||
return blockState.method_11654(class_2318.field_10927);
|
||||
|
||||
return class_2350.field_11043;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the current frame of a {@link AnimatableTexture potentially animated} texture used by this GeoRenderer
|
||||
* <p>
|
||||
* This should only be called immediately prior to rendering
|
||||
*
|
||||
* @see AnimatableTexture#setAndUpdate
|
||||
*/
|
||||
@Override
|
||||
public void updateAnimatedTextureFrame(T animatable) {
|
||||
AnimatableTexture.setAndUpdate(getTextureLocation(animatable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and fire the relevant {@code CompileLayers} event hook for this renderer
|
||||
*/
|
||||
@Override
|
||||
public void fireCompileRenderLayersEvent() {
|
||||
GeckoLibServices.Client.EVENTS.fireCompileBlockRenderLayers(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and fire the relevant {@code Pre-Render} event hook for this renderer
|
||||
*
|
||||
* @return Whether the renderer should proceed based on the cancellation state of the event
|
||||
*/
|
||||
@Override
|
||||
public boolean firePreRenderEvent(class_4587 poseStack, BakedGeoModel model, class_4597 bufferSource, float partialTick, int packedLight) {
|
||||
return GeckoLibServices.Client.EVENTS.fireBlockPreRender(this, poseStack, model, bufferSource, partialTick, packedLight);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and fire the relevant {@code Post-Render} event hook for this renderer
|
||||
*/
|
||||
@Override
|
||||
public void firePostRenderEvent(class_4587 poseStack, BakedGeoModel model, class_4597 bufferSource, float partialTick, int packedLight) {
|
||||
GeckoLibServices.Client.EVENTS.fireBlockPostRender(this, poseStack, model, bufferSource, partialTick, packedLight);
|
||||
}
|
||||
}
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 2017, 2018, 2019 FabricMC
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.fabricmc.fabric.api.registry;
|
||||
|
||||
import net.fabricmc.fabric.api.event.Event;
|
||||
import net.fabricmc.fabric.api.event.EventFactory;
|
||||
import net.minecraft.class_1792;
|
||||
import net.minecraft.class_1842;
|
||||
import net.minecraft.class_1845;
|
||||
import net.minecraft.class_1856;
|
||||
import net.minecraft.class_6880;
|
||||
import net.minecraft.class_7699;
|
||||
|
||||
/**
|
||||
* An extension of {@link class_1845.class_9665} to support ingredients.
|
||||
*/
|
||||
public interface FabricBrewingRecipeRegistryBuilder {
|
||||
/**
|
||||
* An event that is called when the brewing recipe registry is being built.
|
||||
*/
|
||||
Event<FabricBrewingRecipeRegistryBuilder.BuildCallback> BUILD = EventFactory.createArrayBacked(FabricBrewingRecipeRegistryBuilder.BuildCallback.class, listeners -> builder -> {
|
||||
for (FabricBrewingRecipeRegistryBuilder.BuildCallback listener : listeners) {
|
||||
listener.build(builder);
|
||||
}
|
||||
});
|
||||
|
||||
default void registerItemRecipe(class_1792 input, class_1856 ingredient, class_1792 output) {
|
||||
throw new AssertionError("Must be implemented via interface injection");
|
||||
}
|
||||
|
||||
default void registerPotionRecipe(class_6880<class_1842> input, class_1856 ingredient, class_6880<class_1842> output) {
|
||||
throw new AssertionError("Must be implemented via interface injection");
|
||||
}
|
||||
|
||||
default void registerRecipes(class_1856 ingredient, class_6880<class_1842> potion) {
|
||||
throw new AssertionError("Must be implemented via interface injection");
|
||||
}
|
||||
|
||||
default class_7699 getEnabledFeatures() {
|
||||
throw new AssertionError("Must be implemented via interface injection");
|
||||
}
|
||||
|
||||
/**
|
||||
* Use this event to register custom brewing recipes.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
interface BuildCallback {
|
||||
/**
|
||||
* Called when the brewing recipe registry is being built.
|
||||
*
|
||||
* @param builder the {@link class_1845} instance
|
||||
*/
|
||||
void build(class_1845.class_9665 builder);
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.neoforged.neoforge.common.brewing;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.crafting.Ingredient;
|
||||
|
||||
public class BrewingRecipe implements IBrewingRecipe {
|
||||
private final Ingredient input;
|
||||
private final Ingredient ingredient;
|
||||
private final ItemStack output;
|
||||
|
||||
public BrewingRecipe(Ingredient input, Ingredient ingredient, ItemStack output) {
|
||||
this.input = input;
|
||||
this.ingredient = ingredient;
|
||||
this.output = output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInput(ItemStack stack) {
|
||||
return this.input.test(stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemStack getOutput(ItemStack input, ItemStack ingredient) {
|
||||
return isInput(input) && isIngredient(ingredient) ? getOutput().copy() : ItemStack.EMPTY;
|
||||
}
|
||||
|
||||
public Ingredient getInput() {
|
||||
return input;
|
||||
}
|
||||
|
||||
public Ingredient getIngredient() {
|
||||
return ingredient;
|
||||
}
|
||||
|
||||
public ItemStack getOutput() {
|
||||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIngredient(ItemStack ingredient) {
|
||||
return this.ingredient.test(ingredient);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Forge Development LLC and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.neoforged.neoforge.common.brewing;
|
||||
|
||||
import static net.minecraft.world.item.alchemy.PotionBrewing.Builder;
|
||||
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.neoforged.neoforge.event.brewing.RegisterBrewingRecipesEvent;
|
||||
|
||||
/**
|
||||
* Interface for more flexible brewing recipes.
|
||||
*
|
||||
* <p>Register using {@link RegisterBrewingRecipesEvent} and {@link Builder#addRecipe(IBrewingRecipe)}.
|
||||
*/
|
||||
public interface IBrewingRecipe {
|
||||
/**
|
||||
* Returns true is the passed ItemStack is an input for this recipe. "Input"
|
||||
* being the item that goes in one of the three bottom slots of the brewing
|
||||
* stand (e.g: water bottle)
|
||||
*/
|
||||
boolean isInput(ItemStack input);
|
||||
|
||||
/**
|
||||
* Returns true if the passed ItemStack is an ingredient for this recipe.
|
||||
* "Ingredient" being the item that goes in the top slot of the brewing
|
||||
* stand (e.g: nether wart)
|
||||
*/
|
||||
boolean isIngredient(ItemStack ingredient);
|
||||
|
||||
/**
|
||||
* Returns the output when the passed input is brewed with the passed
|
||||
* ingredient. Empty if invalid input or ingredient.
|
||||
*/
|
||||
ItemStack getOutput(ItemStack input, ItemStack ingredient);
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) NeoForged and contributors
|
||||
* SPDX-License-Identifier: LGPL-2.1-only
|
||||
*/
|
||||
|
||||
package net.neoforged.neoforge.event.brewing;
|
||||
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.world.item.alchemy.PotionBrewing;
|
||||
import net.neoforged.bus.api.Event;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
|
||||
/**
|
||||
* Event to register new brewing recipes.
|
||||
*
|
||||
* <p>Fired on both client and server side, on the main event bus.
|
||||
*/
|
||||
public class RegisterBrewingRecipesEvent extends Event {
|
||||
private final PotionBrewing.Builder builder;
|
||||
private final RegistryAccess registryAccess;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public RegisterBrewingRecipesEvent(PotionBrewing.Builder builder, RegistryAccess registryAccess) {
|
||||
this.builder = builder;
|
||||
this.registryAccess = registryAccess;
|
||||
}
|
||||
|
||||
public PotionBrewing.Builder getBuilder() {
|
||||
return builder;
|
||||
}
|
||||
|
||||
public RegistryAccess getRegistryAccess() {
|
||||
return registryAccess;
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user