Skip to content

Commit

Permalink
Merge pull request #172 from applejuiceyy/1.20
Browse files Browse the repository at this point in the history
EntityTasks
  • Loading branch information
UnlikePaladin committed Feb 10, 2024
2 parents f6d80c6 + f10a65f commit 9582402
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package org.figuramc.figura.ducks;

import java.util.OptionalInt;

public class LivingEntityRendererAccessor {
@SuppressWarnings("OptionalUsedAsFieldOrParameterType") // cry
public static OptionalInt overrideOverlay = OptionalInt.empty();
}
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ public class FiguraAPIManager {
add(RenderTask.class);
add(ItemTask.class);
add(BlockTask.class);
add(EntityTask.class);
add(TextTask.class);
add(SpriteTask.class);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,8 @@ public class FiguraDocsManager {
BlockTask.class,
ItemTask.class,
TextTask.class,
SpriteTask.class
SpriteTask.class,
EntityTask.class
));

put("player", List.of(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ public interface LivingEntityAccessor {
@Intrinsic
@Invoker("getCurrentSwingDuration")
int getSwingDuration();

@Intrinsic
@Invoker("updateWalkAnimation")
void invokeUpdateWalkAnimation(float distance);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import org.figuramc.figura.avatar.Avatar;
import org.figuramc.figura.avatar.AvatarManager;
import org.figuramc.figura.config.Configs;
import org.figuramc.figura.ducks.LivingEntityRendererAccessor;
import org.figuramc.figura.gui.PopupMenu;
import org.figuramc.figura.lua.api.vanilla_model.VanillaPart;
import org.figuramc.figura.math.matrix.FiguraMat4;
Expand All @@ -28,6 +29,7 @@
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

Expand Down Expand Up @@ -62,6 +64,18 @@ private void onRender(T livingEntity, float f, float g, PoseStack poseStack, Mul
lastPose = poseStack.last().pose();
}

@ModifyArg(
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/model/EntityModel;renderToBuffer(Lcom/mojang/blaze3d/vertex/PoseStack;Lcom/mojang/blaze3d/vertex/VertexConsumer;IIFFFF)V"
),
method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V",
index = 3
)
private int customOverlay(int thing) {
return LivingEntityRendererAccessor.overrideOverlay.orElse(thing);
}

@Inject(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/model/EntityModel;setupAnim(Lnet/minecraft/world/entity/Entity;FFFFF)V", shift = At.Shift.AFTER), method = "render(Lnet/minecraft/world/entity/LivingEntity;FFLcom/mojang/blaze3d/vertex/PoseStack;Lnet/minecraft/client/renderer/MultiBufferSource;I)V", cancellable = true)
private void preRender(T entity, float yaw, float delta, PoseStack poseStack, MultiBufferSource bufferSource, int light, CallbackInfo ci) {
if (currentAvatar == null)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package org.figuramc.figura.model;

import com.mojang.datafixers.util.Pair;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.texture.OverlayTexture;
import org.figuramc.figura.avatar.Avatar;
Expand Down Expand Up @@ -1300,6 +1299,19 @@ public SpriteTask newSprite(@LuaNotNil String name) {
return task;
}

@LuaWhitelist
@LuaMethodDoc(
overloads = @LuaMethodOverload(
argumentTypes = String.class,
argumentNames = "taskName"
),
value = "model_part.new_entity")
public EntityTask newEntity(@LuaNotNil String name) {
EntityTask task = new EntityTask(name, owner, this);
this.renderTasks.put(name, task);
return task;
}

@LuaWhitelist
@LuaMethodDoc(overloads = @LuaMethodOverload(argumentTypes = RenderTask.class, argumentNames = "renderTask"), value = "model_part.add_task")
public RenderTask addTask(@LuaNotNil RenderTask renderTask) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package org.figuramc.figura.model.rendertasks;

import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.brigadier.StringReader;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRenderDispatcher;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.StringTag;
import net.minecraft.nbt.TagParser;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import org.figuramc.figura.avatar.Avatar;
import org.figuramc.figura.ducks.LivingEntityRendererAccessor;
import org.figuramc.figura.lua.LuaWhitelist;
import org.figuramc.figura.lua.api.entity.EntityAPI;
import org.figuramc.figura.lua.docs.LuaMethodDoc;
import org.figuramc.figura.lua.docs.LuaMethodOverload;
import org.figuramc.figura.lua.docs.LuaTypeDoc;
import org.figuramc.figura.math.vector.FiguraVec2;
import org.figuramc.figura.mixin.LivingEntityAccessor;
import org.figuramc.figura.model.FiguraModelPart;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nullable;
import org.luaj.vm2.LuaError;

import java.util.OptionalInt;
import java.util.function.Function;

@LuaWhitelist
@LuaTypeDoc(
name = "EntityTask",
value = "entity_task"
)
public class EntityTask extends RenderTask {

@Nullable Entity entity;
long ticksSinceEntity;

public EntityTask(String name, Avatar owner, FiguraModelPart parent) {
super(name, owner, parent);
}

@Override
public void render(PoseStack stack, MultiBufferSource buffer, int light, int overlay) {
stack.scale(16, 16, 16);

if (entity != null) {
assert Minecraft.getInstance().level != null;
entity.tickCount = (int) (Minecraft.getInstance().level.getGameTime() - ticksSinceEntity);
EntityRenderDispatcher dispatcher = Minecraft.getInstance().getEntityRenderDispatcher();
boolean h = dispatcher.shouldRenderHitBoxes();
dispatcher.setRenderHitBoxes(false);
OptionalInt prev = LivingEntityRendererAccessor.overrideOverlay;
LivingEntityRendererAccessor.overrideOverlay = OptionalInt.of(this.customization.overlay != null ? this.customization.overlay : overlay);
try {
Minecraft.getInstance().getEntityRenderDispatcher()
.render(
entity, 0.0, 0.0, 0.0, 0.0F, Minecraft.getInstance().getFrameTime(), stack, buffer,
this.customization.light != null ? this.customization.light : light
);
}
finally {
LivingEntityRendererAccessor.overrideOverlay = prev;
dispatcher.setRenderHitBoxes(h);
}
}
}


@Override
public int getComplexity() {
return 20; // good enough
}

@Override
public boolean shouldRender() {
return super.shouldRender() && entity != null;
}

@LuaWhitelist
@LuaMethodDoc("entity_task.as_entity")
public EntityAPI<?> asEntity() {
return entity == null ? null : new EntityAPI<>(entity);
}

@LuaWhitelist
@Contract("_,_->this")
@LuaMethodDoc(
overloads = {
@LuaMethodOverload(
argumentTypes = String.class,
argumentNames = "nbt"
),
@LuaMethodOverload(
argumentTypes = {String.class, String.class},
argumentNames = {"id", "nbt"}
)
},

value = "entity_task.set_nbt"
)
public EntityTask setNbt(String nbtOrId, String nullOrNbt) {
try {
CompoundTag finalNbt;
if(nullOrNbt == null) {
finalNbt = (new TagParser(new StringReader(nbtOrId))).readStruct();

if (!finalNbt.contains("id", CompoundTag.TAG_STRING)) {
throw new LuaError("Nbt must contain id");
}
}
else {
finalNbt = (new TagParser(new StringReader(nullOrNbt))).readStruct();
finalNbt.put("id", StringTag.valueOf(nbtOrId));
}

assert Minecraft.getInstance().level != null;
entity = EntityType.loadEntityRecursive(finalNbt, Minecraft.getInstance().level, Function.identity());
if (entity == null) {
throw new LuaError("Could not create entity");
}
ticksSinceEntity = Minecraft.getInstance().level.getGameTime() - entity.tickCount;
} catch (CommandSyntaxException e) {
throw new LuaError(e.getMessage());
}
return this;
}

@LuaWhitelist
@Contract("_->this")
@LuaMethodDoc(
overloads = @LuaMethodOverload(
argumentTypes = String.class,
argumentNames = "distance"
),
value = "entity_task.update_walking_distance"
)
public EntityTask updateWalkingDistance(float distance) {
if(entity != null && entity instanceof LivingEntity living) {
((LivingEntityAccessor) living).invokeUpdateWalkAnimation(distance);
}
return this;
}

@LuaWhitelist
@Contract("_->this")
@LuaMethodDoc(
overloads = @LuaMethodOverload(
argumentTypes = FiguraVec2.class,
argumentNames = "rotation"
),
value = "entity_task.set_head_rotation"
)
public EntityTask setHeadRotation(FiguraVec2 vec2) {
if(entity != null && entity instanceof LivingEntity living) {
living.yHeadRot = (float) vec2.y;
living.yHeadRotO = (float) vec2.y;
living.setXRot((float) vec2.x);
living.xRotO = (float) vec2.x;
}
return this;
}
}
6 changes: 6 additions & 0 deletions common/src/main/resources/assets/figura/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -1277,6 +1277,7 @@
"figura.docs.model_part.new_item": "Adds a new Item Render Task on this part",
"figura.docs.model_part.new_block": "Adds a new Block Render Task on this part",
"figura.docs.model_part.new_sprite": "Adds a new Sprite Render Task on this part",
"figura.docs.model_part.new_entity": "Adds a new Entity Render Task on this part",
"figura.docs.model_part.add_task": "Adds the given Render Task on this part",
"figura.docs.model_part.get_task": "Gets the Render Task with the given name from this part\nReturns a table with all tasks if a name is not given",
"figura.docs.model_part.remove_task": "Removes the Task with the given name from this part\nRemoves ALL tasks if a name is not given",
Expand Down Expand Up @@ -1413,6 +1414,11 @@
"figura.docs.sprite_task.get_render_type": "Gets the name of the current render type for this sprite",
"figura.docs.sprite_task.set_render_type": "Sets the current render type of this sprite\nTRANSLUCENT by default\nCheck the docs enum command for all render types",
"figura.docs.sprite_task.get_vertices": "Returns a table with all 4 vertices of this sprite\nChanging the values through other functions will reset those vertices",
"figura.docs.entity_task": "A task for rendering an Entity",
"figura.docs.entity_task.as_entity": "Returns the entity associated with this task, or nil if the entity could not exist for any reason.\nDue to the special circumstances some readings of the subsequent value may be completely useless",
"figura.docs.entity_task.set_nbt": "Sets [the nbt of] the entity",
"figura.docs.entity_task.update_walking_distance": "Updates the walking animations given the new information, if applicable. For an expected result it should be called every tick with the appropriate value",
"figura.docs.entity_task.set_head_rotation": "Updates the head rotation of the entity, if applicable",
"figura.docs.renderer": "A global API providing functions that change the way Minecraft renders your player",
"figura.docs.renderer.render_fire": "Whether or not you should visually have the fire effect while on fire\nTrue by default",
"figura.docs.renderer.render_vehicle": "Whether or not your vehicle (boat, minecart, horse, whatever) will be rendered\nTrue by default",
Expand Down

0 comments on commit 9582402

Please sign in to comment.