Compare commits

...

No commits in common. "1.21" and "R3944Realms_LeashedPlayer_neoforge_1_21_5" have entirely different histories.

203 changed files with 2744 additions and 4028 deletions

View File

@ -12,13 +12,14 @@ jobs:
fetch-depth: 0
fetch-tags: true
- name: Setup JDK 17
- name: Setup JDK 21
uses: actions/setup-java@v4
with:
java-version: '17'
java-version: '21'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/actions/setup-gradle@v4
- name: Build with Gradle
uses: gradle/actions/setup-gradle@v3
with:
arguments: build
run: ./gradlew build

View File

@ -1,39 +0,0 @@
package com.r3944realms.leashedplayer.client.models;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.entity.Entity;
import java.util.function.Function;
public abstract class BasicEntityModel<T extends Entity> extends EntityModel<T> {
public int textureWidth = 64;
public int textureHeight = 32;
protected BasicEntityModel() {
this(RenderType::entityCutoutNoCull);
}
protected BasicEntityModel(Function<ResourceLocation, RenderType> pRenderType) {
super(pRenderType);
}
@Override
public void renderToBuffer(PoseStack p_103013_, VertexConsumer p_103014_, int p_103015_, int p_103016_, float p_103017_, float p_103018_, float p_103019_, float p_103020_) {
this.parts().forEach((p_103030_) -> {
p_103030_.render(p_103013_, p_103014_, p_103015_, p_103016_, p_103017_, p_103018_, p_103019_, p_103020_);
});
}
public abstract Iterable<BasicModelPart> parts();
@Override
public abstract void setupAnim(T p_102618_, float p_102619_, float p_102620_, float p_102621_, float p_102622_, float p_102623_);
@Override
public void prepareMobModel(T p_102614_, float p_102615_, float p_102616_, float p_102617_) {
}
}

View File

@ -1,314 +0,0 @@
package com.r3944realms.leashedplayer.client.models;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Axis;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import net.neoforged.neoforge.client.event.RenderTooltipEvent;
import org.joml.Matrix3f;
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import it.unimi.dsi.fastutil.objects.ObjectList;
import net.minecraft.core.Direction;
import java.util.Random;
/*
* @since 1.9.0
* Duplicate of ModelPart class which is not final
*/
@OnlyIn(Dist.CLIENT)
public class BasicModelPart {
public float textureWidth = 64.0F;
public float textureHeight = 32.0F;
public int textureOffsetX;
public int textureOffsetY;
public float rotationPointX;
public float rotationPointY;
public float rotationPointZ;
public float rotateAngleX;
public float rotateAngleY;
public float rotateAngleZ;
public boolean mirror;
public boolean showModel = true;
private final ObjectList<BasicModelPart.ModelBox> cubeList = new ObjectArrayList<>();
private final ObjectList<BasicModelPart> childModels = new ObjectArrayList<>();
public BasicModelPart(BasicEntityModel model) {
this.setTextureSize(model.textureWidth, model.textureHeight);
}
public BasicModelPart(BasicEntityModel model, int texOffX, int texOffY) {
this(model.textureWidth, model.textureHeight, texOffX, texOffY);
}
public BasicModelPart(int textureWidthIn, int textureHeightIn, int textureOffsetXIn, int textureOffsetYIn) {
this.setTextureSize(textureWidthIn, textureHeightIn);
this.setTextureOffset(textureOffsetXIn, textureOffsetYIn);
}
private BasicModelPart() {
}
public BasicModelPart getModelAngleCopy() {
BasicModelPart BasicModelPart = new BasicModelPart();
BasicModelPart.copyModelAngles(this);
return BasicModelPart;
}
public void copyModelAngles(BasicModelPart BasicModelPartIn) {
this.rotateAngleX = BasicModelPartIn.rotateAngleX;
this.rotateAngleY = BasicModelPartIn.rotateAngleY;
this.rotateAngleZ = BasicModelPartIn.rotateAngleZ;
this.rotationPointX = BasicModelPartIn.rotationPointX;
this.rotationPointY = BasicModelPartIn.rotationPointY;
this.rotationPointZ = BasicModelPartIn.rotationPointZ;
}
/**
* Sets the current box's rotation points and rotation angles to another box.
*/
public void addChild(BasicModelPart renderer) {
this.childModels.add(renderer);
}
public BasicModelPart setTextureOffset(int x, int y) {
this.textureOffsetX = x;
this.textureOffsetY = y;
return this;
}
public BasicModelPart addBox(String partName, float x, float y, float z, int width, int height, int depth, float delta, int texX, int texY) {
this.setTextureOffset(texX, texY);
this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, (float)width, (float)height, (float)depth, delta, delta, delta, this.mirror, false);
return this;
}
public BasicModelPart addBox(float x, float y, float z, float width, float height, float depth) {
this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, 0.0F, 0.0F, 0.0F, this.mirror, false);
return this;
}
public BasicModelPart addBox(float x, float y, float z, float width, float height, float depth, boolean mirrorIn) {
this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, 0.0F, 0.0F, 0.0F, mirrorIn, false);
return this;
}
public void addBox(float x, float y, float z, float width, float height, float depth, float delta) {
this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, delta, delta, delta, this.mirror, false);
}
public void addBox(float x, float y, float z, float width, float height, float depth, float deltaX, float deltaY, float deltaZ) {
this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, deltaX, deltaY, deltaZ, this.mirror, false);
}
public void addBox(float x, float y, float z, float width, float height, float depth, float delta, boolean mirrorIn) {
this.addBox(this.textureOffsetX, this.textureOffsetY, x, y, z, width, height, depth, delta, delta, delta, mirrorIn, false);
}
private void addBox(int texOffX, int texOffY, float x, float y, float z, float width, float height, float depth, float deltaX, float deltaY, float deltaZ, boolean mirorIn, boolean p_228305_13_) {
this.cubeList.add(new BasicModelPart.ModelBox(texOffX, texOffY, x, y, z, width, height, depth, deltaX, deltaY, deltaZ, mirorIn, this.textureWidth, this.textureHeight));
}
public void setRotationPoint(float rotationPointXIn, float rotationPointYIn, float rotationPointZIn) {
this.rotationPointX = rotationPointXIn;
this.rotationPointY = rotationPointYIn;
this.rotationPointZ = rotationPointZIn;
}
public void render(PoseStack matrixStackIn, VertexConsumer bufferIn, int packedLightIn, int packedOverlayIn) {
this.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, 1.0F, 1.0F, 1.0F, 1.0F);
}
public void render(PoseStack matrixStackIn, VertexConsumer bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha) {
if (this.showModel) {
if (!this.cubeList.isEmpty() || !this.childModels.isEmpty()) {
matrixStackIn.pushPose();
this.translateRotate(matrixStackIn);
this.doRender(matrixStackIn.last(), bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
for(BasicModelPart BasicModelPart : this.childModels) {
BasicModelPart.render(matrixStackIn, bufferIn, packedLightIn, packedOverlayIn, red, green, blue, alpha);
}
matrixStackIn.popPose();
}
}
}
public void translateRotate(PoseStack matrixStackIn) {
matrixStackIn.translate((double)(this.rotationPointX / 16.0F), (double)(this.rotationPointY / 16.0F), (double)(this.rotationPointZ / 16.0F));
if (this.rotateAngleZ != 0.0F) {
matrixStackIn.mulPose(Axis.ZP.rotation(this.rotateAngleZ));
}
if (this.rotateAngleY != 0.0F) {
matrixStackIn.mulPose(Axis.YP.rotation(this.rotateAngleY));
}
if (this.rotateAngleX != 0.0F) {
matrixStackIn.mulPose(Axis.XP.rotation(this.rotateAngleX));
}
}
private void doRender(PoseStack.Pose matrixEntryIn, VertexConsumer bufferIn, int packedLightIn, int packedOverlayIn, float red, float green, float blue, float alpha) {
Matrix4f matrix4f = matrixEntryIn.pose();
Matrix3f matrix3f = matrixEntryIn.normal();
for(BasicModelPart.ModelBox BasicModelPart$modelbox : this.cubeList) {
for(BasicModelPart.TexturedQuad BasicModelPart$texturedquad : BasicModelPart$modelbox.quads) {
Vector3f vector3f = new Vector3f(BasicModelPart$texturedquad.normal);
vector3f.mul(matrix3f);
float f = vector3f.x();
float f1 = vector3f.y();
float f2 = vector3f.z();
for(int i = 0; i < 4; ++i) {
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex = BasicModelPart$texturedquad.vertexPositions[i];
float f3 = BasicModelPart$positiontexturevertex.position.x() / 16.0F;
float f4 = BasicModelPart$positiontexturevertex.position.y() / 16.0F;
float f5 = BasicModelPart$positiontexturevertex.position.z() / 16.0F;
Vector4f vector4f = new Vector4f(f3, f4, f5, 1.0F);
vector4f.mul(matrix4f);
bufferIn
.setColor(red, green, blue, alpha)
.addVertex(vector4f.x(), vector4f.y(), vector4f.z())
.setUv(BasicModelPart$positiontexturevertex.textureU, BasicModelPart$positiontexturevertex.textureV)
.setLight(packedLightIn)
.setOverlay(packedOverlayIn)
.setNormal(f, f1, f2);
}
}
}
}
/**
* Returns the model renderer with the new texture parameters.
*/
public BasicModelPart setTextureSize(int textureWidthIn, int textureHeightIn) {
this.textureWidth = (float)textureWidthIn;
this.textureHeight = (float)textureHeightIn;
return this;
}
public BasicModelPart.ModelBox getRandomCube(Random randomIn) {
return this.cubeList.get(randomIn.nextInt(this.cubeList.size()));
}
@OnlyIn(Dist.CLIENT)
public static class ModelBox {
private final BasicModelPart.TexturedQuad[] quads;
public final float posX1;
public final float posY1;
public final float posZ1;
public final float posX2;
public final float posY2;
public final float posZ2;
public ModelBox(int texOffX, int texOffY, float x, float y, float z, float width, float height, float depth, float deltaX, float deltaY, float deltaZ, boolean mirorIn, float texWidth, float texHeight) {
this.posX1 = x;
this.posY1 = y;
this.posZ1 = z;
this.posX2 = x + width;
this.posY2 = y + height;
this.posZ2 = z + depth;
this.quads = new BasicModelPart.TexturedQuad[6];
float f = x + width;
float f1 = y + height;
float f2 = z + depth;
x = x - deltaX;
y = y - deltaY;
z = z - deltaZ;
f = f + deltaX;
f1 = f1 + deltaY;
f2 = f2 + deltaZ;
if (mirorIn) {
float f3 = f;
f = x;
x = f3;
}
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex7 = new BasicModelPart.PositionTextureVertex(x, y, z, 0.0F, 0.0F);
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex = new BasicModelPart.PositionTextureVertex(f, y, z, 0.0F, 8.0F);
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex1 = new BasicModelPart.PositionTextureVertex(f, f1, z, 8.0F, 8.0F);
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex2 = new BasicModelPart.PositionTextureVertex(x, f1, z, 8.0F, 0.0F);
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex3 = new BasicModelPart.PositionTextureVertex(x, y, f2, 0.0F, 0.0F);
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex4 = new BasicModelPart.PositionTextureVertex(f, y, f2, 0.0F, 8.0F);
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex5 = new BasicModelPart.PositionTextureVertex(f, f1, f2, 8.0F, 8.0F);
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex6 = new BasicModelPart.PositionTextureVertex(x, f1, f2, 8.0F, 0.0F);
float f4 = (float)texOffX;
float f5 = (float)texOffX + depth;
float f6 = (float)texOffX + depth + width;
float f7 = (float)texOffX + depth + width + width;
float f8 = (float)texOffX + depth + width + depth;
float f9 = (float)texOffX + depth + width + depth + width;
float f10 = (float)texOffY;
float f11 = (float)texOffY + depth;
float f12 = (float)texOffY + depth + height;
this.quads[2] = new BasicModelPart.TexturedQuad(new BasicModelPart.PositionTextureVertex[]{BasicModelPart$positiontexturevertex4, BasicModelPart$positiontexturevertex3, BasicModelPart$positiontexturevertex7, BasicModelPart$positiontexturevertex}, f5, f10, f6, f11, texWidth, texHeight, mirorIn, Direction.DOWN);
this.quads[3] = new BasicModelPart.TexturedQuad(new BasicModelPart.PositionTextureVertex[]{BasicModelPart$positiontexturevertex1, BasicModelPart$positiontexturevertex2, BasicModelPart$positiontexturevertex6, BasicModelPart$positiontexturevertex5}, f6, f11, f7, f10, texWidth, texHeight, mirorIn, Direction.UP);
this.quads[1] = new BasicModelPart.TexturedQuad(new BasicModelPart.PositionTextureVertex[]{BasicModelPart$positiontexturevertex7, BasicModelPart$positiontexturevertex3, BasicModelPart$positiontexturevertex6, BasicModelPart$positiontexturevertex2}, f4, f11, f5, f12, texWidth, texHeight, mirorIn, Direction.WEST);
this.quads[4] = new BasicModelPart.TexturedQuad(new BasicModelPart.PositionTextureVertex[]{BasicModelPart$positiontexturevertex, BasicModelPart$positiontexturevertex7, BasicModelPart$positiontexturevertex2, BasicModelPart$positiontexturevertex1}, f5, f11, f6, f12, texWidth, texHeight, mirorIn, Direction.NORTH);
this.quads[0] = new BasicModelPart.TexturedQuad(new BasicModelPart.PositionTextureVertex[]{BasicModelPart$positiontexturevertex4, BasicModelPart$positiontexturevertex, BasicModelPart$positiontexturevertex1, BasicModelPart$positiontexturevertex5}, f6, f11, f8, f12, texWidth, texHeight, mirorIn, Direction.EAST);
this.quads[5] = new BasicModelPart.TexturedQuad(new BasicModelPart.PositionTextureVertex[]{BasicModelPart$positiontexturevertex3, BasicModelPart$positiontexturevertex4, BasicModelPart$positiontexturevertex5, BasicModelPart$positiontexturevertex6}, f8, f11, f9, f12, texWidth, texHeight, mirorIn, Direction.SOUTH);
}
}
@OnlyIn(Dist.CLIENT)
static class PositionTextureVertex {
public final Vector3f position;
public final float textureU;
public final float textureV;
public PositionTextureVertex(float x, float y, float z, float texU, float texV) {
this(new Vector3f(x, y, z), texU, texV);
}
public BasicModelPart.PositionTextureVertex setTextureUV(float texU, float texV) {
return new BasicModelPart.PositionTextureVertex(this.position, texU, texV);
}
public PositionTextureVertex(Vector3f posIn, float texU, float texV) {
this.position = posIn;
this.textureU = texU;
this.textureV = texV;
}
}
@OnlyIn(Dist.CLIENT)
static class TexturedQuad {
public final BasicModelPart.PositionTextureVertex[] vertexPositions;
public final Vector3f normal;
public TexturedQuad(BasicModelPart.PositionTextureVertex[] positionsIn, float u1, float v1, float u2, float v2, float texWidth, float texHeight, boolean mirrorIn, Direction directionIn) {
this.vertexPositions = positionsIn;
float f = 0.0F / texWidth;
float f1 = 0.0F / texHeight;
positionsIn[0] = positionsIn[0].setTextureUV(u2 / texWidth - f, v1 / texHeight + f1);
positionsIn[1] = positionsIn[1].setTextureUV(u1 / texWidth + f, v1 / texHeight + f1);
positionsIn[2] = positionsIn[2].setTextureUV(u1 / texWidth + f, v2 / texHeight - f1);
positionsIn[3] = positionsIn[3].setTextureUV(u2 / texWidth - f, v2 / texHeight - f1);
if (mirrorIn) {
int i = positionsIn.length;
for(int j = 0; j < i / 2; ++j) {
BasicModelPart.PositionTextureVertex BasicModelPart$positiontexturevertex = positionsIn[j];
positionsIn[j] = positionsIn[i - 1 - j];
positionsIn[i - 1 - j] = BasicModelPart$positiontexturevertex;
}
}
this.normal = directionIn.step();
if (mirrorIn) {
this.normal.mul(-1.0F, 1.0F, 1.0F);
}
}
}
}

View File

@ -1,166 +0,0 @@
package com.r3944realms.leashedplayer.content.entities;
import com.r3944realms.leashedplayer.content.entities.props.ChainLeashable;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.protocol.game.ClientGamePacketListener;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.server.level.ServerEntity;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.util.Mth;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.decoration.BlockAttachedEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.WallBlock;
import net.minecraft.world.level.gameevent.GameEvent;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
public class ChainTieEntity extends BlockAttachedEntity {
public ChainTieEntity(EntityType<? extends BlockAttachedEntity> type, Level worldIn, BlockPos hangingPositionIn) {
super(type, worldIn, hangingPositionIn);
this.setPos(hangingPositionIn.getX() + 0.5D, hangingPositionIn.getY(), hangingPositionIn.getZ() + 0.5D);
}
public ChainTieEntity(EntityType<? extends BlockAttachedEntity> hangingEntityEntityType, Level level) {
super(hangingEntityEntityType, level);
}
public void playPlacementSound() {
this.playSound(SoundEvents.ARMOR_EQUIP_CHAIN.value(), 1.0F, 1.0F);
}
public static ChainTieEntity createTie(Level worldIn, BlockPos fence) {
ChainTieEntity entityChainTie = new ChainTieEntity(ModEntityRegister.CHAIN_TIE.get(), worldIn, fence);
worldIn.addFreshEntity(entityChainTie);
entityChainTie.playPlacementSound();
return entityChainTie;
}
public static ChainTieEntity getOrCreateKnot(Level pLevel, BlockPos pPos) {
int i = pPos.getX();
int j = pPos.getY();
int k = pPos.getZ();
for (ChainTieEntity chainTieEntity : pLevel.getEntitiesOfClass(
ChainTieEntity.class, new AABB((double)i - 1.0, (double)j - 1.0, (double)k - 1.0, (double)i + 1.0, (double)j + 1.0, (double)k + 1.0)
)) {
if (chainTieEntity.getPos().equals(pPos)) {
return chainTieEntity;
}
}
ChainTieEntity chainTieEntity = createTie(pLevel, pPos);
pLevel.addFreshEntity(chainTieEntity);
return chainTieEntity;
}
@Override
protected void recalculateBoundingBox() {
this.setPosRaw(
this.pos.getX() + 0.5D,
this.pos.getY() + 0.5D,
this.pos.getZ() + 0.5D
);
double xSize = 0.3D;
double ySize = 0.875D;
this.setBoundingBox(
new AABB(
this.getX() - xSize,
this.getY() - 0.5,
this.getZ() - xSize,
this.getX() + xSize,
this.getY() + ySize - 0.5,
this.getZ() + xSize
)
);
}
@Override
public @NotNull InteractionResult interact(@NotNull Player pPlayer, @NotNull InteractionHand pHand) {
if (this.level().isClientSide) {
return InteractionResult.SUCCESS;
} else {
boolean flag = false;
List<ChainLeashable> list = ChainLeashable.leashableInArea(this.level(), this.getPos(), chainLeashable -> {
Entity entity = chainLeashable.getLeashHolder();
return entity == pPlayer || entity == this;
});
for (ChainLeashable ChainLeashable : list) {
if (ChainLeashable.getLeashHolder() == pPlayer) {
ChainLeashable.setLeashedTo(this, true);
flag = true;
}
}
boolean flag1 = false;
if (!flag) {
this.discard();
if (pPlayer.getAbilities().instabuild) {
for (ChainLeashable ChainLeashable : list) {
if (ChainLeashable.isLeashed() && ChainLeashable.getLeashHolder() == this) {
ChainLeashable.dropLeash(true, false);
flag1 = true;
}
}
}
}
if (flag || flag1) {
this.gameEvent(GameEvent.BLOCK_ATTACH, pPlayer);
}
return InteractionResult.CONSUME;
}
}
@Override
public boolean shouldRenderAtSqrDistance(double distance) {
return distance < 1024.0D;
}
@Override
public boolean survives() {
return this.level().getBlockState(this.pos).getBlock() instanceof WallBlock;
}
@Override
public void dropItem(@Nullable Entity pEntity) {
this.playSound(SoundEvents.ARMOR_EQUIP_CHAIN.value(), 1.0F, 1.0F);
}
@Override
protected void defineSynchedData(SynchedEntityData.@NotNull Builder pBuilder) {
}
@Override
public void setPos(double x, double y, double z) {
super.setPos(Mth.floor(x) + 0.5D, Mth.floor(y) + 0.5D, Mth.floor(z) + 0.5D);
}
@Override
public @NotNull Packet<ClientGamePacketListener> getAddEntityPacket(@NotNull ServerEntity pEntity) {
return new ClientboundAddEntityPacket(this, 0, this.getPos());
}
@Override
public @NotNull Vec3 getRopeHoldPosition(float pPartialTicks) {
return this.getPosition(pPartialTicks).add(0.0, 0.2, 0.0);
}
@Override
public ItemStack getPickResult() {
return new ItemStack(Items.CHAIN);
}
}

View File

@ -1,4 +0,0 @@
package com.r3944realms.leashedplayer.client.models;
public class ChainTieModel extends BasicEnti{
}

View File

@ -1,210 +0,0 @@
package com.r3944realms.leashedplayer.content.entities.props;
import com.mojang.datafixers.util.Either;
import net.minecraft.core.BlockPos;
import net.minecraft.network.protocol.game.ClientboundSetEntityLinkPacket;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.AABB;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import java.util.function.Predicate;
public interface ChainLeashable {
String LEASH_TAG = "chain_leash";
@Nullable
ChainLeashable.ChainData getLeashData();
void setLeashData(@Nullable ChainLeashable.ChainData pLeashData);
default boolean isLeashed() {
return this.getLeashData() != null && this.getLeashData().leashHolder != null;
}
default boolean mayBeLeashed() {
return this.getLeashData() != null;
}
default boolean canHaveALeashAttachedToIt() {
return this.canBeLeashed() && !this.isLeashed();
}
default boolean canBeLeashed() {
return true;
}
default boolean handleLeashAtDistance(Entity pLeashHolder, float pDistance) {
return true;
}
default void leashTooFarBehaviour() {
this.dropLeash(true, true);
}
default void closeRangeLeashBehaviour(Entity pEntity) {
}
default void elasticRangeLeashBehaviour(Entity pLeashHolder, float pDistance) {
legacyElasticRangeLeashBehaviour((Entity & ChainLeashable)this, pLeashHolder, pDistance);
}
@Nullable
default Entity getLeashHolder() {
return getLeashHolder((Entity & ChainLeashable)this);
}
private static <E extends Entity & ChainLeashable> void legacyElasticRangeLeashBehaviour(E pEntity, Entity pLeashHolder, float pDistance) {
double d0 = (pLeashHolder.getX() - pEntity.getX()) / (double)pDistance;
double d1 = (pLeashHolder.getY() - pEntity.getY()) / (double)pDistance;
double d2 = (pLeashHolder.getZ() - pEntity.getZ()) / (double)pDistance;
pEntity.setDeltaMovement(
pEntity.getDeltaMovement().add(Math.copySign(d0 * d0 * 0.4, d0), Math.copySign(d1 * d1 * 0.4, d1), Math.copySign(d2 * d2 * 0.4, d2))
);
}
@Nullable
private static <E extends Entity & ChainLeashable> Entity getLeashHolder(E pEntity) {
ChainLeashable.ChainData chainLeashable$chaindata = pEntity.getLeashData();
if (chainLeashable$chaindata == null) {
return null;
} else {
if (chainLeashable$chaindata.delayedLeashHolderId != 0 && pEntity.level().isClientSide) {
Entity entity = pEntity.level().getEntity(chainLeashable$chaindata.delayedLeashHolderId);
if (entity instanceof Entity) {
chainLeashable$chaindata.setLeashHolder(entity);
}
}
return chainLeashable$chaindata.leashHolder;
}
}
default void setLeashedTo(Entity pLeashHolder, boolean pBroadcastPacket) {
setLeashedTo((Entity & ChainLeashable)this, pLeashHolder, pBroadcastPacket);
}
static List<ChainLeashable> leashableInArea(Level pLevel, BlockPos pPos, Predicate<ChainLeashable> pPredicate) {
double d0 = 7.0;
int i = pPos.getX();
int j = pPos.getY();
int k = pPos.getZ();
AABB aabb = new AABB((double)i - 7.0, (double)j - 7.0, (double)k - 7.0, (double)i + 7.0, (double)j + 7.0, (double)k + 7.0);
return pLevel.getEntitiesOfClass(Entity.class, aabb, p_353023_ -> p_353023_ instanceof ChainLeashable chainLeashable && pPredicate.test(chainLeashable)).stream().map(ChainLeashable.class::cast).toList();
}
private static <E extends Entity & ChainLeashable> void setLeashedTo(E pEntity, Entity pLeashHolder, boolean pBroadcastPacket) {
ChainLeashable.ChainData chainLeashable$chaindata = pEntity.getLeashData();
if (chainLeashable$chaindata == null) {
chainLeashable$chaindata = new ChainLeashable.ChainData(pLeashHolder);
pEntity.setLeashData(chainLeashable$chaindata);
} else {
chainLeashable$chaindata.setLeashHolder(pLeashHolder);
}
if (pBroadcastPacket && pEntity.level() instanceof ServerLevel serverlevel) {
//TODO自写Packet ClientboundSetEntityLinkPacket(pEntity, pLeashHolder)
serverlevel.getChunkSource().broadcast(pEntity, new ClientboundSetEntityLinkPacket(pEntity, pLeashHolder));
}
if (pEntity.isPassenger()) {
pEntity.stopRiding();
}
}
default void dropLeash(boolean pBroadcastPacket, boolean pDropItem) {
dropLeash((Entity & ChainLeashable)this, pBroadcastPacket, pDropItem);
}
private static <E extends Entity & ChainLeashable> void dropLeash(E pEntity, boolean pBroadcastPacket, boolean pDropItem) {
ChainLeashable.ChainData chainLeashable$chaindata = pEntity.getLeashData();
if (chainLeashable$chaindata != null && chainLeashable$chaindata.leashHolder != null) {
pEntity.setLeashData(null);
if (!pEntity.level().isClientSide && pDropItem) {
pEntity.spawnAtLocation(Items.CHAIN);
}
if (pBroadcastPacket && pEntity.level() instanceof ServerLevel serverlevel) {
serverlevel.getChunkSource().broadcast(pEntity, new ClientboundSetEntityLinkPacket(pEntity, null));
}
}
}
static <E extends Entity & ChainLeashable> void tickLeash(E pEntity) {
ChainLeashable.ChainData chainLeashable$chaindata = pEntity.getLeashData();
if (chainLeashable$chaindata != null && chainLeashable$chaindata.delayedLeashInfo != null) {
restoreLeashFromSave(pEntity, chainLeashable$chaindata);
}
if (chainLeashable$chaindata != null && chainLeashable$chaindata.leashHolder != null) {
if (!pEntity.isAlive() || !chainLeashable$chaindata.leashHolder.isAlive()) {
dropLeash(pEntity, true, true);
}
Entity entity = pEntity.getLeashHolder();
if (entity != null && entity.level() == pEntity.level()) {
float f = pEntity.distanceTo(entity);
if (!pEntity.handleLeashAtDistance(entity, f)) {
return;
}
if ((double)f > 10.0) {
pEntity.leashTooFarBehaviour();
} else if ((double)f > 6.0) {
pEntity.elasticRangeLeashBehaviour(entity, f);
pEntity.checkSlowFallDistance();
} else {
pEntity.closeRangeLeashBehaviour(entity);
}
}
}
}
private static <E extends Entity & ChainLeashable> void restoreLeashFromSave(E pEntity, ChainLeashable.ChainData pLeashData) {
if (pLeashData.delayedLeashInfo != null && pEntity.level() instanceof ServerLevel serverlevel) {
Optional<UUID> optional1 = pLeashData.delayedLeashInfo.left();
Optional<BlockPos> optional = pLeashData.delayedLeashInfo.right();
if (optional1.isPresent()) {
Entity entity = serverlevel.getEntity(optional1.get());
if (entity != null) {
setLeashedTo(pEntity, entity, true);
return;
}
} else if (optional.isPresent()) {
setLeashedTo(pEntity, LeashFenceKnotEntity.getOrCreateKnot(serverlevel, optional.get()), true);
return;
}
if (pEntity.tickCount > 100) {
pEntity.spawnAtLocation(Items.LEAD);
pEntity.setLeashData(null);
}
}
}
final class ChainData {
public int delayedLeashHolderId;
@Nullable
public Entity leashHolder;
@Nullable
public Either<UUID, BlockPos> delayedLeashInfo;
ChainData(@org.jetbrains.annotations.Nullable Either<UUID, BlockPos> pDelayedLeashInfo) {
this.delayedLeashInfo = pDelayedLeashInfo;
}
public ChainData(@org.jetbrains.annotations.Nullable Entity pLeashHolder) {
this.leashHolder = pLeashHolder;
}
ChainData(int pDelayedLeashInfoId) {
this.delayedLeashHolderId = pDelayedLeashInfoId;
}
public void setLeashHolder(Entity pLeashHolder) {
this.leashHolder = pLeashHolder;
this.delayedLeashInfo = null;
this.delayedLeashHolderId = 0;
}
}
}

View File

@ -1,70 +1,25 @@
# 版本 0.0.4.0.4 提前介绍c[没有BUG的话TeaCon最终版本将会是0.0.4] 【注意:本解釋簡繁混寫,因爲趕時間,所以並不怎麽規範,請諒解】
## 简介
现在开始你可以用拴绳拴住玩家,也可以拴住自己了,不如尝试拴住彼此来通关我的世界吧(
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
Installation information
=======
This template repository can be directly cloned to get you started with a new
mod. Simply create a new repository cloned from this one, by following the
instructions provided by [GitHub](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template).
你可以:
1. 拴绳可以拴住玩家
2. 在无任何拴住实体的情况下用拴绳对准栅栏可以拴住自己
3. 可以用指令来获取和调整玩家实体的拴绳的长度和设置拴绳数据实体
4. 目前有游戏规则来决定被栓玩家是否在传送时能随拴绳持有者一起传送
## 配置文件
1. 可改变指令前命名空间和关闭命名空间
2. 修改命令拴绳的可设置的长度范围
3. 设置拴绳在达到多少倍的拴绳长度后掉落
4. 拴绳箭最大存活时间
Once you have your clone, simply open the repository in the IDE of your choice. The usual recommendation for an IDE is either IntelliJ IDEA or Eclipse.
## 新物品 和 实体
### 拴绳箭 [有普通和荧光和药水三种箭矢]
获得飞一样的感觉(操作不当可能会摔死
+ 拴绳箭可以拴其它可拴LivingEntity了
### 紫水晶剪刀
剪断拴绳链接,在发射器里可使用,对自己也可使用,但耗费更多耐久
#### 射中实体时会将射击者拴绳绑定在改实体上该实体父类必须是有LivingEntity类型同时拴绳箭会以普通的箭矢掉落
#### 射中栅栏时,会自动将玩家拴在上面 ,同时拴绳箭会以普通的箭矢掉落
#### 在地面上的箭可以通过按Shift靠近来捡起如果捡起实体为发射箭矢玩家则直接获取拴绳箭矢如果捡起者为非发射者则成为发送者的拴绳持有者并获得普通箭矢
If at any point you are missing libraries in your IDE, or you've run into problems you can
run `gradlew --refresh-dependencies` to refresh the local cache. `gradlew clean` to reset everything
{this does not affect your code} and then start the process again.
## 新药水和效果
### 效果
* 禁拴 - 拥有此BUFF的LivingEntity将无法被拴住
### 药水
* 禁拴药水
Mapping Names:
============
By default, the MDK is configured to use the official mapping names from Mojang for methods and fields
in the Minecraft codebase. These names are covered by a specific license. All modders should be aware of this
license. For the latest license text, refer to the mapping file itself, or the reference copy here:
https://github.com/NeoForged/NeoForm/blob/main/Mojang.md
## 指令
可能会因为配置中差异性导致前缀'lp'变为其它或取消其存在,以模组配置文件为准
* `/lp leash length [<玩家>] set <长度> ` - 设置该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 ,<长度> 为在 5 ~ 1024之间的浮点数 ]
* `/lp leash length [<玩家>] [get]` - 顯示该玩家的拴绳长度 [ 如果<玩家>为空则代表执行对象是自己 , [get] 可不写]
* `/lp leash data [<玩家>] set <實體>/<方塊坐標>` - 設置該玩家的的拴繩數據實體設置為<實體>/位於<方塊坐標>處的柵欄上的拴繩結實體
* `/lp leash data [<玩家>] [get]` - 顯示该玩家的拴绳數據 [ 如果<玩家>为空则代表执行对象是自己 , [get] 可不写]
* `/lp leash clear [<玩家[可多个对象]>] ` - 清除該玩家的的拴繩數據實體 [ 如果<玩家>为空则代表执行对象是自己 ]
* `/lp motion [<实体[可多个对象]>] add/set/multiply <x> <y> <z>` - 给实体添加/设置/倍乘 加速度
* `/lp talkArea <[<玩家[可多个对象]>]> set/setPreference/unlimited/currentConfig <数值>` - 设置玩家聊天可见半径/设置半径预期/应用预期/取消限制/获取目前配置
* `/lp tick ...` - 用法同原版Tick但权限降为2只用于调试切勿滥用后期考虑可能写成区域性的
* `/lp debug ...` - Debug指令未来可能会移除
## 游戏规则
* `LP.TeleportWithLeashedPlayers` - 此規則啓用后, 被栓玩家將會随玩家拴绳持有者一起传送 [默认值: True]
* `LP.CreateLeashFenceKnotEntityIfAbsent` - 此規則啓用后, 在設置 leashData 時,如果對應方塊坐標上的柵欄沒有拴繩結則會自動創建這個實體並綁定 [默认值: True]
* `LP.KeepLeashNotDropTime` - 此规则决定,当拴绳关系创建时一段时间里,即是距离已经达到了断裂距离,也保持其不断裂 [默认值: 240ticks ,可设置范围[80, 1200]ticks]
* `LP.DefaultTalkArea` - 此规则决定,聊天半径最小正值 [默认值: -1]
* `LP.OpenTOPNeededModeWhenScreenIsNotNull` - 此规则决定,是否在在打开 屏幕{除Top的NoteGui 和 聊天GUI外} 情况下改变Top的显示模式为NEEDED [默认值: true]
* `LP.CanCommonPlayerChangeSelfTalkArea` - 此规则决定,是否普通玩家可以修改自己的聊天可见区域 [默认值: true]
## 联动内容
# 与Nestle 的 贴贴拴绳箭
射中实体生成贴贴拴绳实体并绑定在一起,解除需用到贴贴拴绳(不太好个人觉得)
Additional Resources:
==========
Community Documentation: https://docs.neoforged.net/
NeoForged Discord: https://discord.neoforged.net/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 382 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 404 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 498 B

View File

@ -1,8 +0,0 @@
{
"credit": "Made with Blockbench",
"parent": "minecraft:item/generated",
"textures": {
"1": "leashedplayer:item/neoforge",
"particle": "leashedplayer:item/neoforge"
}
}

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 256 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 B

View File

@ -1,6 +1,9 @@
MIT License
Copyright (c) 2024 LeashedPlayer Project
Copyright (c) 2023 NeoForged project
This license applies to the template files as supplied by github.com/NeoForged/MDK
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

View File

@ -1,9 +1,7 @@
plugins {
id 'java-library'
id 'eclipse'
id 'idea'
id 'maven-publish'
id 'net.neoforged.gradle.userdev' version '7.0.145'
id 'net.neoforged.gradle.userdev' version '7.0.184'
}
tasks.named('wrapper', Wrapper).configure {
@ -19,19 +17,6 @@ version = mod_version
group = mod_group_id
repositories {
maven {
// location of the maven that hosts JEI files since January 2023
name = "Jared's maven"
url = "https://maven.blamejared.com/"
}
maven {
// location of a maven mirror for JEI files, as a fallback
name = "ModMaven"
url = "https://modmaven.dev"
}
maven { // TOP
url "https://maven.k-4u.nl"
}
mavenLocal()
}
@ -67,26 +52,27 @@ runs {
client {
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
server {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
argument '--nogui'
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
systemProperty 'forge.enabledGameTestNamespaces', project.mod_id
systemProperty 'neoforge.enabledGameTestNamespaces', project.mod_id
}
data {
clientData {
// example of overriding the workingDirectory set in configureEach above, uncomment if you want to use it
// workingDirectory project.file('run-data')
systemProperty('gradle.task', 'runData')
// Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
programArguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
arguments.addAll '--mod', project.mod_id, '--all', '--output', file('src/generated/resources/').getAbsolutePath(), '--existing', file('src/main/resources/').getAbsolutePath()
}
}
@ -100,7 +86,9 @@ sourceSets.main.resources { srcDir 'src/generated/resources' }
configurations {
runtimeClasspath.extendsFrom localRuntime
}
minecraft {
accessTransformers.file("src/main/resources/META-INF/accesstransformer.cfg")
}
dependencies {
// Specify the version of Minecraft to use.
// Depending on the plugin applied there are several options. We will assume you applied the userdev plugin as shown above.
@ -109,14 +97,7 @@ dependencies {
// And its provides the option to then use net.minecraft as the group, and one of; client, server or joined as the module name, plus the game version as version.
// For all intends and purposes: You can treat this dependency as if it is a normal library you would use.
implementation "net.neoforged:neoforge:${neo_version}"
compileOnly "mcjty.theoneprobe:theoneprobe:${top_version}"
runtimeOnly("mezz.jei:jei-${mc_version}-neoforge:${jei_version}")
// compile against the JEI API but do not include it at runtime
compileOnly("mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}")
compileOnly(files("Resource/nestle-0.1.1.jar"))
runtimeOnly(files("Resource/nestle-0.1.1.jar"))
// at runtime, use the full JEI jar for NeoForge
// compileOnly("mezz.jei:jei-${mc_version}-neoforge-api:${jei_version}")
// Example optional mod dependency with JEI
// The JEI API is declared for compile time use, while the full JEI artifact is used at runtime
// compileOnly "mezz.jei:jei-${mc_version}-common-api:${jei_version}"
@ -176,25 +157,13 @@ publishing {
maven {
url "file://${project.projectDir}/repo"
}
// maven {
// // location of the maven that hosts JEI files since January 2023
// name = "Jared's maven"
// url = "https://maven.blamejared.com/"
// }
// maven {
// // location of a maven mirror for JEI files, as a fallback
// name = "ModMaven"
// url = "https://modmaven.dev"
// }
}
}
tasks.withType(JavaCompile).configureEach {
options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
}
minecraft {
accessTransformers.file("src/main/resources/META-INF/accesstransformer.cfg")
}
// IDEA no longer automatically downloads sources/javadoc jars for dependencies, so we need to explicitly enable the behavior.
idea {
module {

View File

@ -1,30 +1,29 @@
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
org.gradle.jvmargs=-Xmx8G
org.gradle.daemon=false
org.gradle.debug=false
org.gradle.jvmargs=-Xmx3G
org.gradle.daemon=true
org.gradle.parallel=true
org.gradle.caching=false
org.gradle.configuration-cache=false
#read more on this at https://github.com/neoforged/NeoGradle/blob/NG_7.0/README.md#apply-parchment-mappings
# you can also find the latest versions at: https://parchmentmc.org/docs/getting-started
neogradle.subsystems.parchment.minecraftVersion=1.21
neogradle.subsystems.parchment.mappingsVersion=2024.07.28
neogradle.subsystems.parchment.minecraftVersion=1.21.4
neogradle.subsystems.parchment.mappingsVersion=2025.03.23
# Environment Properties
# You can find the latest versions here: https://projects.neoforged.net/neoforged/neoforge
# The Minecraft version must agree with the Neo version to get a valid artifact
minecraft_version=1.21
minecraft_version=1.21.5
# The Minecraft version range can use any release version of Minecraft as bounds.
# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly
# as they do not follow standard versioning conventions.
minecraft_version_range=[1.21,1.22)
minecraft_version_range=[1.21.5]
# The Neo version must agree with the Minecraft version to get a valid artifact
neo_version=21.0.157
neo_version=21.5.30-beta
# The Neo version range can use any version of Neo as bounds
neo_version_range=[21.0.0-beta,)
neo_version_range=[21.5.30-beta,)
# The loader version range can only use the major version of FML as bounds
loader_version_range=[4,)
top_version = 1.21_neo-12.0.4-6
#jei_setting
jei_version=19.8.2.99
mc_version=1.21
loader_version_range=[1,)
## Mod Properties
# The unique mod identifier for the mod. Must be lowercase in English locale. Must fit the regex [a-z][a-z0-9_]{1,63}
@ -35,7 +34,7 @@ mod_name=Leashed Player
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT
# The mod version. See https://semver.org/
mod_version=0.0.4.0.4
mod_version=1.21.5_0.0.4.0.4.1
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html

Binary file not shown.

View File

@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.9-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.12-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME

0
gradlew vendored Executable file → Normal file
View File

188
gradlew.bat vendored
View File

@ -1,94 +1,94 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@rem SPDX-License-Identifier: Apache-2.0
@rem
@if "%DEBUG%"=="" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
echo. 1>&2
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
echo. 1>&2
echo Please set the JAVA_HOME variable in your environment to match the 1>&2
echo location of your Java installation. 1>&2
goto fail
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
if %ERRORLEVEL% equ 0 goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
set EXIT_CODE=%ERRORLEVEL%
if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -7,7 +7,5 @@ pluginManagement {
}
plugins {
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.8.0'
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
}
include 'leashedplayer_1_21_3'

View File

@ -1,16 +0,0 @@
// 1.21 2024-11-25T23:55:52.7726677 Item Models: leashedplayer
766c487fbf0c59e9045eeaf81daf583eb679b0e1 assets/leashedplayer/models/item/amethyst_shears.json
5846df9d85726428905701120ef34c9324c20faf assets/leashedplayer/models/item/bow_lra_pulling_0.json
845a7316b86e26f88c6932d4ef2656126503727a assets/leashedplayer/models/item/bow_lra_pulling_1.json
5bd1f9f28b91005c587f1c38fb77cd19b59495e3 assets/leashedplayer/models/item/bow_lra_pulling_2.json
90909de0fcb2a6b0b9731bb998f8d866841de6d2 assets/leashedplayer/models/item/bow_nra_pulling_0.json
de6fed69522a94812c66ba1864ae6df7465aad9c assets/leashedplayer/models/item/bow_nra_pulling_1.json
1e34de6579d5c250eff9871e589c584d888c3c6d assets/leashedplayer/models/item/bow_nra_pulling_2.json
83946f4d60d0fb1758d6553c36330506c8e48ada assets/leashedplayer/models/item/crossbow_leash_rope_arrow.json
7d9d1678faf41b58d2934d0335f700e17c372c10 assets/leashedplayer/models/item/crossbow_nestle_rope_arrow.json
bb0d76077719c83c8a8bd4346a24ea1766175125 assets/leashedplayer/models/item/fabric.json
63ec6c618a3a23eab4cab9c52d7d3250de9b516e assets/leashedplayer/models/item/kid_spawn_egg.json
114d3cc5832ef047403114504483c6f3ea07e77c assets/leashedplayer/models/item/leash_rope_arrow.json
f77241714f5233f127eee3c7521b448add1eaad2 assets/leashedplayer/models/item/nestle_rope_arrow.json
c4748995a5fe190d20e3bd16f4b2244164ec0f83 assets/leashedplayer/models/item/spectral_leash_rope_arrow.json
c4ef06f3162fe85f152c5b4a25ecdb4c2c56f945 assets/leashedplayer/models/item/tipped_leash_rope_arrow.json

View File

@ -1,3 +1,3 @@
// 1.21 2024-11-05T23:00:18.5223698 Registries
// 1.21.5 2025-03-29T16:40:03.0405054 Registries
f2536789df7f06362718a59ba4a96890e2f9b8aa data/leashedplayer/jukebox_song/what_does_the_fox_say.json
6f79a674215db9f9d2820b1c7f052c60ce729fee data/leashedplayer/painting_variant/group_photo.json
84106976f4f71012fc5bd1784303a0d135623c77 data/leashedplayer/painting_variant/group_photo.json

View File

@ -1,6 +1,7 @@
// 1.21 2024-11-25T23:24:58.9769291 Tags for minecraft:item mod id leashedplayer
// 1.21.5 2025-03-29T16:40:02.9875592 Tags for minecraft:item mod id leashedplayer
84707301f1fe2490a899deb51302d413cfff5a89 data/c/tags/item/tools/shear.json
a91f0f4956d65c981d76c9f41de5272b2e0b5786 data/minecraft/tags/item/arrows.json
bde6ca31173d1f22d5f6fe355dc90c9faa35b239 data/minecraft/tags/item/amethyst_tool_materials.json
63e4ad58dc8397171f84264d53dfe4fb503c7b1e data/minecraft/tags/item/arrows.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/durability.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/mining.json
84707301f1fe2490a899deb51302d413cfff5a89 data/minecraft/tags/item/enchantable/vanishing.json

View File

@ -1,2 +1,2 @@
// 1.21 2024-12-15T17:40:40.0369665 Languages: en_us for mod: leashedplayer
d88b57505584fdfde48b00652789cb078b469830 assets/leashedplayer/lang/en_us.json
// 1.21.5 2025-03-29T16:40:03.0435015 Languages: en_us for mod: leashedplayer
2c7f061dfc276db13135adce15c68cfc145ccf37 assets/leashedplayer/lang/en_us.json

View File

@ -1 +1 @@
// 1.21 2024-10-23T13:15:06.1052755 Tags for minecraft:block mod id leashedplayer
// 1.21.5 2025-03-29T16:40:03.0112992 Tags for minecraft:block mod id leashedplayer

View File

@ -1,2 +1,2 @@
// 1.21 2024-11-05T22:44:13.1754334 Sound Definitions
// 1.21.5 2025-03-29T16:40:03.0510463 Sound Definitions
81f1cc9f404c2670bf7cc679107177ffb0b48c77 assets/leashedplayer/sounds.json

View File

@ -1,2 +1,2 @@
// 1.21 2024-10-23T13:15:06.1052755 Tags for minecraft:painting_variant mod id leashedplayer
// 1.21.5 2025-03-29T16:40:03.0163693 Tags for minecraft:painting_variant mod id leashedplayer
e081a053d7c2f2d3238cf38436185ef23d234505 data/minecraft/tags/painting_variant/placeable.json

View File

@ -1,2 +1,2 @@
// 1.21 2024-11-03T11:56:02.1150382 Languages: lzh for mod: leashedplayer
a9b5a3116c6381872e174909553b8dac080dede8 assets/leashedplayer/lang/lzh.json
// 1.21.5 2025-03-29T16:40:02.9987109 Languages: lzh for mod: leashedplayer
7536eb6d1c69695c06ebb9da5b57a391174b02cb assets/leashedplayer/lang/lzh.json

View File

@ -1,15 +0,0 @@
// 1.21 2024-11-26T16:39:25.2156177 Recipes
13ebe9a580731296eb10c05d1844657d58e07cc1 data/leashedplayer/advancement/recipes/misc/amethyst_shears.json
1b45d1ad8dc73f1787c97777ad13d9771c9e0ad1 data/leashedplayer/advancement/recipes/misc/leash_rope_arrow.json
a89ec35176f84a580181c5839d6f249e482a65a9 data/leashedplayer/advancement/recipes/misc/nestle_rope_arrow.json
04bd2d8a0c7288776da2119eb9a9f9cf694be1b6 data/leashedplayer/recipe/amethyst_shears.json
974d74538b3e172946f2e169036b453b6eb6bc0a data/leashedplayer/recipe/leash_rope_arrow.json
093bae9d2e24a901ce8450d802ad5d142d1d74ed data/leashedplayer/recipe/nestle_rope_arrow.json
8de575d00dcc51fce8ebfa2542e193ffda1bafa8 data/minecraft/advancement/recipes/misc/nestle_rope_arrow_with_leash_rope_arrow.json
c0e05f359296d3e28573fa1b205ac44736376622 data/minecraft/advancement/recipes/misc/spectral_leash_rope_arrow_with_glowstone_dust.json
131fcbef603bfde7204d8e1ad15e4544696926bf data/minecraft/advancement/recipes/misc/spectral_leash_rope_arrow_with_leash_rope_arrow.json
fb35ec6670c3711b7e1d0e96f39ad914cb2419ae data/minecraft/recipe/nestle_rope_arrow_with_leash_rope_arrow.json
bb5909aa91d878c8f0ef9999881cfe89532509dd data/minecraft/recipe/spectral_leash_rope_arrow_with_glowstone_dust.json
a1381da885fbedec01243c78afbb0a50ca803ee4 data/minecraft/recipe/spectral_leash_rope_arrow_with_leash_rope_arrow.json
4dffdb7a2a537b409d1ec2630d9b74300649e1d8 data/minecraft/recipe/tipped_leash_rope_arrow_a.json
7810cb5e8c165f479fc6cd030bd1cf7bc508993b data/minecraft/recipe/tipped_leash_rope_arrow_b.json

View File

@ -1,2 +1,2 @@
// 1.21 2024-12-15T17:48:33.0549249 Languages: zh_cn for mod: leashedplayer
72797aa9107025df7d91eaff3ea51745d410261c assets/leashedplayer/lang/zh_cn.json
// 1.21.5 2025-03-29T16:40:03.0306291 Languages: zh_cn for mod: leashedplayer
f7bcf89907a8ca5f575e4b519d53cd0628bb1e6b assets/leashedplayer/lang/zh_cn.json

View File

@ -0,0 +1,11 @@
// 1.21.5 2025-03-29T16:40:03.0040344 LeashedPlayer Recipes
13ebe9a580731296eb10c05d1844657d58e07cc1 data/leashedplayer/advancement/recipes/misc/amethyst_shears.json
1b45d1ad8dc73f1787c97777ad13d9771c9e0ad1 data/leashedplayer/advancement/recipes/misc/leash_rope_arrow.json
a26d63c2360b32df0b636a5dec96dd919139e022 data/leashedplayer/advancement/recipes/misc/spectral_leash_rope_arrow.json
af1f65626735f1001426e0984217139e15649725 data/leashedplayer/recipe/amethyst_shears.json
db45be6e2bbddc49e60a6c1b12e2ef44afad30d8 data/leashedplayer/recipe/leash_rope_arrow.json
db37bd69a700eaae69bff48c77ed49ca55fb9bf1 data/leashedplayer/recipe/spectral_leash_rope_arrow.json
935d8732ca65dd73e4668a197cda60480053fbcd data/minecraft/advancement/recipes/misc/leash_rope_arrow_shape.json
5811048f18527a45b36b8b927de4e5d7c12a75eb data/minecraft/recipe/leash_rope_arrow_shape.json
4dffdb7a2a537b409d1ec2630d9b74300649e1d8 data/minecraft/recipe/tipped_leash_rope_arrow_a.json
7810cb5e8c165f479fc6cd030bd1cf7bc508993b data/minecraft/recipe/tipped_leash_rope_arrow_b.json

View File

@ -0,0 +1,25 @@
// 1.21.5 2025-03-29T16:40:03.0481 Model Definitions - leashedplayer
d213db38f45b911f2023c83e15b018371a630ae0 assets/leashedplayer/items/amethyst_shears.json
bc53c9feb22db83882974d60456bef0d3ef3ef5e assets/leashedplayer/items/fabric.json
e4e426067245e93d282a3d953c420fca04c23f3d assets/leashedplayer/items/leash_rope_arrow.json
6151e1b11ec884d511b2fd595e39c9f12674e824 assets/leashedplayer/items/spectral_leash_rope_arrow.json
1b914911c9077563701e9ac4b7f8c425f6eff4ee assets/leashedplayer/items/tipped_leash_rope_arrow.json
766c487fbf0c59e9045eeaf81daf583eb679b0e1 assets/leashedplayer/models/item/amethyst_shears.json
5846df9d85726428905701120ef34c9324c20faf assets/leashedplayer/models/item/bow_lra_pulling_0.json
845a7316b86e26f88c6932d4ef2656126503727a assets/leashedplayer/models/item/bow_lra_pulling_1.json
5bd1f9f28b91005c587f1c38fb77cd19b59495e3 assets/leashedplayer/models/item/bow_lra_pulling_2.json
83946f4d60d0fb1758d6553c36330506c8e48ada assets/leashedplayer/models/item/crossbow_leash_rope_arrow.json
bb0d76077719c83c8a8bd4346a24ea1766175125 assets/leashedplayer/models/item/fabric.json
114d3cc5832ef047403114504483c6f3ea07e77c assets/leashedplayer/models/item/leash_rope_arrow.json
c4748995a5fe190d20e3bd16f4b2244164ec0f83 assets/leashedplayer/models/item/spectral_leash_rope_arrow.json
ba065b1a88d82f95e10d026bf7bfdac7923de24c assets/leashedplayer/models/item/tipped_leash_rope_arrow.json
fe3d4b8fd83f9ba4e2a951ec2e23ea98a347c2cc assets/minecraft/items/bow.json
12be767d961ae273ae0968ad06f022b57afbb0b0 assets/minecraft/items/crossbow.json
08270cb07bcffbeedc5c5eeb4904c4f852a8741b assets/minecraft/models/item/bow_pulling_0.json
ceb850b6b4a0650ee3d1529e67ab8e7447b0319f assets/minecraft/models/item/bow_pulling_1.json
65c4490152c9f65bc766d686b38fffdfeb7a0873 assets/minecraft/models/item/bow_pulling_2.json
3f5af50f9ebf07f64949415b4d3a3b6ec549f93b assets/minecraft/models/item/crossbow_arrow.json
b98e781a6782a959e897e7db93ef9e9bed6ee72f assets/minecraft/models/item/crossbow_firework.json
967e2cb3fce436263b91050e448394e460d1596d assets/minecraft/models/item/crossbow_pulling_0.json
1b3d6214059e250dda7aba60632cdc5a315a6146 assets/minecraft/models/item/crossbow_pulling_1.json
98bcc5449dcc6b30ae1e0558906c2b3ce5d32da0 assets/minecraft/models/item/crossbow_pulling_2.json

View File

@ -1,13 +1,12 @@
// 1.21 2024-11-26T16:52:31.259654 Advancements
// 1.21.5 2025-03-30T19:34:30.4253532 Advancements
4d97adba079f1966090a52443bb439319f550680 data/leashedplayer/advancement/advancement_leash_arrow.json
f16184b81ea35a0fbd8f2c49b085a96c32818c69 data/leashedplayer/advancement/dog_running_player.json
bce12ed339b3b0fded263ba039f7a4e6fcfb84ca data/leashedplayer/advancement/follow_arrow.json
29911bbed5a1b7ede2b08d82e6716cd9463bc061 data/leashedplayer/advancement/leashed_friend.json
25f6b476b194a27c0fe0e75d74ac3a7ff4054789 data/leashedplayer/advancement/leashed_self.json
a69a455855fb6dd8a8ac131a55099de5de45d7c4 data/leashedplayer/advancement/leash_arrow.json
133f844ffafd37b9ba57cafa96350f035cac57f9 data/leashedplayer/advancement/leash_start.json
d109d59adbfa6efdefb4003623c9fb4950f2956b data/leashedplayer/advancement/leash_start.json
2d8bce7fd078f9cc6b73b77f2fbab30e6cc197f4 data/leashedplayer/advancement/leash_terminator.json
4e567c22e18462ad367fe1817140d1ffa13a6294 data/leashedplayer/advancement/neo_fox.json
95486932f200c278f23444adca2e328a82e7f863 data/leashedplayer/advancement/nestle_arrow.json
4b0bcf6b372f52e954edcef37a6b04435ec2b4e8 data/leashedplayer/advancement/no_leash.json
72f40eb5816d1e8c296bdf4df6b599c15ba7e7e9 data/leashedplayer/advancement/tipped_leash_arrow.json

View File

@ -1,2 +1,2 @@
// 1.21 2024-12-15T17:48:33.0539432 Languages: zh_tw for mod: leashedplayer
a01c64ca969974766c47baadd465b24b6fb5803b assets/leashedplayer/lang/zh_tw.json
// 1.21.5 2025-03-29T16:40:03.0241113 Languages: zh_tw for mod: leashedplayer
c23825af72a73bc54b72ad3817acb5a03d299375 assets/leashedplayer/lang/zh_tw.json

View File

@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/amethyst_shears"
}
}

View File

@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/fabric"
}
}

View File

@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/leash_rope_arrow"
}
}

View File

@ -0,0 +1,6 @@
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/spectral_leash_rope_arrow"
}
}

View File

@ -0,0 +1,12 @@
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/tipped_leash_rope_arrow",
"tints": [
{
"type": "minecraft:potion",
"default": -13083194
}
]
}
}

View File

@ -17,8 +17,6 @@
"advancement.leashedplayer.leashed_self.desc": "“Restrain oneself with a rope",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "It seems can be equipped.",
"advancement.leashedplayer.nestle_arrow": "Arrow with the Power of Nestle!",
"advancement.leashedplayer.nestle_arrow.desc": "The Power of Nestle!!!",
"advancement.leashedplayer.no_leash": "Don't tie me up",
"advancement.leashedplayer.no_leash.desc": "You cannot be leashed by ANY",
"advancement.leashedplayer.tipped_leash_arrow": "God said there should be more arrows",
@ -29,16 +27,10 @@
"entity.leashedplayer.leash_rope_arrow": "Leash Rope Arrow",
"entity.leashedplayer.nestle_rope_arrow": "Nestle Rope Arrow",
"entity.leashedplayer.spectral_leash_rope_arrow": "Spectral Leash Rope Arrow",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea": "Should Non-OP Player can change their TalkArea",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea.description": "Above on its Name",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "Create Leash Fence Knot Entity if absent",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "Create LeashKnot Entity if it's absent on fence",
"gamerule.LP.DefaultTalkArea": "Default Area Talk",
"gamerule.LP.DefaultTalkArea.description": "When the global setting is non-negative, it limits the chat range for all players. If a player's configured chat range is smaller than this value, this rule applies. Otherwise, the player's custom value is used.",
"gamerule.LP.KeepLeashNotDropTime": "Keep leash alive Time",
"gamerule.LP.KeepLeashNotDropTime.description": "The time of Keep new leash which has far distance alive (Tick)",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull": "Open TOP NEEDED Mode When Screen isn't null",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull.description": "The One Probe will automatic to be in the Needed Mode when Gui Screen is not NULL",
"gamerule.LP.TeleportWithLeashedPlayers": "Teleport leashed player with player holder",
"gamerule.LP.TeleportWithLeashedPlayers.description": "Holder will teleport with their leashed players ",
"item.leash_rope_arrow.desc.1": "§7This arrow will carry the owner along with its flight:",
@ -49,43 +41,23 @@
"item.leash_rope_arrow.description": "Arrows with ropes attached?",
"item.leashedplayer.amethyst_shears": "Amethyst Shears",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.kid_spawn_egg": "Kid Spawn Egg",
"item.leashedplayer.leash_rope_arrow": "Leash Rope Arrow",
"item.leashedplayer.neoforge": "NeoForge",
"item.leashedplayer.nestle_rope_arrow": "Nestle Rope Arrow",
"item.leashedplayer.spectral_leash_rope_arrow": "Spectral Leash Rope Arrow",
"item.minecraft.lingering_potion.effect.no_leash": "Splash No Leash Potion",
"item.minecraft.potion.effect.no_leash": "No Leash Potion",
"item.minecraft.splash_potion.effect.no_leash": "Splash No Leash Potion",
"item.minecraft.tipped_arrow.effect.no_leash": "Arrow of No Leash",
"item.nestle_rope_arrow.desc.1": "§7This arrow will carry the owner along with its flight:",
"item.nestle_rope_arrow.desc.2": "§c1.§r If it hits an entity, it will leash the owner with the entity and drop as a normal arrow;",
"item.nestle_rope_arrow.desc.3": "§c2.§r When fired from its launcher, the first player hit will become the arrow's owner and will fly along with it.",
"item.nestle_rope_arrow.desc.4": "",
"item.nestle_rope_arrow.desc.5": "",
"item.spectral_leash_rope_arrow.desc": "§c2.§r Strike the entity to give it a §e§lGlowing§r effect.",
"item.tipped_leash_rope_arrow.desc": "§c2.§rStrike the entity to give it a Potion effect.",
"item.tipped_leash_rope_arrow.name": "Tipped Leash Rope Arrow Soaked By %1$s",
"item.variant.leash_rope_arrow.desc.1": "§7A variant of Leash Rope Arrow",
"item.variant.leash_rope_arrow.desc.2": "§c1.§r The function is the same as its original one。",
"jukebox_song.leashedplayer.what_does_the_fox_say": "What does the fox say?",
"key.leashedplayer.apply_talkarea_preference": "Apply TalkArea Preference",
"key.leashedplayer.category": "Leashed Player",
"key.leashedplayer.leash_length.add": "Increase the Length of Leash Rope",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "Only work on Players",
"key.leashedplayer.leash_length.sub": "Decrease the Length of Leash Rope",
"leashedplayer.chat.none_heard_you": "Nobody heard your message",
"leashedplayer.command.chat.message.no_right": "You haven't the right to do that!",
"leashedplayer.command.chat.message.talkarea.current_config": "%s 's §6TalkArea Current§7:§e %d §6blocks §f(§aPrefence§7:§e %d §ablocks§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s 's §atalk area preference set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s 's talk area preference is not set!",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6TalkArea Current§7:§e %d §6blocks §f(§aPrefence§7:§e %d §ablocks§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§aTalk area preference set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "Your talk area preference is not set!",
"leashedplayer.command.chat.message.talkarea.self.set": "§aTalk area set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§aTalk area unlimited!§r",
"leashedplayer.command.chat.message.talkarea.set": "%s 's §atalk area set to §e%d§a blocks!§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s 's §atalk area unlimited!§r",
"leashedplayer.command.leash.message.leash.data.clear": "%1$s's LeashData(LeashHolderEntity: %2$s) now is clear",
"leashedplayer.command.leash.message.leash.data.clear.leash.clear.failed.no_data": "%1$s has no LeashData can be clear",
"leashedplayer.command.leash.message.leash.data.null": "%1$s has no LeashDataEntity",
@ -110,7 +82,6 @@
"leashedplayer.leash_rope.length.increase": "§aIncrease the §f%s §aLength of Leash Rope§7(§bLength§7:§e%d§7)",
"leashedplayer.leash_rope.length.increase.self": "§aIncrease the Length of Leash Rope§7(§bLength§7:§e%d§7)",
"leashedplayer.leash_rope_arrow.try_to_pickup.push_shift_tip": "§aPush §f§lShift§a to pick up quickly",
"multiplayer.disconnect.addiction": "You've triggered the anti-addiction mechanic, and you'll come back when you rest!",
"painting.leashedplayer.group_photo.author": "§9Leisure §4Time §eDock§r",
"painting.leashedplayer.group_photo.title": "§dGroup Photo §7[§6memorable§7]§r",
"sound.leashedplayer.subtitle.what_does_the_fox_say": "Great Chu will rise again! Chen She will be king!"

View File

@ -1,15 +1,3 @@
{
"entity.leashedplayer.kid_player": "幼",
"gamerule.LP.DefaultTalkArea.description": "阖局初置非负数,则限一顾之日下,若立聊城小在直则用其常,若用玩义直上跻之地",
"leashedplayer.chat.none_heard_you": "无人受子问",
"leashedplayer.command.chat.message.talkarea.current_config": "%s§6今聊城可知半径置§e %d§6格§f(§a默§7§e%d格§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s§6默置§e %d§6格§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s未置默视之",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6今聊城可知半径置§e %d§6格§f(§a默§7§e%d格§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§6默置§e %d§6格§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "未置默视之",
"leashedplayer.command.chat.message.talkarea.self.set": "§6今聊城可知半径置§e%d §6格§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§a语矢无限§r",
"leashedplayer.command.chat.message.talkarea.set": "%s§6今聊城可知半径置§e%d §6格§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s§a语矢无限§r"
"entity.leashedplayer.kid_player": "幼"
}

View File

@ -17,8 +17,6 @@
"advancement.leashedplayer.leashed_self.desc": "用拴绳拴住自己",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "似乎可以戴头上",
"advancement.leashedplayer.nestle_arrow": "贴贴之箭!",
"advancement.leashedplayer.nestle_arrow.desc": "贴贴之力!!!",
"advancement.leashedplayer.no_leash": "勿拴我",
"advancement.leashedplayer.no_leash.desc": "你不会被任何东西拴住",
"advancement.leashedplayer.tipped_leash_arrow": "神说要有更多箭矢",
@ -29,16 +27,10 @@
"entity.leashedplayer.leash_rope_arrow": "拴绳箭",
"entity.leashedplayer.nestle_rope_arrow": "贴贴拴绳箭",
"entity.leashedplayer.spectral_leash_rope_arrow": "拴绳光灵箭",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea": "非OP应该可以修改自己的聊天可见半径吗?",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea.description": "同名",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失则创建拴绳结",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在栅栏处缺失拴绳结,则创建它",
"gamerule.LP.DefaultTalkArea": "默认聊天区域可见半径",
"gamerule.LP.DefaultTalkArea.description": "全局区域设置为非负数时,则限制全体玩家的聊天区域。若玩家设置的聊天区域小于该值则采用该规则,反之则采用玩家自定义值",
"gamerule.LP.KeepLeashNotDropTime": "保持拴绳不掉落的时间",
"gamerule.LP.KeepLeashNotDropTime.description": "当距离过远时,保持新建拴绳不掉落的时间 (刻)",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull": "当屏幕不为空时自动打开探测器的Needed模式",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull.description": "当屏幕不为空时自动打开探测器的Needed模式",
"gamerule.LP.TeleportWithLeashedPlayers": "被拴玩家随玩家持有者传送",
"gamerule.LP.TeleportWithLeashedPlayers.description": "传送时将被拴玩家与持有者一起传送",
"item.leash_rope_arrow.desc.1": "§7该箭将会携带拥有者随其飞行",
@ -49,43 +41,23 @@
"item.leash_rope_arrow.description": "带有拴绳的箭矢?",
"item.leashedplayer.amethyst_shears": "紫水晶剪刀",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.kid_spawn_egg": "小孩生成蛋",
"item.leashedplayer.leash_rope_arrow": "拴绳箭",
"item.leashedplayer.neoforge": "NeoForge",
"item.leashedplayer.nestle_rope_arrow": "贴贴拴绳箭",
"item.leashedplayer.spectral_leash_rope_arrow": "拴绳光灵箭",
"item.minecraft.lingering_potion.effect.no_leash": "滞留型禁拴药水",
"item.minecraft.potion.effect.no_leash": "禁拴药水",
"item.minecraft.splash_potion.effect.no_leash": "喷溅型禁拴药水",
"item.minecraft.tipped_arrow.effect.no_leash": "禁拴之箭",
"item.nestle_rope_arrow.desc.1": "§7该箭将会携带拥有者随其飞行",
"item.nestle_rope_arrow.desc.2": "§c1.§r 若击中生物时,将持有者与其拴在一起并已普通箭形式掉落;",
"item.nestle_rope_arrow.desc.3": "§c2.§r 当前其发射器里发射,第一个射中的玩家将成为此箭的持有者并随箭飞行.",
"item.nestle_rope_arrow.desc.4": "",
"item.nestle_rope_arrow.desc.5": "",
"item.spectral_leash_rope_arrow.desc": "§c2.§r 击中实体给与其§e§l发光§7(§e§lGlowing§7)§r效果",
"item.tipped_leash_rope_arrow.desc": "§c2.§r 击中实体给与其药水效果",
"item.tipped_leash_rope_arrow.name": "用%1$s浸泡过的拴绳箭",
"item.variant.leash_rope_arrow.desc.1": "§7拴绳箭的一个变种",
"item.variant.leash_rope_arrow.desc.2": "§c1.§r 功能同其本体;",
"jukebox_song.leashedplayer.what_does_the_fox_say": "狐狸是怎么叫的?",
"key.leashedplayer.apply_talkarea_preference": "应用可见区域预设",
"key.leashedplayer.category": "可拴玩家",
"key.leashedplayer.leash_length.add": "增加拴绳长度",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "只在玩家身上有效",
"key.leashedplayer.leash_length.sub": "减小拴绳长度",
"leashedplayer.chat.none_heard_you": "沒有人接收到你的消息",
"leashedplayer.command.chat.message.no_right": "你无权这样做!",
"leashedplayer.command.chat.message.talkarea.current_config": "%s§6目前聊天区域可见半径设置§7:§e %d §6格 §f(§a默认值§7:§e %d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s§a默认聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s未设置默认可见消息聊天区域半径",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6目前聊天区域可见半径设置§7:§e %d §6格 §f(§a默认值§7:§e %d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§a默认聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "未设置默认可见消息聊天区域半径",
"leashedplayer.command.chat.message.talkarea.self.set": "§a聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§a聊天区域半径无限制§r",
"leashedplayer.command.chat.message.talkarea.set": "%s§a聊天区域可见消息半径设置为 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s§a聊天区域半径无限制§r",
"leashedplayer.command.leash.message.leash.data.clear": "%1$s的拴绳数据拴绳持有者实体%2$s现在已清除",
"leashedplayer.command.leash.message.leash.data.clear.leash.clear.failed.no_data": "%1$s沒有拴绳数据可清除",
"leashedplayer.command.leash.message.leash.data.null": "%1$s沒有拴绳数据实体",
@ -110,7 +82,6 @@
"leashedplayer.leash_rope.length.increase": "§a增加§f%s的拴绳长度§a§7(§b长度§7:§e%d§7)",
"leashedplayer.leash_rope.length.increase.self": "§a增加拴绳长度§a§7(§b长度§7:§e%d§7)",
"leashedplayer.leash_rope_arrow.try_to_pickup.push_shift_tip": "§a按下§f§lShift键§a以加快拾取",
"multiplayer.disconnect.addiction": "你触发了防沉迷机制,休息会再来吧!",
"painting.leashedplayer.group_photo.author": "§9闲趣§4时§e坞§r",
"painting.leashedplayer.group_photo.title": "§d集体照 §7[§6纪念§7]§r",
"sound.leashedplayer.subtitle.what_does_the_fox_say": "大楚兴~ 陈胜王~~"

View File

@ -17,8 +17,6 @@
"advancement.leashedplayer.leashed_self.desc": "用栓繩拴住自己",
"advancement.leashedplayer.neo_fox": "NEOFORGE!",
"advancement.leashedplayer.neo_fox.desc": "似乎可以戴著",
"advancement.leashedplayer.nestle_arrow": "貼貼之箭!",
"advancement.leashedplayer.nestle_arrow.desc": "貼貼之力!!!",
"advancement.leashedplayer.no_leash": "請恁勿拴唔",
"advancement.leashedplayer.no_leash.desc": "恁不會被任何拴住",
"advancement.leashedplayer.tipped_leash_arrow": "神說要有更多箭矢",
@ -29,16 +27,10 @@
"entity.leashedplayer.leash_rope_arrow": "拴繩箭",
"entity.leashedplayer.nestle_rope_arrow": "貼貼拴繩箭",
"entity.leashedplayer.spectral_leash_rope_arrow": "拴繩光靈箭",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea": "非OP應該可以修改自己的聊天可見半徑嗎",
"gamerule.LP.CanCommonPlayerChangeSelfTalkArea.description": "同名",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent": "如果缺失則創建拴繩結",
"gamerule.LP.CreateLeashFenceKnotEntityIfAbsent.description": "如果在柵欄処缺失拴繩結,則創建它",
"gamerule.LP.DefaultTalkArea": "默認聊天區域可見半徑",
"gamerule.LP.DefaultTalkArea.description": "儅全局區域為非負時,則限制全服玩家聊天區域。若玩家自定義值小於該規則則采用,反之則用玩家自定義值",
"gamerule.LP.KeepLeashNotDropTime": "保持其不掉落的時間",
"gamerule.LP.KeepLeashNotDropTime.description": "儅距離過遠時,保持其不掉落的時間(刻)",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull": "避免糠測器糠屏幕",
"gamerule.LP.OpenTOPNeededModeWhenScreenIsNotNull.description": "避免糠測器糠屏幕",
"gamerule.LP.TeleportWithLeashedPlayers": "被拴玩家随玩家持有者傳送",
"gamerule.LP.TeleportWithLeashedPlayers.description": "將被拴玩家將隨持有者一起傳送",
"item.leash_rope_arrow.desc.1": "§7該箭將會攜帶擁有者隨其飛行",
@ -49,43 +41,23 @@
"item.leash_rope_arrow.description": "帶有拴繩的箭矢?",
"item.leashedplayer.amethyst_shears": "紫水晶剪刀",
"item.leashedplayer.fabric": "Fabric",
"item.leashedplayer.kid_spawn_egg": "小孩生成蛋",
"item.leashedplayer.leash_rope_arrow": "拴繩箭",
"item.leashedplayer.neoforge": "NeoForge",
"item.leashedplayer.nestle_rope_arrow": "貼貼拴繩箭",
"item.leashedplayer.spectral_leash_rope_arrow": "拴繩光靈箭",
"item.minecraft.lingering_potion.effect.no_leash": "滯留型禁拴藥水",
"item.minecraft.potion.effect.no_leash": "禁拴藥水",
"item.minecraft.splash_potion.effect.no_leash": "噴濺型禁拴藥水",
"item.minecraft.tipped_arrow.effect.no_leash": "禁拴之箭",
"item.nestle_rope_arrow.desc.1": "§7該箭將會攜帶擁有者隨其飛行",
"item.nestle_rope_arrow.desc.2": "§c1.§r 若擊中生物時,將持有者與其拴在一起其上並以普通箭的形式掉落;",
"item.nestle_rope_arrow.desc.3": "§c2.§r 當箭從發射器發射時,第一個射中的玩家將成為此箭的持有者並隨箭飛行;",
"item.nestle_rope_arrow.desc.4": "",
"item.nestle_rope_arrow.desc.5": "",
"item.spectral_leash_rope_arrow.desc": "擊中實體給予其§e§l發光§7(§e§lGlowing§7)§r效果",
"item.tipped_leash_rope_arrow.desc": "擊中實體給予其药水效果",
"item.tipped_leash_rope_arrow.name": "蘸有%1$s的拴繩箭",
"item.variant.leash_rope_arrow.desc.1": "§7拴繩箭矢的一個變種",
"item.variant.leash_rope_arrow.desc.2": "§c1.§r 功能與本體一致;",
"jukebox_song.leashedplayer.what_does_the_fox_say": "狐狸是怎麽叫的?",
"key.leashedplayer.apply_talkarea_preference": "應用設置可見區域預設",
"key.leashedplayer.category": "可拴玩家",
"key.leashedplayer.leash_length.add": "增加拴繩長度",
"key.leashedplayer.leash_length.not_support_to_not_player_entity": "僅對玩家有效",
"key.leashedplayer.leash_length.sub": "減小拴繩長度",
"leashedplayer.chat.none_heard_you": "無人接收到你的訊息",
"leashedplayer.command.chat.message.no_right": "你無權這麽做!",
"leashedplayer.command.chat.message.talkarea.current_config": "%s§6目前可見訊息聊天半徑設置§7:§e%d §6格 §f(§a默認值§7:§e%d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.preference.set": "%s§a默認聊天區域可見訊息半徑設置為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.preference_not_set": "%s未設置可見訊息聊天半徑",
"leashedplayer.command.chat.message.talkarea.self.current_config": "§6目前可見訊息聊天半徑設置§7:§e%d §6格 §f(§a默認值§7:§e%d §a格§f)§r",
"leashedplayer.command.chat.message.talkarea.self.preference.set": "§a默認聊天區域可見訊息半徑設置為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.preference_not_set": "未設置可見訊息聊天半徑",
"leashedplayer.command.chat.message.talkarea.self.set": "§a聊天區域可見半徑為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.self.unlimited": "§a聊天區域半徑無限制§r",
"leashedplayer.command.chat.message.talkarea.set": "%s§a聊天區域可見半徑為 §e%d §a格!§r",
"leashedplayer.command.chat.message.talkarea.unlimited": "%s§a聊天區域半徑無限制§r",
"leashedplayer.command.leash.message.leash.data.clear": "%1$s的拴繩數據拴繩持有者實體%2$s現在已清除",
"leashedplayer.command.leash.message.leash.data.clear.leash.clear.failed.no_data": "%1$s沒有拴繩數據實體可被清除",
"leashedplayer.command.leash.message.leash.data.null": "%1$s沒有拴繩數據實體",
@ -110,7 +82,6 @@
"leashedplayer.leash_rope.length.increase": "§a增加§f%s§a的拴繩長度§7(§長度§7:§e%d§7)",
"leashedplayer.leash_rope.length.increase.self": "§a增加拴繩長度§7(§長度§7:§e%d§7)",
"leashedplayer.leash_rope_arrow.try_to_pickup.push_shift_tip": "§a按下§f§lShift鍵§a以加速拾取",
"multiplayer.disconnect.addiction": "你觸發了防沉迷機制,休息會再來吧!",
"painting.leashedplayer.group_photo.author": "§9閑趣§4時§e塢§r",
"painting.leashedplayer.group_photo.title": "§d集體照 §7[§6紀念§7]§r",
"sound.leashedplayer.subtitle.what_does_the_fox_say": "大楚興~ 陳勝王~~"

View File

@ -1,6 +0,0 @@
{
"parent": "minecraft:item/crossbow",
"textures": {
"layer0": "leashedplayer:item/crossbow_nestle_rope_arrow"
}
}

View File

@ -1,3 +0,0 @@
{
"parent": "minecraft:item/template_spawn_egg"
}

View File

@ -1,6 +0,0 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "leashedplayer:item/nestle_rope_arrow"
}
}

View File

@ -1,7 +1,7 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "minecraft:item/tipped_arrow_head",
"layer0": "leashedplayer:item/tipped_leash_rope_arrow_head",
"layer1": "leashedplayer:item/tipped_leash_rope_arrow_base"
}
}

View File

@ -0,0 +1,65 @@
{
"model": {
"type": "minecraft:condition",
"on_false": {
"type": "minecraft:model",
"model": "minecraft:item/bow"
},
"on_true": {
"type": "leashedplayer:conditional_range",
"fallback": {
"type": "minecraft:model",
"model": "minecraft:item/bow_pulling_0"
},
"falseModels": [
{
"model": {
"type": "minecraft:model",
"model": "minecraft:item/bow_pulling_0"
},
"threshold": 0.0
},
{
"model": {
"type": "minecraft:model",
"model": "minecraft:item/bow_pulling_1"
},
"threshold": 0.65
},
{
"model": {
"type": "minecraft:model",
"model": "minecraft:item/bow_pulling_2"
},
"threshold": 0.9
}
],
"property": "leashedplayer:bow_pull",
"scale": 0.05,
"trueModels": [
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/bow_lra_pulling_0"
},
"threshold": 0.0
},
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/bow_lra_pulling_1"
},
"threshold": 0.65
},
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/bow_lra_pulling_2"
},
"threshold": 0.9
}
]
},
"property": "minecraft:using_item"
}
}

View File

@ -0,0 +1,61 @@
{
"model": {
"type": "minecraft:condition",
"on_false": {
"type": "minecraft:select",
"cases": [
{
"model": {
"type": "minecraft:model",
"model": "minecraft:item/crossbow_arrow"
},
"when": "arrow"
},
{
"model": {
"type": "minecraft:model",
"model": "minecraft:item/crossbow_firework"
},
"when": "rocket"
},
{
"model": {
"type": "minecraft:model",
"model": "leashedplayer:item/crossbow_leash_rope_arrow"
},
"when": "leash_rope_arrow"
}
],
"fallback": {
"type": "minecraft:model",
"model": "minecraft:item/crossbow"
},
"property": "leashedplayer:charge_extend_type"
},
"on_true": {
"type": "minecraft:range_dispatch",
"entries": [
{
"model": {
"type": "minecraft:model",
"model": "minecraft:item/crossbow_pulling_1"
},
"threshold": 0.58
},
{
"model": {
"type": "minecraft:model",
"model": "minecraft:item/crossbow_pulling_2"
},
"threshold": 1.0
}
],
"fallback": {
"type": "minecraft:model",
"model": "minecraft:item/crossbow_pulling_0"
},
"property": "minecraft:crossbow/pull"
},
"property": "minecraft:using_item"
}
}

View File

@ -1,6 +1,6 @@
{
"parent": "minecraft:item/bow",
"textures": {
"layer0": "leashedplayer:item/bow_nra_pulling_0"
"layer0": "minecraft:item/bow_pulling_0"
}
}

View File

@ -1,6 +1,6 @@
{
"parent": "minecraft:item/bow",
"textures": {
"layer0": "leashedplayer:item/bow_nra_pulling_1"
"layer0": "minecraft:item/bow_pulling_1"
}
}

View File

@ -1,6 +1,6 @@
{
"parent": "minecraft:item/bow",
"textures": {
"layer0": "leashedplayer:item/bow_nra_pulling_2"
"layer0": "minecraft:item/bow_pulling_2"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/crossbow",
"textures": {
"layer0": "minecraft:item/crossbow_arrow"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/crossbow",
"textures": {
"layer0": "minecraft:item/crossbow_firework"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/crossbow",
"textures": {
"layer0": "minecraft:item/crossbow_pulling_0"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/crossbow",
"textures": {
"layer0": "minecraft:item/crossbow_pulling_1"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/crossbow",
"textures": {
"layer0": "minecraft:item/crossbow_pulling_2"
}
}

View File

@ -13,7 +13,7 @@
},
"display": {
"announce_to_chat": false,
"background": "leashedplayer:textures/gui/advancements/backgrounds/leashed_player.png",
"background": "leashedplayer:textures/gui/advancements/backgrounds/leashed_player",
"description": {
"translate": "advancement.leashedplayer.leash_start.desc"
},

View File

@ -1,35 +0,0 @@
{
"parent": "leashedplayer:leash_arrow",
"criteria": {
"has_nestle_rope_arrow": {
"conditions": {
"items": [
{
"items": "leashedplayer:nestle_rope_arrow"
}
]
},
"trigger": "minecraft:inventory_changed"
}
},
"display": {
"description": {
"translate": "advancement.leashedplayer.nestle_arrow.desc"
},
"frame": "goal",
"hidden": true,
"icon": {
"count": 1,
"id": "leashedplayer:nestle_rope_arrow"
},
"title": {
"translate": "advancement.leashedplayer.nestle_arrow"
}
},
"requirements": [
[
"has_nestle_rope_arrow"
]
],
"sends_telemetry_event": true
}

View File

@ -1,32 +0,0 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_nestle_rope": {
"conditions": {
"items": [
{
"items": "nestle:nestle_lead"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "leashedplayer:nestle_rope_arrow"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_nestle_rope"
]
],
"rewards": {
"recipes": [
"leashedplayer:nestle_rope_arrow"
]
}
}

View File

@ -23,7 +23,7 @@
},
"has_the_recipe": {
"conditions": {
"recipe": "minecraft:spectral_leash_rope_arrow_with_leash_rope_arrow"
"recipe": "leashedplayer:spectral_leash_rope_arrow"
},
"trigger": "minecraft:recipe_unlocked"
}
@ -37,7 +37,7 @@
],
"rewards": {
"recipes": [
"minecraft:spectral_leash_rope_arrow_with_leash_rope_arrow"
"leashedplayer:spectral_leash_rope_arrow"
]
}
}

View File

@ -1,5 +1,11 @@
{
"asset_id": "leashedplayer:group_photo",
"author": {
"translate": "painting.leashedplayer.group_photo.author"
},
"height": 3,
"title": {
"translate": "painting.leashedplayer.group_photo.title"
},
"width": 4
}

View File

@ -2,12 +2,8 @@
"type": "minecraft:crafting_shaped",
"category": "misc",
"key": {
"#": {
"item": "minecraft:amethyst_shard"
},
"%": {
"item": "minecraft:stick"
}
"#": "minecraft:amethyst_shard",
"%": "minecraft:stick"
},
"pattern": [
"#%",

View File

@ -2,12 +2,8 @@
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
{
"item": "minecraft:lead"
},
{
"item": "minecraft:arrow"
}
"minecraft:lead",
"minecraft:arrow"
],
"result": {
"count": 1,

View File

@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
{
"item": "nestle:nestle_lead"
},
{
"item": "minecraft:arrow"
}
],
"result": {
"count": 1,
"id": "leashedplayer:nestle_rope_arrow"
}
}

View File

@ -2,12 +2,8 @@
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
{
"item": "minecraft:lead"
},
{
"item": "minecraft:spectral_arrow"
}
"minecraft:lead",
"minecraft:spectral_arrow"
],
"result": {
"count": 1,

View File

@ -23,7 +23,7 @@
},
"has_the_recipe": {
"conditions": {
"recipe": "minecraft:spectral_leash_rope_arrow_with_glowstone_dust"
"recipe": "minecraft:leash_rope_arrow_shape"
},
"trigger": "minecraft:recipe_unlocked"
}
@ -37,7 +37,7 @@
],
"rewards": {
"recipes": [
"minecraft:spectral_leash_rope_arrow_with_glowstone_dust"
"minecraft:leash_rope_arrow_shape"
]
}
}

View File

@ -1,32 +0,0 @@
{
"parent": "minecraft:recipes/root",
"criteria": {
"has_nestle": {
"conditions": {
"items": [
{
"items": "nestle:nestle"
}
]
},
"trigger": "minecraft:inventory_changed"
},
"has_the_recipe": {
"conditions": {
"recipe": "minecraft:nestle_rope_arrow_with_leash_rope_arrow"
},
"trigger": "minecraft:recipe_unlocked"
}
},
"requirements": [
[
"has_the_recipe",
"has_nestle"
]
],
"rewards": {
"recipes": [
"minecraft:nestle_rope_arrow_with_leash_rope_arrow"
]
}
}

View File

@ -2,12 +2,8 @@
"type": "minecraft:crafting_shaped",
"category": "misc",
"key": {
"#": {
"item": "leashedplayer:leash_rope_arrow"
},
"$": {
"item": "minecraft:glowstone_dust"
}
"#": "leashedplayer:leash_rope_arrow",
"$": "minecraft:glowstone_dust"
},
"pattern": [
" $ ",

View File

@ -1,16 +0,0 @@
{
"type": "minecraft:crafting_shapeless",
"category": "misc",
"ingredients": [
{
"item": "nestle:nestle"
},
{
"item": "leashedplayer:leash_rope_arrow"
}
],
"result": {
"count": 1,
"id": "leashedplayer:nestle_rope_arrow"
}
}

View File

@ -0,0 +1,5 @@
{
"values": [
"minecraft:amethyst_shard"
]
}

View File

@ -2,7 +2,6 @@
"values": [
"leashedplayer:leash_rope_arrow",
"leashedplayer:spectral_leash_rope_arrow",
"leashedplayer:tipped_leash_rope_arrow",
"leashedplayer:nestle_rope_arrow"
"leashedplayer:tipped_leash_rope_arrow"
]
}

View File

@ -1,93 +1,51 @@
package com.r3944realms.leashedplayer;
import com.r3944realms.leashedplayer.client.renders.entities.*;
import com.r3944realms.leashedplayer.client.renderer.LeashRendererUtil;
import com.r3944realms.leashedplayer.client.renderer.PlayerLeashState;
import com.r3944realms.leashedplayer.client.renderer.entities.ChestItemLayerRenderer;
import com.r3944realms.leashedplayer.client.renderer.entities.LeashRopeArrowRenderer;
import com.r3944realms.leashedplayer.client.renderer.entities.SpectralLeashRopeArrowRenderer;
import com.r3944realms.leashedplayer.client.renderer.item.ConditionalRangeItemModel;
import com.r3944realms.leashedplayer.client.renderer.item.properties.conditional.ChargeExtend;
import com.r3944realms.leashedplayer.content.ModKeyMapping;
import com.r3944realms.leashedplayer.content.commands.Command;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.OpenTOPNeededModeWhenScreenIsNotNull;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.items.type.ILeashRopeArrow;
import com.r3944realms.leashedplayer.content.items.type.INestleRopeArrow;
import com.r3944realms.leashedplayer.modInterface.IPlayerRenderStateExtension;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import com.r3944realms.leashedplayer.network.server.Code;
import com.r3944realms.leashedplayer.network.server.DecreaseLeashRopeLength;
import com.r3944realms.leashedplayer.network.server.IncreaseLeashRopeLength;
import com.r3944realms.leashedplayer.utils.Util;
import mcjty.theoneprobe.config.Config;
import mcjty.theoneprobe.gui.GuiNote;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.screens.ChatScreen;
import net.minecraft.client.gui.screens.DisconnectedScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.entity.player.PlayerRenderer;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.client.resources.PlayerSkin;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.DisconnectionDetails;
import net.minecraft.network.chat.Component;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.FastColor;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionContents;
import net.minecraft.world.item.component.ChargedProjectiles;
import net.minecraft.world.phys.HitResult;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.ModList;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLClientSetupEvent;
import net.neoforged.neoforge.client.event.*;
import net.neoforged.neoforge.network.PacketDistributor;
import java.util.List;
public abstract class ClientEventHandler {
public static final String ADDICTION = "multiplayer.disconnect.addiction";
public class ClientEventHandler {
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.GAME, modid = LeashedPlayer.MOD_ID)
public static class Game extends ClientEventHandler {
private static int oldSelect;
private static boolean configSaved = false;
private static final boolean IS_TOP_LOADED = ModList.get().isLoaded("theoneprobe");
public static class Game {
@SubscribeEvent
public static void onClientTick(ClientTickEvent.Pre event) {
Minecraft mc = Minecraft.getInstance();
if (mc.level == null) return;
if (GameruleRegistry.getGameruleBoolValue(mc.level, OpenTOPNeededModeWhenScreenIsNotNull.ID)){
Screen currentScreen = mc.screen;
if (IS_TOP_LOADED) {
if (currentScreen != null) {
if (currentScreen instanceof GuiNote || currentScreen instanceof ChatScreen) {
configSaved = false;
oldSelect = Config.needsProbe.get();
} else {
if (!configSaved) {
oldSelect = Config.needsProbe.get();
Config.setProbeNeeded(Config.PROBE_NEEDED);
configSaved = true;
} else {
Config.setProbeNeeded(Config.PROBE_NEEDED);
}
}
} else {
Config.setProbeNeeded(oldSelect);
configSaved = false;
}
}
}
}
@SubscribeEvent
public static void onScreenOpen(ScreenEvent.Opening opening) {
if(opening.getNewScreen() instanceof DisconnectedScreen screen) {
if (screen.details.reason().getString().equals("You are already connected to this proxy!")) {
screen.details = new DisconnectionDetails(Component.translatable(ADDICTION).withStyle(ChatFormatting.RED));
}
public static void onPlayerRendererEventPre(RenderPlayerEvent.Post event) {
PlayerRenderState renderState = event.getRenderState();
PlayerLeashState playerLeashState = ((IPlayerRenderStateExtension) renderState).getPlayerLeashState();
if(playerLeashState != null) {
if (playerLeashState.vanilaLeashState != null)
LeashRendererUtil.renderLeash(event.getPoseStack(), event.getMultiBufferSource(), playerLeashState.vanilaLeashState);
else
LeashRendererUtil.renderLeash(event.getPoseStack(), event.getMultiBufferSource(), renderState);
}
}
@SubscribeEvent
@ -95,10 +53,6 @@ public abstract class ClientEventHandler {
Minecraft minecraft = Minecraft.getInstance();
LocalPlayer player = minecraft.player;
assert player != null;
if (ModKeyMapping.KEY_APPLY_TALKAREA_PREFERENCE.isDown()) {
String prefix = (Command.SHOULD_USE_PREFIX ? Command.PREFIX : "") + " ";
player.connection.sendCommand(prefix + "talkArea usePreference");
}
if (ModKeyMapping.KEY_ADD_LEASH_LENGTH.isDown()) {
PlayerLeashable playerLeashable = (PlayerLeashable) player;
if (playerLeashable.getLeashDataFromEntityData() == null) {
@ -135,70 +89,37 @@ public abstract class ClientEventHandler {
}
@EventBusSubscriber(value = Dist.CLIENT, bus = EventBusSubscriber.Bus.MOD, modid = LeashedPlayer.MOD_ID)
public static class Mod extends ClientEventHandler {
public static class Mod {
@SubscribeEvent
public static void onRegisterItemProperties (FMLClientSetupEvent event){
event.enqueueWork(() -> {
ItemProperties.register(Items.CROSSBOW, ResourceLocation.withDefaultNamespace("leash_rope_arrow"),
((pStack, pLevel, pEntity, pSeed) -> {
ChargedProjectiles chargedProjectiles = pStack.get(DataComponents.CHARGED_PROJECTILES);
return chargedProjectiles != null && (chargedProjectiles.contains(ModItemRegister.LEASH_ROPE_ARROW.get()) || chargedProjectiles.contains(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get())) ? 1.0F : 0.0F;}
));
ItemProperties.register(Items.CROSSBOW, ResourceLocation.withDefaultNamespace("nestle_rope_arrow"),
((pStack, pLevel, pEntity, pSeed) -> {
ChargedProjectiles chargedProjectiles = pStack.get(DataComponents.CHARGED_PROJECTILES);
return chargedProjectiles != null && (chargedProjectiles.contains(ModItemRegister.NESTLE_ROPE_ARROW.get())) ? 1.0F : 0.0F;}
));
ItemProperties.register(Items.BOW, ResourceLocation.withDefaultNamespace("leash_rope_arrow_pulling"),
((pStack, pLevel, pEntity, pSeed) ->
(pEntity != null && pEntity.isUsingItem() && pEntity.getUseItem() == pStack && ILeashRopeArrow.isLeashRopeArrow(pStack, pEntity)) ? 1.0F : 0.0F
));
ItemProperties.register(Items.BOW, ResourceLocation.withDefaultNamespace("nestle_rope_arrow_pulling"),
((pStack, pLevel, pEntity, pSeed) ->
(pEntity != null && pEntity.isUsingItem() && pEntity.getUseItem() == pStack && INestleRopeArrow.isNestleRopeArrow(pStack, pEntity)) ? 1.0F : 0.0F
));
});
public static void onRegisterItemModels(RegisterItemModelsEvent event) {
event.register(ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "conditional_range"), ConditionalRangeItemModel.Unbaked.MAP_CODEC);
}
@SubscribeEvent
public static void registrySelectItemModelProperty(RegisterSelectItemModelPropertyEvent event) {
event.register(ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "charge_extend_type"), ChargeExtend.TYPE);
}
@SubscribeEvent
public static void registerKeyMapping(RegisterKeyMappingsEvent event) {
event.register(ModKeyMapping.KEY_APPLY_TALKAREA_PREFERENCE);
event.register(ModKeyMapping.KEY_ADD_LEASH_LENGTH);
event.register(ModKeyMapping.KEY_SUB_LEASH_LENGTH);
}
@SubscribeEvent
public static void onRegisterRenderer (EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(ModEntityRegister.NESTLE_ROPE_ARROW.get(), NestleRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.LEASH_ROPE_ARROW.get(), LeashRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.SPECTRAL_LEASH_ROPE_ARROW.get(), SpectralLeashRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.KID.get(), KidPlayerRenderer::create);
}
@SubscribeEvent
public static void onAddLayers (EntityRenderersEvent.AddLayers event){
PlayerRenderer renderer = event.getSkin(PlayerSkin.Model.WIDE);
if (renderer instanceof PlayerRenderer playerRenderer) {
playerRenderer.addLayer(new ChestItemLayerRenderer<>(playerRenderer, event.getContext().getItemInHandRenderer()));
playerRenderer.addLayer(new ChestItemLayerRenderer<>(playerRenderer, event.getContext().getEntityRenderDispatcher().getItemInHandRenderer()));
}
PlayerRenderer slimRenderer = event.getSkin(PlayerSkin.Model.SLIM);
if (slimRenderer instanceof PlayerRenderer slimPlayerRenderer) {
slimPlayerRenderer.addLayer(new ChestItemLayerRenderer<>(slimPlayerRenderer, event.getContext().getItemInHandRenderer()));
slimPlayerRenderer.addLayer(new ChestItemLayerRenderer<>(slimPlayerRenderer, event.getContext().getEntityRenderDispatcher().getItemInHandRenderer()));
}
}
@SubscribeEvent
public static void onRegisterItemColorHandlers (RegisterColorHandlersEvent.Item event){
event.register(
(color, i) -> i > 0
? -1
: FastColor.ARGB32.opaque(color.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY).getColor()),
ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get()
);
public static void RegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(ModEntityRegister.LEASH_ROPE_ARROW.get(), LeashRopeArrowRenderer::new);
event.registerEntityRenderer(ModEntityRegister.SPECTRAL_LEASH_ROPE_ARROW.get(), SpectralLeashRopeArrowRenderer::new);
}
}
}

View File

@ -1,28 +1,22 @@
package com.r3944realms.leashedplayer;
import com.mojang.brigadier.CommandDispatcher;
import com.r3944realms.leashedplayer.content.commands.*;
import com.r3944realms.leashedplayer.content.commands.LeashCommand;
import com.r3944realms.leashedplayer.content.commands.MotionCommand;
import com.r3944realms.leashedplayer.content.commands.TickCommand;
import com.r3944realms.leashedplayer.content.effects.ModPotionRegister;
import com.r3944realms.leashedplayer.content.entities.LittlePlayer;
import com.r3944realms.leashedplayer.content.entities.ModEntityRegister;
import com.r3944realms.leashedplayer.content.gamerules.GameruleRegistry;
import com.r3944realms.leashedplayer.content.gamerules.Server.OpenTOPNeededModeWhenScreenIsNotNull;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import com.r3944realms.leashedplayer.content.misc.LeadBreakItemBehavior;
import com.r3944realms.leashedplayer.network.client.BooleanGameRuleValueChangeData;
import com.r3944realms.leashedplayer.utils.Logger;
import com.r3944realms.leashedplayer.utils.Util;
import io.github.kunosayo.nestle.init.ModCreativeTab;
import net.minecraft.ChatFormatting;
import net.minecraft.commands.CommandSourceStack;
import net.minecraft.core.component.DataComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.ItemTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.animal.Fox;
import net.minecraft.world.item.CreativeModeTab;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.alchemy.PotionBrewing;
@ -33,13 +27,9 @@ import net.neoforged.bus.api.SubscribeEvent;
import net.neoforged.fml.common.EventBusSubscriber;
import net.neoforged.fml.event.lifecycle.FMLCommonSetupEvent;
import net.neoforged.neoforge.event.AnvilUpdateEvent;
import net.neoforged.neoforge.event.BuildCreativeModeTabContentsEvent;
import net.neoforged.neoforge.event.RegisterCommandsEvent;
import net.neoforged.neoforge.event.brewing.RegisterBrewingRecipesEvent;
import net.neoforged.neoforge.event.entity.EntityAttributeCreationEvent;
import net.neoforged.neoforge.event.entity.player.PlayerEvent;
import net.neoforged.neoforge.event.tick.EntityTickEvent;
import net.neoforged.neoforge.network.PacketDistributor;
public class CommonEventHandler {
@ -50,45 +40,13 @@ public class CommonEventHandler {
CommandDispatcher<CommandSourceStack> dispatcher = event.getDispatcher();
LeashCommand.register(dispatcher);
MotionCommand.register(dispatcher);
ChatCommand.register(dispatcher);
TickCommand.register(dispatcher);
DebugCommand.register(dispatcher);
}
@SubscribeEvent
public static void onJoinServer(PlayerEvent.PlayerLoggedInEvent event) {
PacketDistributor.sendToPlayer((ServerPlayer) event.getEntity(),
new BooleanGameRuleValueChangeData(
OpenTOPNeededModeWhenScreenIsNotNull.ID,
GameruleRegistry.getGameruleBoolValue(
event.getEntity().level(),
OpenTOPNeededModeWhenScreenIsNotNull.ID)
)
);
}
@SubscribeEvent
public static void OnRegisterPotionBrewing(RegisterBrewingRecipesEvent event) {
PotionBrewing.Builder builder = event.getBuilder();
builder.addMix(Potions.WATER, Items.SLIME_BALL, ModPotionRegister.NO_LEASH);
}
@SubscribeEvent
public static void OnAnvilUpdated(AnvilUpdateEvent event) {
String name = event.getName();
ItemStack left = event.getLeft();
if (left.is(Items.ANVIL) && name != null && name.equals("NeoForge")) {
event.setCost(1);
event.setOutput(ModItemRegister.NEOFORGE.get().getDefaultInstance());
} else if (left.is(ModItemRegister.NEOFORGE.get().asItem()) && name != null && name.equals("Forge")) {
ItemStack instance = Items.ANVIL.getDefaultInstance();
instance.set(DataComponents.CUSTOM_NAME, Component.literal("Forge").withStyle(ChatFormatting.BOLD).withStyle(ChatFormatting.AQUA));
event.setOutput(instance);
event.setCost(1);
}
}
@SubscribeEvent
public static void OnLivingTickEvent(EntityTickEvent.Post event) {
Entity entity = event.getEntity();
@ -96,62 +54,55 @@ public class CommonEventHandler {
if (level.isClientSide()) {
return;
}
if (entity instanceof Fox fox) {
if (fox.getMainHandItem().is(ItemTags.ANVIL)) {
fox.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
Util.throwItemTowardsLook(fox, ModItemRegister.NEOFORGE.get(), 0.3f, 0.1f);
fox.playSound(fox.getEatingSound(ItemStack.EMPTY));
} else if (fox.getMainHandItem().is(ModItemRegister.NEOFORGE.get())) {
// 繞圈參數
float rotationSpeed = 10.0f; // tick 旋轉的角度
// 計算新的旋轉角度
fox.yBodyRot += rotationSpeed; // 身體旋轉
fox.yHeadRot += rotationSpeed; // 頭部旋轉
fox.yRotO += rotationSpeed; // 當前旋轉角度
fox.yHeadRotO += rotationSpeed; // 頭部的當前旋轉角度
if (entity instanceof Fox fox) {
if (fox.getMainHandItem().is(ItemTags.ANVIL)) {
fox.setItemSlot(EquipmentSlot.MAINHAND, ItemStack.EMPTY);
Util.throwItemTowardsLook(fox, ModItemRegister.NEOFORGE.get(), 0.3f, 0.1f);
fox.playSound(SoundEvents.FOX_EAT);
} else if (fox.getMainHandItem().is(ModItemRegister.NEOFORGE.get())) {
// 繞圈參數
float rotationSpeed = 10.0f; // tick 旋轉的角度
// 計算新的旋轉角度
fox.yBodyRot += rotationSpeed; // 身體旋轉
fox.yHeadRot += rotationSpeed; // 頭部旋轉
fox.yRotO += rotationSpeed; // 當前旋轉角度
fox.yHeadRotO += rotationSpeed; // 頭部的當前旋轉角度
// 確保旋轉角度不超出 360 重置為 0 以便持續旋轉
if (fox.yBodyRot >= 360) fox.yBodyRot -= 360;
if (fox.yHeadRot >= 360) fox.yHeadRot -= 360;
// 確保旋轉角度不超出 360 重置為 0 以便持續旋轉
if (fox.yBodyRot >= 360) fox.yBodyRot -= 360;
if (fox.yHeadRot >= 360) fox.yHeadRot -= 360;
}
}
}
}
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
public static class Mod extends CommonEventHandler {
@SubscribeEvent
public static void onCommonSetup(FMLCommonSetupEvent event) {
event.enqueueWork(() -> {
if (LeashedPlayer.IS_NESTLE_LOADED) {
Logger.logger.info("[LeashedPlayer] Hello, Nestle");
DispenserBlock.registerProjectileBehavior(ModItemRegister.NESTLE_ROPE_ARROW.get());
}
DispenserBlock.registerProjectileBehavior(ModItemRegister.LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get());
DispenserBlock.registerBehavior(ModItemRegister.AMETHYST_SHEARS.get(), new LeadBreakItemBehavior());
});
@SubscribeEvent
public static void OnAnvilUpdated(AnvilUpdateEvent event) {
String name = event.getName();
ItemStack left = event.getLeft();
if (left.is(Items.ANVIL) && name != null && name.equals("NeoForge")) {
event.setCost(1);
event.setOutput(ModItemRegister.NEOFORGE.get().getDefaultInstance());
} else if (left.is(ModItemRegister.NEOFORGE.get().asItem()) && name != null && name.equals("Forge")) {
ItemStack instance = Items.ANVIL.getDefaultInstance();
instance.set(DataComponents.CUSTOM_NAME, Component.literal("Forge").withStyle(ChatFormatting.BOLD).withStyle(ChatFormatting.AQUA));
event.setOutput(instance);
event.setCost(1);
}
@SubscribeEvent
public static void onEntityAttributeEvent(EntityAttributeCreationEvent event) {
event.put(ModEntityRegister.KID.get(), LittlePlayer.createAttributes().build());
}
@SubscribeEvent
public static void onBuiltCreativeModeTabContents(BuildCreativeModeTabContentsEvent event) {
if (LeashedPlayer.IS_NESTLE_LOADED){
CreativeModeTab tab = event.getTab();
if (tab == ModCreativeTab.MAIN_TABS.get()) {
event.accept(ModItemRegister.NESTLE_ROPE_ARROW.get());
}
}
}
}
}
@EventBusSubscriber(modid = LeashedPlayer.MOD_ID, bus = EventBusSubscriber.Bus.MOD)
public static class Mod extends CommonEventHandler {
@SubscribeEvent
public static void onCommonSetup(FMLCommonSetupEvent event) {
event.enqueueWork(() -> {
DispenserBlock.registerProjectileBehavior(ModItemRegister.LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get());
DispenserBlock.registerProjectileBehavior(ModItemRegister.SPECTRAL_LEASH_ROPE_ARROW.get());
DispenserBlock.registerBehavior(ModItemRegister.AMETHYST_SHEARS.get(), new LeadBreakItemBehavior());
});
}
}
}

View File

@ -12,7 +12,6 @@ import com.r3944realms.leashedplayer.content.paintings.ModPaintingsRegister;
import com.r3944realms.leashedplayer.content.sounds.ModSoundRegister;
import com.r3944realms.leashedplayer.utils.Util;
import net.neoforged.bus.api.IEventBus;
import net.neoforged.fml.ModList;
import net.neoforged.fml.ModLoadingContext;
import net.neoforged.fml.common.Mod;
import net.neoforged.fml.config.ModConfig;
@ -21,27 +20,24 @@ import static com.r3944realms.leashedplayer.utils.Logger.logger;
@Mod(LeashedPlayer.MOD_ID)
public class LeashedPlayer {
public static final String MOD_ID = "leashedplayer";
public static boolean IS_NESTLE_LOADED;
private static Double M1;//拴繩掉落距離倍基數
private static Double M2;//繩箭拴繩掉落距離倍基數
private static Integer M3; //拴绳最小长度
private static Integer M4; //拴绳最大长度
public LeashedPlayer(IEventBus event) {
ModItemRegister.register(event);
ModPaintingsRegister.register(event);
ModRecipeRegister.register(event);
ModSoundRegister.register(event);
ModPaintingsRegister.register(event);
ModEffectRegister.register(event);
ModPotionRegister.register(event);
ModEntityRegister.register(event);
ModCreativeTab.register(event);
ModCriteriaTriggers.register(event);
ModRecipeRegister.register(event);
initiation();
}
private void initiation() {
logger.info("Initializing LeashedPlayer Mod");
IS_NESTLE_LOADED = ModList.get().isLoaded("nestle");
String leashedPlayerCommonConfig = "LeashedPlayerCommonConfig";
Util.configFileCreate(new String[]{leashedPlayerCommonConfig});
ModLoadingContext.get().getActiveContainer().registerConfig(ModConfig.Type.COMMON, LeashPlayerCommonConfig.SPEC, MOD_ID + "/" + leashedPlayerCommonConfig + "/LeashPlayer.toml");
@ -71,5 +67,4 @@ public class LeashedPlayer {
return M4;
}
}

View File

@ -0,0 +1,540 @@
package com.r3944realms.leashedplayer.client.renderer;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.datafixers.util.Either;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import com.r3944realms.leashedplayer.modInterface.ILivingEntityExtension;
import com.r3944realms.leashedplayer.modInterface.IPlayerRenderStateExtension;
import com.r3944realms.leashedplayer.modInterface.PlayerLeashable;
import net.minecraft.client.Camera;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.AbstractClientPlayer;
import net.minecraft.client.renderer.LightTexture;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.core.BlockPos;
import net.minecraft.util.Mth;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Leashable;
import net.minecraft.world.entity.decoration.LeashFenceKnotEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.entity.vehicle.NewMinecartBehavior;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.LightLayer;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.joml.Matrix4f;
import java.util.List;
import java.util.UUID;
@OnlyIn(Dist.CLIENT)
public class LeashRendererUtil {
public static void renderLeash(PoseStack poseStack, MultiBufferSource buffer, EntityRenderState.LeashState leashState) {
float f = 0.025F;
float f1 = (float)(leashState.end.x - leashState.start.x);
float f2 = (float)(leashState.end.y - leashState.start.y + 0.2);
float f3 = (float)(leashState.end.z - leashState.start.z);
float f4 = Mth.invSqrt(f1 * f1 + f3 * f3) * 0.025F / 2.0F;
float f5 = f3 * f4;
float f6 = f1 * f4;
poseStack.pushPose();
poseStack.translate(leashState.offset.add(0, -0.2, -0.2));
VertexConsumer vertexconsumer = buffer.getBuffer(RenderType.leash());
Matrix4f matrix4f = poseStack.last().pose();
for (int i = 0; i <= 24; i++) {
addVertexPair(
vertexconsumer,
matrix4f,
f1,
f2,
f3,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.025F,
f5,
f6,
i,
false
);
}
for (int j = 24; j >= 0; j--) {
addVertexPair(
vertexconsumer,
matrix4f,
f1,
f2,
f3,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.0F,
f5,
f6,
j,
true
);
}
poseStack.popPose();
}
/**
* <h1>1. 角度与弧度转换</h1>
* {@snippet lang=java :
* double d0 = (double)(pEntity.getPreciseBodyRotation(pPartialTick) * (float)(Math.PI / 180.0)) + (Math.PI / 2);
* }
* <ul>
* <li><code>pEntity.getPreciseBodyRotation(pPartialTick)</code> 返回实体的旋转角度通常是以度为单位/li>
* <li> <code>(Math.PI / 180.0)</code> 是将度数转换为弧度的乘数因为大多数三角函数 <code>cos</code> <code>sin</code>都需要弧度值</li>
* <li><code>+ (Math.PI / 2)</code> 用于将结果平移90度四分之一圆可能是为了校正方向或设置起始方向 </li>
* </ul>
*
* <p>
* <h1> 2. 三角函数计算位移</h1>
* {@snippet lang=java :
* double d1 = Math.cos(d0) * vec31.z + Math.sin(d0) * vec31.x;
* double d2 = Math.sin(d0) * vec31.z - Math.cos(d0) * vec31.x;
* }
* <ul>
* <li><code>d1</code> <code>d2</code> 是利用三角函数 <code>cos</code> <code>sin</code> 计算出来的位移量用于确定实体相对于其旋转的实际位置</li>
* <li><code>Math.cos(d0) * vec31.z</code> <code>Math.sin(d0) * vec31.x</code> 分别计算沿 X Z 轴的位移分量这种计算通常用于旋转一个点或向量</li>
* <li>两个公式结合起来用于旋转平面内的一个点 <code>(vec31.x, vec31.z)</code>从而得到旋转后的新坐标</li>
* </ul>
* <p>
* <h1> 3. 线性插值 (Lerp) </h1>
* {@snippet lang=java :
* double d3 = Mth.lerp(pPartialTick, pEntity.xo, pEntity.getX()) + d1;
* double d4 = Mth.lerp(pPartialTick, pEntity.yo, pEntity.getY()) + vec31.y;
* double d5 = Mth.lerp(pPartialTick, pEntity.zo, pEntity.getZ()) + d2;
* }
* <ul>
* <li><code>Mth.lerp</code> 是线性插值函数通常用于在两个值之间平滑过渡</li>
* <li><code>pEntity.xo</code>, <code>pEntity.yo</code>, <code>pEntity.zo</code> 是实体在上一个刻度tick中的位置 <code>pEntity.getX()</code>, <code>pEntity.getY()</code>, <code>pEntity.getZ()</code> 是当前刻度的位置</li>
* <li><code>pPartialTick</code> 介于 <code>0</code> <code>1</code> 之间用来平滑过渡使得动画更加流畅</li>
* </ul>
* <p>
* <h1> 4. 向量差值 </h1>
* {@snippet lang=java :
* float f = (float)(vec3.x - d3);
* float f1 = (float)(vec3.y - d4);
* float f2 = (float)(vec3.z - d5);
* }
* <ul>
* <li>计算两个点<code>vec3</code> <code>(d3, d4, d5)</code>之间的差值得到的 <code>f</code><code>f1</code><code>f2</code> 是向量差用于后续的渲染计算</li>
* </ul>
* <p>
* <h1> 5. 逆平方根与比例因子 </h1>
* {@snippet lang=java :
* float f4 = Mth.invSqrt(f * f + f2 * f2) * 0.025F / 2.0F;
* }
* <ul>
* <li><code>Mth.invSqrt</code> 计算的是逆平方根通常用于归一化向量或调整比例</li>
* <li><code>f * f + f2 * f2</code> 是计算向量 <code>(f, f2)</code> 的平方和用于得到其长度的平方</li>
* <li>乘以 <code>0.025F / 2.0F</code> 用于缩放结果使得线条在渲染时具有合适的比例</li>
* </ul>
* <p>
* <h1> 6. 循环绘制 </h1>
* {@snippet lang=java :
* for (int i1 = 0; i1 <= 24; i1++) {
* addVertexPair(vertexconsumer, matrix4f, f, f1, f2, i, j, k, l, 0.025F, 0.025F, f5, f6, i1, false);
* }
* }
* <ul>
* <li>循环从 <code>0</code> <code>24</code>用于创建24个顶点对形成一个链状结构或绳索的外观</li>
* <li>每个循环迭代都会更新顶点的位置颜色光照等属性使得链状结构被绘制出来</li>
* </ul>
* <p>
* <h1> 总结 </h1>
* 这些数学运算主要用于计算实体在三维空间中的位置和方向以确保在渲染链状结构如拴住的绳索链条能够跟随实体的移动和旋转并正确显示在图形编程中这些计算非常常见尤其是在处理旋转插值和光照效果时
*/
public static void renderLeash(
PoseStack poseStack,
MultiBufferSource bufferSource,
PlayerRenderState playerRenderState
) {
float f = 0.025F;
// 获得绳索持有者的位置
PlayerLeashState leashState = ((IPlayerRenderStateExtension)playerRenderState).getPlayerLeashState();
if (leashState == null)
return;
Vec3 Holder = leashState.pos;//TODO问题修复
Vec3 o = leashState.o;
// 计算实体的朝向角度弧度
float partialTick = playerRenderState.partialTick;
double entityRotationAngleRadians = (double)(leashState.getPreciseBodyRotation(partialTick) * (float) (Math.PI / 180.0)) + (Math.PI / 2);
// 计算实体的绳索偏移此处add偏移让渲染拴绳显示在玩家头部下大约在脖子处
// Logger.logger.info("eyeHeight:{}",playerRenderState.eyeHeight);
Vec3 cameraEntityLeashOffset = new Vec3(0.0, leashState.eyeHeight , playerRenderState.boundingBoxWidth * 0.4F).add(0, -0.2, -0.2);
double leashOffsetX = Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.z + Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
double leashOffsetZ = Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.z - Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
// 计算实体当前的实际位置
double entityPosX = Mth.lerp(partialTick, o.x, playerRenderState.x) + leashOffsetX;
double entityPosY = Mth.lerp(partialTick, o.y, playerRenderState.y) + cameraEntityLeashOffset.y;
double entityPosZ = Mth.lerp(partialTick, o.z, playerRenderState.z) + leashOffsetZ;
// 计算绳索的相对位置差
float deltaX = (float)(Holder.x - entityPosX);
float deltaY = (float)(Holder.y - entityPosY);
float deltaZ = (float)(Holder.z - entityPosZ);
// 计算比例因子用于调节绳索的粗细
float leashLengthRatio = Mth.invSqrt(deltaX * deltaX + deltaZ * deltaZ) * 0.025F / 2.0F;
// 计算比例因子用于调节绳索的粗细
float leashXZScaleX = deltaZ * leashLengthRatio;
float leashXZScaleZ = deltaX * leashLengthRatio;
poseStack.pushPose();
poseStack.translate(leashOffsetX, cameraEntityLeashOffset.y,leashOffsetZ);
VertexConsumer vertexconsumer = bufferSource.getBuffer(RenderType.leash());
Matrix4f matrix4f = poseStack.last().pose();
for (int i = 0; i <= 24; i++) {
addVertexPair(
vertexconsumer,
matrix4f,
deltaX,
deltaY,
deltaZ,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.025F,
leashXZScaleX,
leashXZScaleZ,
i,
false
);
}
for (int j = 24; j >= 0; j--) {
addVertexPair(
vertexconsumer,
matrix4f,
deltaX,
deltaY,
deltaZ,
leashState.startBlockLight,
leashState.endBlockLight,
leashState.startSkyLight,
leashState.endSkyLight,
0.025F,
0.0F,
leashXZScaleX,
leashXZScaleZ,
j,
true
);
}
poseStack.popPose();
}
protected static void addVertexPair(
VertexConsumer buffer,
Matrix4f pose,
float startX,
float startY,
float startZ,
int entityBlockLight,
int holderBlockLight,
int entitySkyLight,
int holderSkyLight,
float yOffset,
float dy,
float dx,
float dz,
int index,
boolean reverse
) {
float f = (float)index / 24.0F;
int i = (int)Mth.lerp(f, (float)entityBlockLight, (float)holderBlockLight);
int j = (int)Mth.lerp(f, (float)entitySkyLight, (float)holderSkyLight);
int k = LightTexture.pack(i, j);
float f1 = index % 2 == (reverse ? 1 : 0) ? 0.7F : 1.0F;
float f2 = 0.5F * f1;
float f3 = 0.4F * f1;
float f4 = 0.3F * f1;
float f5 = startX * f;
float f6 = startY > 0.0F ? startY * f * f : startY - startY * (1.0F - f) * (1.0F - f);
float f7 = startZ * f;
buffer.addVertex(pose, f5 - dx, f6 + dy, f7 + dz).setColor(f2, f3, f4, 1.0F).setLight(k);
buffer.addVertex(pose, f5 + dx, f6 + yOffset - dy, f7 - dz).setColor(f2, f3, f4, 1.0F).setLight(k);
}
public static <E extends Entity> void renderLeashForCamera(
Camera camera,
float partialTick,
PoseStack poseStack,
MultiBufferSource bufferSource,
E leashHolder,
Vec3 holderOffset
) {
poseStack.pushPose();
// Logger.logger.info("eyeHeight{}", camera.getEntity().getEyeHeight());
// 获得绳索持有者的位置
Vec3 leashHolderPosition = leashHolder.getRopeHoldPosition(partialTick).add(holderOffset);
// 获取当前观察的实体
Entity cameraEntity = camera.getEntity();
// 计算实体的朝向角度弧度
double entityRotationAngleRadians = (double)(cameraEntity.getPreciseBodyRotation(partialTick) * (float) (Math.PI / 180.0)) + (Math.PI / 2);
// 计算实体的绳索偏移此处add偏移让渲染拴绳显示在玩家头部下大约在脖子处
Vec3 cameraEntityLeashOffset = cameraEntity.getLeashOffset(partialTick).add(0, -0.2, -0.5);
double leashOffsetX = Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.z + Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
double leashOffsetZ = Math.sin(entityRotationAngleRadians) * cameraEntityLeashOffset.z - Math.cos(entityRotationAngleRadians) * cameraEntityLeashOffset.x;
// 计算实体当前的实际位置
double entityPosX = Mth.lerp(partialTick, cameraEntity.xo, cameraEntity.getX()) + leashOffsetX;
double entityPosY = Mth.lerp(partialTick, cameraEntity.yo, cameraEntity.getY()) + cameraEntityLeashOffset.y;
double entityPosZ = Mth.lerp(partialTick, cameraEntity.zo, cameraEntity.getZ()) + leashOffsetZ;
// 在当前变换矩阵上应用偏移
poseStack.translate(leashOffsetX, cameraEntityLeashOffset.y , leashOffsetZ);
// 计算绳索的相对位置差
float deltaX = (float)(leashHolderPosition.x - entityPosX);
float deltaY = (float)(leashHolderPosition.y - entityPosY);
float deltaZ = (float)(leashHolderPosition.z - entityPosZ);
// 获取顶点消费者用于绘制绳索
VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.leash());
Matrix4f matrix = poseStack.last().pose();
// 计算比例因子用于调节绳索的粗细
float leashLengthRatio = Mth.invSqrt(deltaX * deltaX + deltaZ * deltaZ) * 0.025F / 2.0F;
float leashXZScaleX = deltaZ * leashLengthRatio;
float leashXZScaleZ = deltaX * leashLengthRatio;
// 获取光照信息
BlockPos cameraEntityBlockPos = BlockPos.containing(cameraEntity.getEyePosition(partialTick));
BlockPos leashHolderBlockPos = BlockPos.containing(leashHolder.getEyePosition(partialTick));
int cameraEntityBlockLightLevel = getBlockLightLevel(cameraEntity, cameraEntityBlockPos);
int leashHolderBlockLightLevel = getBlockLightLevel(leashHolder, leashHolderBlockPos); //getBlockLightLevel(leashHolder, leashHolderBlockPos);
int cameraEntitySkyLightLevel = cameraEntity.level().getBrightness(LightLayer.SKY, cameraEntityBlockPos);
int leashHolderSkyLightLevel = cameraEntity.level().getBrightness(LightLayer.SKY, leashHolderBlockPos);
// 绘制绳索的上半部分
for (int segment = 0; segment <= 24; segment++) {
addVertexPair(vertexConsumer, matrix, deltaX, deltaY, deltaZ, cameraEntityBlockLightLevel, leashHolderBlockLightLevel, cameraEntitySkyLightLevel, leashHolderSkyLightLevel, 0.025F, 0.025F, leashXZScaleX, leashXZScaleZ, segment, false);
}
// 绘制绳索的下半部分
for (int segment = 24; segment >= 0; segment--) {
addVertexPair(vertexConsumer, matrix, deltaX, deltaY, deltaZ, cameraEntityBlockLightLevel, leashHolderBlockLightLevel, cameraEntitySkyLightLevel, leashHolderSkyLightLevel, 0.025F, 0.0F, leashXZScaleX, leashXZScaleZ, segment, true);
}
poseStack.popPose();
}
public static void levelRenderLeash(ClientLevel level, Camera pCamera, PoseStack poseStack, MultiBufferSource.BufferSource multibuffersource$buffersource) {
for(Entity entity : level.entitiesForRendering()) {
//对于玩家实体拴绳渲染从第一人称视角
if (entity instanceof AbstractClientPlayer abstractClientPlayer) {
if(!(pCamera.getEntity() instanceof AbstractClientPlayer)) continue;
Minecraft mc = Minecraft.getInstance();
if (mc.options.getCameraType().isFirstPerson()) {
Leashable.LeashData leashDataFromEntityData = ((PlayerLeashable) abstractClientPlayer).getLeashDataFromEntityData();
if(leashDataFromEntityData == null) continue;
Either<UUID, BlockPos> delayedLeashInfo = leashDataFromEntityData.delayedLeashInfo;
if(delayedLeashInfo != null) {
float partialTickTime = pCamera.getPartialTickTime();
Vec3 position = pCamera.getPosition();
double dX = Mth.lerp(partialTickTime, abstractClientPlayer.xOld, abstractClientPlayer.getX()) - position.x;
double dY = Mth.lerp(partialTickTime, abstractClientPlayer.yOld, abstractClientPlayer.getY()) - position.y;
double dZ = Mth.lerp(partialTickTime, abstractClientPlayer.zOld, abstractClientPlayer.getZ()) - position.z;
Vec3 vec3 = getRenderOffset(entity, partialTickTime);
double dX_ = dX + vec3.x();
double dY_ = dY + vec3.y();
double dZ_ = dZ + vec3.z();
poseStack.pushPose();
poseStack.translate(dX_, dY_, dZ_);
if (delayedLeashInfo.right().isPresent() && delayedLeashInfo.left().isEmpty()) {
renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, LeashFenceKnotEntity.getOrCreateKnot(level, delayedLeashInfo.right().get()), Vec3.ZERO);
} else if (delayedLeashInfo.right().isEmpty() && delayedLeashInfo.left().isPresent()) {
Player playerByUUID = level.getPlayerByUUID(delayedLeashInfo.left().get());
if (playerByUUID != null) {
renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, playerByUUID, Vec3.ZERO);
} else {
double MaxLeashLength = ((ILivingEntityExtension) abstractClientPlayer).getLeashLength() * LeashedPlayer.M1() * LeashedPlayer.M2();
List<Entity> entities = level.getEntities(
null,
new AABB(
abstractClientPlayer.getX() - MaxLeashLength,
abstractClientPlayer.getY() - MaxLeashLength,
abstractClientPlayer.getZ() - MaxLeashLength,
abstractClientPlayer.getX() + MaxLeashLength,
abstractClientPlayer.getY() + MaxLeashLength,
abstractClientPlayer.getZ() + MaxLeashLength
)
);
Entity holder = null;
for (Entity entity_ : entities) {
if(entity_.getUUID().equals(delayedLeashInfo.left().get())) {
holder = entity_;
break;
}
}
if (holder != null) {
if(holder instanceof LeashRopeArrow) {
renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder, new Vec3(0.,-0.09, 0));//TODO: 待擴展Vec3吗
}
else renderLeashForCamera(pCamera, partialTickTime, poseStack, multibuffersource$buffersource, holder, Vec3.ZERO);
}
}
break;
}
}
}
}
}
}
public static Vec3 getRenderOffset(Entity entity, float partialTickTime) {
Vec3 ret = Vec3.ZERO;
if(entity.isPassenger()
&& entity.getVehicle() instanceof AbstractMinecart abstractminecart
&& abstractminecart.getBehavior() instanceof NewMinecartBehavior newminecartbehavior
&& newminecartbehavior.cartHasPosRotLerp()
) {
double d2 = Mth.lerp(partialTickTime, abstractminecart.xOld, abstractminecart.getX());
double d0 = Mth.lerp(partialTickTime, abstractminecart.yOld, abstractminecart.getY());
double d1 = Mth.lerp(partialTickTime, abstractminecart.zOld, abstractminecart.getZ());
ret = newminecartbehavior.getCartLerpPosition(partialTickTime).subtract(new Vec3(d2, d0, d1));
}
return ret;
}
public static void createPlayerLeashState(AbstractClientPlayer abstractClientPlayer, IPlayerRenderStateExtension playerRenderState, float partialTick) {
Leashable.LeashData leashDataFromEntityData = ((PlayerLeashable) abstractClientPlayer).getLeashDataFromEntityData();
Leashable.LeashData leashData = ((PlayerLeashable) abstractClientPlayer).getLeashData();
PlayerRenderState playerRs = (PlayerRenderState)playerRenderState;
if (leashDataFromEntityData != null) {
Entity leashHolder = leashDataFromEntityData.leashHolder;
Either<UUID, BlockPos> delayedLeashInfo = leashDataFromEntityData.delayedLeashInfo;
PlayerLeashState playerLeashState = new PlayerLeashState();
if (delayedLeashInfo != null) {
createPlayerLeashState_(abstractClientPlayer, playerRenderState, leashDataFromEntityData, delayedLeashInfo, playerLeashState, partialTick);
BlockPos blockpos1 = BlockPos.containing(abstractClientPlayer.getEyePosition(partialTick));
playerLeashState.startBlockLight = getBlockLightLevel(abstractClientPlayer, blockpos1);
playerLeashState.startSkyLight = abstractClientPlayer.level().getBrightness(LightLayer.SKY, blockpos1);
} else if(leashHolder != null) {
createPlayerLeashState__(abstractClientPlayer, playerRenderState, leashHolder, playerLeashState, partialTick);
} else {
playerRenderState.setPlayerLeashState(null);
}
} else if(leashData != null) {
playerRs.leashState = null;
Entity leashHolder = ((PlayerLeashable) abstractClientPlayer).getLeashHolder();
PlayerLeashState playerLeashState = playerRenderState.getPlayerLeashState();
if (leashHolder != null & playerLeashState != null) {
float f = leashHolder.getPreciseBodyRotation(partialTick) * (float) (Math.PI / 180.0);
Vec3 vec3 = abstractClientPlayer.getLeashOffset(partialTick).yRot(-f);
BlockPos blockpos1 = BlockPos.containing(abstractClientPlayer.getEyePosition(partialTick));
BlockPos blockpos = BlockPos.containing(leashHolder.getEyePosition(partialTick));
playerLeashState.vanilaLeashState = new EntityRenderState.LeashState();
EntityRenderState.LeashState entityrenderstate$leashstate = playerLeashState.vanilaLeashState;
entityrenderstate$leashstate.offset = vec3;
entityrenderstate$leashstate.start = abstractClientPlayer.getPosition(partialTick).add(vec3);
entityrenderstate$leashstate.end = leashHolder.getRopeHoldPosition(partialTick);
entityrenderstate$leashstate.startBlockLight = getBlockLightLevel(abstractClientPlayer, blockpos1);
entityrenderstate$leashstate.endBlockLight = getBlockLightLevel(leashHolder, blockpos);
entityrenderstate$leashstate.startSkyLight = abstractClientPlayer.level().getBrightness(LightLayer.SKY, blockpos1);
entityrenderstate$leashstate.endSkyLight = abstractClientPlayer.level().getBrightness(LightLayer.SKY, blockpos);
} else {
playerRenderState.setPlayerLeashState(null);
}
} else {
playerRenderState.setPlayerLeashState(null);
}
}
private static <T extends Entity> int getBlockLightLevel(T entity, BlockPos pos) {
return entity.isOnFire() ? 15 : entity.level().getBrightness(LightLayer.BLOCK, pos);
}
private static int getBlockLightLevel(Level level, BlockPos pos) {
return level.getBrightness(LightLayer.BLOCK, pos);
}
private static void createPlayerLeashState__(AbstractClientPlayer abstractClientPlayer, IPlayerRenderStateExtension playerRenderState, Entity leashHolder, PlayerLeashState playerLeashState, float partialTick) {
playerLeashState.pos = leashHolder.position().add(0.0, leashHolder.getEyeHeight() * 0.6, -0.2);
playerLeashState.o = abstractClientPlayer.getPosition(partialTick);
playerLeashState.yRotO = abstractClientPlayer.yRotO;
playerLeashState.yRot = abstractClientPlayer.getYRot();
playerLeashState.eyeHeight = abstractClientPlayer.getEyeHeight();
playerRenderState.setPlayerLeashState(playerLeashState);
}
private static void createPlayerLeashState_(AbstractClientPlayer abstractClientPlayer, IPlayerRenderStateExtension playerRenderState, Leashable.LeashData leashDataFromEntityData, Either<UUID, BlockPos> delayedLeashInfo, PlayerLeashState playerLeashState, float partialTick) {
Minecraft mc = Minecraft.getInstance();
ClientLevel level = mc.level;
if (delayedLeashInfo.right().isPresent() && delayedLeashInfo.left().isEmpty()) {
assert level != null;
playerLeashState.pos = delayedLeashInfo.right().get().getCenter();
playerLeashState.endBlockLight = getBlockLightLevel(level, delayedLeashInfo.right().get());
playerLeashState.endSkyLight = level.getBrightness(LightLayer.SKY, delayedLeashInfo.right().get());
} else if (delayedLeashInfo.right().isEmpty() && delayedLeashInfo.left().isPresent()) {
assert level != null;
Player playerByUUID = level.getPlayerByUUID(delayedLeashInfo.left().get());
if (playerByUUID != null) {
playerLeashState.pos = playerByUUID.position().add(0.0, playerByUUID.getEyeHeight() * 0.6, 0);
} else {
double breakDistanceTime = (leashDataFromEntityData.leashHolder instanceof LeashRopeArrow) ? LeashedPlayer.M1() * LeashedPlayer.M2() : LeashedPlayer.M1();
double MaxLeashLength = ((ILivingEntityExtension) abstractClientPlayer).getLeashLength() * breakDistanceTime;
List<Entity> entities = level.getEntities(
null,
new AABB(
abstractClientPlayer.getX() - MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getY() - MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getZ() - MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getX() + MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getY() + MaxLeashLength * LeashedPlayer.M2(),
abstractClientPlayer.getZ() + MaxLeashLength * LeashedPlayer.M2()
)
);
Entity holder = null;
for (Entity entity_ : entities) {
if (entity_.getUUID().equals(delayedLeashInfo.left().get())) {
holder = entity_;
break;
}
}
if (holder != null) {
playerLeashState.pos = holder.position().add(0.0, holder.getEyeHeight() * 0.6, 0);//TODO: 待擴展Vec3
playerLeashState.endBlockLight = getBlockLightLevel(level, holder.getOnPos());
playerLeashState.endSkyLight = level.getBrightness(LightLayer.SKY, holder.getOnPos());
} else {
playerLeashState.pos = abstractClientPlayer.position();
}
}
}
playerLeashState.o = abstractClientPlayer.getPosition(partialTick);
playerLeashState.yRotO = abstractClientPlayer.yRotO;
playerLeashState.yRot = abstractClientPlayer.getYRot();
playerLeashState.eyeHeight = abstractClientPlayer.getEyeHeight();
playerRenderState.setPlayerLeashState(playerLeashState);
}
}

View File

@ -0,0 +1,41 @@
package com.r3944realms.leashedplayer.client.renderer;
import net.minecraft.client.renderer.entity.state.EntityRenderState;
import net.minecraft.util.Mth;
import net.minecraft.world.phys.Vec3;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
@OnlyIn(Dist.CLIENT)
public class PlayerLeashState {
public Vec3 o, pos, offset;
public float yRotO, yRot;
public float eyeHeight;
public int startBlockLight;
public int endBlockLight;
public int startSkyLight;
public int endSkyLight;
@Nullable
public EntityRenderState.LeashState vanilaLeashState;
public float getPreciseBodyRotation(float pPartialTick) {
return Mth.lerp(pPartialTick, this.yRotO, this.yRot);
}
public PlayerLeashState() {
this.offset = Vec3.ZERO;
this.o = Vec3.ZERO;
this.pos = Vec3.ZERO;
this.yRot = 0.0f;
this.yRotO = 0.0f;
this.eyeHeight = 0.0f;
this.startBlockLight = 0;
this.endBlockLight = 0;
this.startSkyLight = 15;
this.endSkyLight = 15;
this.vanilaLeashState = null;
}
}

View File

@ -0,0 +1,13 @@
package com.r3944realms.leashedplayer.client.renderer;
import net.minecraft.world.entity.LivingEntity;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class PlayerSlotItemLayerState {
public LivingEntity entity;
public PlayerSlotItemLayerState(LivingEntity entity) {
this.entity = entity;
}
}

View File

@ -0,0 +1,120 @@
package com.r3944realms.leashedplayer.client.renderer.entities;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import com.r3944realms.leashedplayer.modInterface.IPlayerRenderStateExtension;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.client.renderer.entity.state.PlayerRenderState;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
public class ChestItemLayerRenderer<S extends PlayerRenderState, M extends EntityModel<S>> extends RenderLayer<S, M> {
private final ItemInHandRenderer heldItemRenderer;
public ChestItemLayerRenderer(RenderLayerParent<S, M> context, ItemInHandRenderer heldItemRenderer) {
super(context);
this.heldItemRenderer = heldItemRenderer;
}
@Override
public void render(@NotNull PoseStack poseStack, @NotNull MultiBufferSource bufferSource, int packedLight, @NotNull S renderState, float yRot, float xRot) {
ItemDisplayContext mode = ItemDisplayContext.FIXED;
IPlayerRenderStateExtension rs = (IPlayerRenderStateExtension) renderState;
LivingEntity entity = rs.getPlayerSlotItemLayerState().entity;
ItemStack chestStack = entity.getItemBySlot(EquipmentSlot.CHEST);
if (!chestStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(chestStack).equals(EquipmentSlot.CHEST))) {
poseStack.pushPose();
((PlayerModel) this.getParentModel()).body.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.translate(0, -0.24f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, poseStack, bufferSource, packedLight);
poseStack.scale(1.01f, 1.01f, 1.01f);
poseStack.translate(0, -1 / 4f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).rightArm.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(-1/12f, 0, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, poseStack, bufferSource, packedLight);
poseStack.scale(0.99f, 0.99f, 0.99f);
poseStack.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).leftArm.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(1/12f, 0, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, poseStack, bufferSource, packedLight);
poseStack.scale(0.99f, 0.99f, 0.99f);
poseStack.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, poseStack, bufferSource, packedLight);
poseStack.popPose();
}
}
ItemStack legsStack = entity.getItemBySlot(EquipmentSlot.LEGS);
if (!legsStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(legsStack).equals(EquipmentSlot.LEGS))) {
poseStack.pushPose();
((PlayerModel) this.getParentModel()).rightLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(0, -1/6f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, poseStack, bufferSource, packedLight);
poseStack.scale(1.01f, 1.01f, 1.01f);
poseStack.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).leftLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(2/3f, 2/3f, 2/3f);
poseStack.translate(0, -1/6f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, poseStack, bufferSource, packedLight);
poseStack.scale(1.01f, 1.01f, 1.01f);
poseStack.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, poseStack, bufferSource, packedLight);
poseStack.popPose();
}
}
ItemStack feetStack = entity.getItemBySlot(EquipmentSlot.FEET);
if (!feetStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(feetStack).equals(EquipmentSlot.FEET))) {
poseStack.pushPose();
((PlayerModel) this.getParentModel()).rightLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(0.75f, 0.75f, 0.75f);
poseStack.translate(0, -0.8f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, poseStack, bufferSource, packedLight);
poseStack.popPose();
poseStack.pushPose();
((PlayerModel) this.getParentModel()).leftLeg.translateAndRotate(poseStack);
poseStack.mulPose(Axis.XP.rotationDegrees(180));
poseStack.scale(0.75f, 0.75f, 0.75f);
poseStack.translate(0, -0.8f, 0);
poseStack.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, poseStack, bufferSource, packedLight);
poseStack.popPose();
}
}
}
}

View File

@ -1,23 +1,30 @@
package com.r3944realms.leashedplayer.client.renders.entities;
package com.r3944realms.leashedplayer.client.renderer.entities;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.LeashRopeArrow;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.state.ArrowRenderState;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
@OnlyIn(Dist.CLIENT)
public class LeashRopeArrowRenderer extends ArrowRenderer<LeashRopeArrow> {
public class LeashRopeArrowRenderer extends ArrowRenderer<LeashRopeArrow, ArrowRenderState> {
public static final ResourceLocation LEASH_ROPE_ARROW = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/entity/projectiles/leash_rope_arrow.png");
public LeashRopeArrowRenderer(EntityRendererProvider.Context pContext) {
super(pContext);
}
@Override
public @NotNull ResourceLocation getTextureLocation(@NotNull LeashRopeArrow pEntity) {
public @NotNull ArrowRenderState createRenderState() {
return new ArrowRenderState();
}
@Override
protected @NotNull ResourceLocation getTextureLocation(@NotNull ArrowRenderState arrowRenderState) {
return LEASH_ROPE_ARROW;
}
}

View File

@ -1,23 +1,31 @@
package com.r3944realms.leashedplayer.client.renders.entities;
package com.r3944realms.leashedplayer.client.renderer.entities;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.SpectralLeashRopeArrow;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.state.ArrowRenderState;
import net.minecraft.resources.ResourceLocation;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
@OnlyIn(Dist.CLIENT)
public class SpectralLeashRopeArrowRenderer extends ArrowRenderer<SpectralLeashRopeArrow> {
public class SpectralLeashRopeArrowRenderer extends ArrowRenderer<SpectralLeashRopeArrow, ArrowRenderState> {
public static final ResourceLocation SPECTRAL_LEASH_ROPE_ARROW = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/entity/projectiles/spectral_leash_rope_arrow.png");
public SpectralLeashRopeArrowRenderer(EntityRendererProvider.Context pContext) {
super(pContext);
}
@Override
public @NotNull ResourceLocation getTextureLocation(@NotNull SpectralLeashRopeArrow pEntity) {
public @NotNull ArrowRenderState createRenderState() {
return new ArrowRenderState();
}
@Override
protected @NotNull ResourceLocation getTextureLocation(@NotNull ArrowRenderState arrowRenderState) {
return SPECTRAL_LEASH_ROPE_ARROW;
}
}

View File

@ -1,4 +1,4 @@
package com.r3944realms.leashedplayer.client.renders.gui;
package com.r3944realms.leashedplayer.client.renderer.gui;
import com.google.common.collect.Maps;
import com.mojang.blaze3d.vertex.PoseStack;

View File

@ -1,4 +1,4 @@
package com.r3944realms.leashedplayer.client.renders.gui;
package com.r3944realms.leashedplayer.client.renderer.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import com.r3944realms.leashedplayer.client.processBar.IProcessBar;

View File

@ -1,4 +1,4 @@
package com.r3944realms.leashedplayer.client.renders.gui;
package com.r3944realms.leashedplayer.client.renderer.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import com.r3944realms.leashedplayer.client.processBar.IProcessBar;

View File

@ -1,4 +1,4 @@
package com.r3944realms.leashedplayer.client.renders.gui;
package com.r3944realms.leashedplayer.client.renderer.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import com.r3944realms.leashedplayer.LeashedPlayer;

View File

@ -1,4 +1,4 @@
package com.r3944realms.leashedplayer.client.renders.gui;
package com.r3944realms.leashedplayer.client.renderer.gui;
import com.mojang.blaze3d.vertex.PoseStack;
import com.r3944realms.leashedplayer.client.processBar.IProcessBar;

View File

@ -0,0 +1,139 @@
package com.r3944realms.leashedplayer.client.renderer.item;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import com.r3944realms.leashedplayer.client.renderer.item.properties.conditionalRange.ConditionalRangeItemModelProperties;
import com.r3944realms.leashedplayer.client.renderer.item.properties.conditionalRange.ConditionalRangeItemModelProperty;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.item.ItemModel;
import net.minecraft.client.renderer.item.ItemModelResolver;
import net.minecraft.client.renderer.item.ItemModels;
import net.minecraft.client.renderer.item.ItemStackRenderState;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@OnlyIn(Dist.CLIENT)
public class ConditionalRangeItemModel implements ItemModel {
private final ConditionalRangeItemModelProperty property;
private final float scale;
private final float[] onTrueThresholds;
private final float[] onFalseThresholds;
private final ItemModel[] onTrueModels;
private final ItemModel[] onFalseModels;
private final ItemModel fallback;
public ConditionalRangeItemModel(ConditionalRangeItemModelProperty property, float scale, float[] onTrueThresholds, float[] onFalseThresholds, ItemModel[] onTrueModels, ItemModel[] onFalseModels, ItemModel fallback) {
this.property = property;
this.scale = scale;
this.onTrueThresholds = onTrueThresholds;
this.onFalseThresholds = onFalseThresholds;
this.onTrueModels = onTrueModels;
this.onFalseModels = onFalseModels;
this.fallback = fallback;
}
private static int lastIndexLessOrEqual(float[] thresholds, float value) {
if (thresholds.length < 16) {
for (int k = 0; k < thresholds.length; k++) {
if (thresholds[k] > value) {
return k - 1;
}
}
return thresholds.length - 1;
} else {
int i = Arrays.binarySearch(thresholds, value);
if (i < 0) {
int j = ~i;
return j - 1;
} else {
return i;
}
}
}
@Override
public void update(@NotNull ItemStackRenderState renderState, @NotNull ItemStack stack, @NotNull ItemModelResolver itemModelResolver, @NotNull ItemDisplayContext displayContext, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed) {
ConditionalRangeItemModelProperty.ConditionalRangeData conditionalRangeData = this.property.get(stack, level, entity, seed, displayContext);
float f = conditionalRangeData.floatValue() * this.scale;
boolean b = conditionalRangeData.boolValue();
ItemModel itemModel;
if(Float.isNaN(f)) {
itemModel = this.fallback; ;
} else {
int i;
if (b) {
i = lastIndexLessOrEqual(this.onTrueThresholds, f);
}
else {
i = lastIndexLessOrEqual(this.onFalseThresholds, f);
}
itemModel = i == -1 ? this.fallback : b ? onTrueModels[i] : onFalseModels[i];
}
itemModel.update(renderState, stack, itemModelResolver, displayContext, level, entity, seed);
}
public record Entry(float threshold, ItemModel.Unbaked model) {
public static final Codec<Entry> CODEC = RecordCodecBuilder.create(
instance -> instance.group(
Codec.FLOAT.fieldOf("threshold").forGetter(Entry::threshold),
ItemModels.CODEC.fieldOf("model").forGetter(Entry::model)
).apply(instance, Entry::new)
);
public static final Comparator<Entry> BY_THRESHOLD = Comparator.comparingDouble(Entry::threshold);
}
public record Unbaked(
ConditionalRangeItemModelProperty property, float scale, List<Entry> trueModels, List<Entry> falseModels, Optional<ItemModel.Unbaked> fallback
) implements ItemModel.Unbaked {
public static final MapCodec<Unbaked> MAP_CODEC = RecordCodecBuilder.mapCodec(
instance -> instance.group(
ConditionalRangeItemModelProperties.MAP_CODEC.forGetter(Unbaked::property),
Codec.FLOAT.optionalFieldOf("scale", 1.0F).forGetter(Unbaked::scale),
Entry.CODEC.listOf().fieldOf("trueModels").forGetter(Unbaked::trueModels),
Entry.CODEC.listOf().fieldOf("falseModels").forGetter(Unbaked::falseModels),
ItemModels.CODEC.optionalFieldOf("fallback").forGetter(Unbaked::fallback)
).apply(instance, Unbaked::new)
);
@Override
public @NotNull MapCodec<? extends ItemModel.Unbaked> type() {
return MAP_CODEC;
}
@Override
public @NotNull ItemModel bake(@NotNull BakingContext context) {
float[] floatArrA = new float[this.trueModels.size()];
float[] floatArrB = new float[this.falseModels.size()];
ItemModel[] itemModelArrA = new ItemModel[this.trueModels.size()];
ItemModel[] itemModelArrB = new ItemModel[this.falseModels.size()];
List<Entry> trueModelList = new ArrayList<>(this.trueModels);
List<Entry> falseModelList = new ArrayList<>(this.falseModels);
trueModelList.sort(Entry.BY_THRESHOLD);
falseModelList.sort(Entry.BY_THRESHOLD);
for (int i = 0; i < trueModelList.size(); i++) {
Entry rangeselectitemmodel$entry = trueModelList.get(i);
floatArrA[i] = rangeselectitemmodel$entry.threshold;
itemModelArrA[i] = rangeselectitemmodel$entry.model.bake(context);
}
for (int i = 0; i < falseModels.size(); i++) {
Entry rangeselectitemmodel$entry = falseModelList.get(i);
floatArrB[i] = rangeselectitemmodel$entry.threshold;
itemModelArrB[i] = rangeselectitemmodel$entry.model.bake(context);
}
ItemModel itemmodel = this.fallback.map(p_387030_ -> p_387030_.bake(context)).orElse(context.missingItemModel());
return new ConditionalRangeItemModel(this.property, this.scale, floatArrA, floatArrB, itemModelArrA, itemModelArrB, itemmodel);
}
@Override
public void resolveDependencies(@NotNull Resolver resolver) {
this.fallback.ifPresent(itemModel -> itemModel.resolveDependencies(resolver));
this.trueModels.forEach(entry -> entry.model.resolveDependencies(resolver));
this.falseModels.forEach(entry -> entry.model.resolveDependencies(resolver));
}
}
}

View File

@ -0,0 +1,46 @@
package com.r3944realms.leashedplayer.client.renderer.item.properties.conditional;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.r3944realms.leashedplayer.content.items.type.ILeashRopeArrow;
import com.r3944realms.leashedplayer.extend.CrossbowItem$ChargeTypeExtend;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.item.properties.select.SelectItemModelProperty;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.component.ChargedProjectiles;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@OnlyIn(Dist.CLIENT)
public record ChargeExtend() implements SelectItemModelProperty<CrossbowItem$ChargeTypeExtend> {
public static Codec<CrossbowItem$ChargeTypeExtend> CODEC = CrossbowItem$ChargeTypeExtend.CODEC;
public static Type<ChargeExtend, CrossbowItem$ChargeTypeExtend> TYPE = Type.create(
MapCodec.unit(new ChargeExtend()), CODEC
);
@Override
public @NotNull CrossbowItem$ChargeTypeExtend get(@NotNull ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed, @NotNull ItemDisplayContext displayContext) {
ChargedProjectiles chargedprojectiles = stack.get(DataComponents.CHARGED_PROJECTILES);
if(chargedprojectiles == null || chargedprojectiles.isEmpty()) {
return CrossbowItem$ChargeTypeExtend.NONE;
} else {
return ILeashRopeArrow.isLeashRopeArrow(stack, entity) ? CrossbowItem$ChargeTypeExtend.LEASH_ROPE_ARROW :
chargedprojectiles.contains(Items.FIREWORK_ROCKET) ? CrossbowItem$ChargeTypeExtend.ROCKET : CrossbowItem$ChargeTypeExtend.ARROW;
}
}
@Override
public @NotNull Codec<CrossbowItem$ChargeTypeExtend> valueCodec() {
return CODEC;
}
@Override
public @NotNull Type<? extends SelectItemModelProperty<CrossbowItem$ChargeTypeExtend>, CrossbowItem$ChargeTypeExtend> type() {
return TYPE;
}
}

View File

@ -0,0 +1,27 @@
package com.r3944realms.leashedplayer.client.renderer.item.properties.conditionalRange;
import com.mojang.serialization.MapCodec;
import com.r3944realms.leashedplayer.content.items.type.ILeashRopeArrow;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.renderer.item.properties.numeric.UseDuration;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.Nullable;
public record BowPull() implements ConditionalRangeItemModelProperty {
public static final MapCodec<BowPull> MAP_CODEC = MapCodec.unit(new BowPull());
@Override
public ConditionalRangeData get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed, ItemDisplayContext displayContext) {
if (entity != null && entity.getUseItem() == stack) {
return ConditionalRangeData.create(ILeashRopeArrow.isLeashRopeArrow(stack, entity), (float)UseDuration.useDuration(stack, entity));
}
else return ConditionalRangeData.create(false, 0.0F);
}
@Override
public MapCodec<? extends ConditionalRangeItemModelProperty> type() {
return MAP_CODEC;
}
}

View File

@ -0,0 +1,19 @@
package com.r3944realms.leashedplayer.client.renderer.item.properties.conditionalRange;
import com.mojang.serialization.MapCodec;
import com.r3944realms.leashedplayer.LeashedPlayer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ExtraCodecs;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
@OnlyIn(Dist.CLIENT)
public class ConditionalRangeItemModelProperties {
private static final ExtraCodecs.LateBoundIdMapper<ResourceLocation, MapCodec<? extends ConditionalRangeItemModelProperty>> ID_MAPPER = new ExtraCodecs.LateBoundIdMapper<>();
public static final MapCodec<ConditionalRangeItemModelProperty> MAP_CODEC = ID_MAPPER.codec(ResourceLocation.CODEC)
.dispatchMap("property", ConditionalRangeItemModelProperty::type, mapCodec -> mapCodec);
public static void bootstrap() {
ID_MAPPER.put(ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "bow_pull"), BowPull.MAP_CODEC);
net.neoforged.fml.ModLoader.postEvent(new com.r3944realms.leashedplayer.content.events.RegisterConditionalRangeItemPropertyEvent(ID_MAPPER));
}
}

View File

@ -0,0 +1,23 @@
package com.r3944realms.leashedplayer.client.renderer.item.properties.conditionalRange;
import com.mojang.serialization.MapCodec;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import javax.annotation.Nullable;
@OnlyIn(Dist.CLIENT)
public interface ConditionalRangeItemModelProperty {
ConditionalRangeData get(ItemStack stack, @Nullable ClientLevel level, @Nullable LivingEntity entity, int seed, ItemDisplayContext displayContext);
MapCodec<? extends ConditionalRangeItemModelProperty> type();
record ConditionalRangeData(boolean boolValue, float floatValue) {
public static ConditionalRangeData create(boolean boolValue, float floatValue) {
return new ConditionalRangeData(boolValue, floatValue);
}
}
}

View File

@ -1,115 +0,0 @@
package com.r3944realms.leashedplayer.client.renders.entities;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.math.Axis;
import net.minecraft.client.model.EntityModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.renderer.ItemInHandRenderer;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.RenderLayerParent;
import net.minecraft.client.renderer.entity.layers.RenderLayer;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemDisplayContext;
import net.minecraft.world.item.ItemStack;
import org.jetbrains.annotations.NotNull;
public class ChestItemLayerRenderer<T extends LivingEntity, M extends EntityModel<T>> extends RenderLayer<T, M> {
private final ItemInHandRenderer heldItemRenderer;
public ChestItemLayerRenderer(RenderLayerParent<T, M> context, ItemInHandRenderer heldItemRenderer) {
super(context);
this.heldItemRenderer = heldItemRenderer;
}
@Override
public void render(@NotNull PoseStack matrices, @NotNull MultiBufferSource vertexConsumers, int light, @NotNull T entity, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
ItemDisplayContext mode = ItemDisplayContext.FIXED;
ItemStack chestStack = entity.getItemBySlot(EquipmentSlot.CHEST);
if (!chestStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(chestStack).equals(EquipmentSlot.CHEST))) {
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).body.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.translate(0, -1 / 4f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(1.01f, 1.01f, 1.01f);
matrices.translate(0, -1 / 4f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).rightArm.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(-1/12f, 0, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(0.99f, 0.99f, 0.99f);
matrices.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).leftArm.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(1/12f, 0, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(0.99f, 0.99f, 0.99f);
matrices.translate(0, -1/2f, 0);
this.heldItemRenderer.renderItem(entity, chestStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
}
}
ItemStack legsStack = entity.getItemBySlot(EquipmentSlot.LEGS);
if (!legsStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(legsStack).equals(EquipmentSlot.LEGS))) {
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).rightLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(0, -1/6f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(1.01f, 1.01f, 1.01f);
matrices.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).leftLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(2/3f, 2/3f, 2/3f);
matrices.translate(0, -1/6f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.scale(1.01f, 1.01f, 1.01f);
matrices.translate(0, -1/3f, 0);
this.heldItemRenderer.renderItem(entity, legsStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
}
}
ItemStack feetStack = entity.getItemBySlot(EquipmentSlot.FEET);
if (!feetStack.isEmpty()) {
if (!(entity.getEquipmentSlotForItem(feetStack).equals(EquipmentSlot.FEET))) {
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).rightLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(0.75f, 0.75f, 0.75f);
matrices.translate(0, -0.8f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
matrices.pushPose();
((PlayerModel<?>) this.getParentModel()).leftLeg.translateAndRotate(matrices);
matrices.mulPose(Axis.XP.rotationDegrees(180));
matrices.scale(0.75f, 0.75f, 0.75f);
matrices.translate(0, -0.8f, 0);
matrices.mulPose(Axis.YP.rotationDegrees(180));
this.heldItemRenderer.renderItem(entity, feetStack, mode, false, matrices, vertexConsumers, light);
matrices.popPose();
}
}
}
}

View File

@ -1,107 +0,0 @@
package com.r3944realms.leashedplayer.client.renders.entities;
import com.mojang.blaze3d.vertex.PoseStack;
import com.r3944realms.leashedplayer.content.entities.LittlePlayer;
import net.minecraft.client.model.HumanoidModel;
import net.minecraft.client.model.PlayerModel;
import net.minecraft.client.model.geom.ModelLayers;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.HumanoidMobRenderer;
import net.minecraft.client.renderer.entity.layers.HumanoidArmorLayer;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.HumanoidArm;
import net.minecraft.world.item.CrossbowItem;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.item.UseAnim;
import net.neoforged.api.distmarker.Dist;
import net.neoforged.api.distmarker.OnlyIn;
import org.jetbrains.annotations.NotNull;
@OnlyIn(Dist.CLIENT)
public class KidPlayerRenderer extends HumanoidMobRenderer<LittlePlayer, PlayerModel<LittlePlayer>> {
public static @NotNull KidPlayerRenderer create(@NotNull EntityRendererProvider.Context pContext) {
if (pContext instanceof PlayerContext pc) {
return new KidPlayerRenderer(pc);
}
return new KidPlayerRenderer(new PlayerContext(pContext, true));
}
public static class PlayerContext extends EntityRendererProvider.Context {
boolean isUseSlimModel;
public PlayerContext(EntityRendererProvider.Context pContext, boolean pIsSlimModel) {
super(pContext.getEntityRenderDispatcher(), pContext.getItemRenderer(), pContext.getBlockRenderDispatcher(), pContext.getItemInHandRenderer(), pContext.getResourceManager(), pContext.getModelSet(), pContext.getFont());
this.isUseSlimModel = pIsSlimModel;
}
public boolean isUseSlimModel() {
return isUseSlimModel;
}
}
public KidPlayerRenderer(PlayerContext pContext) {
super(pContext, new PlayerModel<>(pContext.bakeLayer(pContext.isUseSlimModel() ? ModelLayers.PLAYER_SLIM : ModelLayers.PLAYER), pContext.isUseSlimModel()), 0.5F);
this.addLayer(new HumanoidArmorLayer<>(this,
new HumanoidModel<>(pContext.bakeLayer(ModelLayers.PLAYER_INNER_ARMOR)),
new HumanoidModel<>(pContext.bakeLayer(ModelLayers.PLAYER_OUTER_ARMOR)),
pContext.getModelManager()
));
}
@Override
public @NotNull ResourceLocation getTextureLocation(@NotNull LittlePlayer pEntity) {
return pEntity.getSkin().texture();
}
public void render(@NotNull LittlePlayer companion, float companionYaw, float pPartialTicks, @NotNull PoseStack pMatrixStack,
@NotNull MultiBufferSource pBuffer, int pPackedLight) {
this.setModelProperties(companion);
super.render(companion, companionYaw, pPartialTicks, pMatrixStack, pBuffer, pPackedLight);
}
private void setModelProperties(LittlePlayer companion) {
PlayerModel<LittlePlayer> companionModel = this.getModel();
HumanoidModel.ArmPose humanoidmodel$armpose = getArmPose(companion, InteractionHand.MAIN_HAND);
HumanoidModel.ArmPose humanoidmodel$armpose1 = getArmPose(companion, InteractionHand.OFF_HAND);
if (companion.getMainArm() == HumanoidArm.RIGHT) {
companionModel.rightArmPose = humanoidmodel$armpose;
companionModel.leftArmPose = humanoidmodel$armpose1;
} else {
companionModel.rightArmPose = humanoidmodel$armpose1;
companionModel.leftArmPose = humanoidmodel$armpose;
}
}
private static HumanoidModel.ArmPose getArmPose(LittlePlayer companion, InteractionHand hand) {
ItemStack itemstack = companion.getItemInHand(hand);
if (itemstack.isEmpty()) {
return HumanoidModel.ArmPose.EMPTY;
} else {
if (companion.getUsedItemHand() == hand && companion.getUseItemRemainingTicks() > 0) {
UseAnim useanim = itemstack.getUseAnimation();
if (useanim == UseAnim.BOW) {
return HumanoidModel.ArmPose.BOW_AND_ARROW;
}
if (useanim == UseAnim.CROSSBOW && hand == companion.getUsedItemHand()) {
return HumanoidModel.ArmPose.CROSSBOW_CHARGE;
}
} else if (!companion.swinging && itemstack.is(Items.CROSSBOW) && CrossbowItem.isCharged(itemstack)) {
return HumanoidModel.ArmPose.CROSSBOW_HOLD;
}
return HumanoidModel.ArmPose.ITEM;
}
}
protected void scale(@NotNull LittlePlayer player, PoseStack pPoseStack, float pPartialTickTime) {
float f = 0.9375F;
pPoseStack.scale(f, f, f);
}
}

View File

@ -1,21 +0,0 @@
package com.r3944realms.leashedplayer.client.renders.entities;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.content.entities.NestleRopeArrow;
import net.minecraft.client.renderer.entity.ArrowRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
public class NestleRopeArrowRenderer extends ArrowRenderer<NestleRopeArrow> {
public static final ResourceLocation NESTLE_ROPE_ARROW = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "textures/entity/projectiles/nestle_rope_arrow.png");
public NestleRopeArrowRenderer(EntityRendererProvider.Context pContext) {
super(pContext);
}
@Override
public @NotNull ResourceLocation getTextureLocation(@NotNull NestleRopeArrow pEntity) {
return NESTLE_ROPE_ARROW;
}
}

View File

@ -1,32 +0,0 @@
package com.r3944realms.leashedplayer.compat.jei;
import com.r3944realms.leashedplayer.LeashedPlayer;
import com.r3944realms.leashedplayer.compat.jei.common.PotionSubtypeInterpreter;
import com.r3944realms.leashedplayer.compat.jei.crafting.TippedLeashArrowRecipeMaker;
import com.r3944realms.leashedplayer.content.items.ModItemRegister;
import mezz.jei.api.IModPlugin;
import mezz.jei.api.JeiPlugin;
import mezz.jei.api.constants.RecipeTypes;
import mezz.jei.api.registration.IRecipeRegistration;
import mezz.jei.api.registration.ISubtypeRegistration;
import net.minecraft.resources.ResourceLocation;
import org.jetbrains.annotations.NotNull;
@JeiPlugin
public class JEIPlugin implements IModPlugin {
private static final ResourceLocation UID = ResourceLocation.fromNamespaceAndPath(LeashedPlayer.MOD_ID, "jei_plugin");
@Override
public @NotNull ResourceLocation getPluginUid() {
return UID;
}
@Override
public void registerItemSubtypes(ISubtypeRegistration registration) {
registration.registerSubtypeInterpreter(ModItemRegister.TIPPED_LEASH_ROPE_ARROW.get(), PotionSubtypeInterpreter.INSTANCE);
}
@Override
public void registerRecipes(@NotNull IRecipeRegistration registration) {
registration.addRecipes(RecipeTypes.CRAFTING, TippedLeashArrowRecipeMaker.createRecipes());
}
}

View File

@ -1,28 +0,0 @@
package com.r3944realms.leashedplayer.compat.jei.common;
import mezz.jei.api.ingredients.subtypes.IIngredientSubtypeInterpreter;
import mezz.jei.api.ingredients.subtypes.UidContext;
import net.minecraft.core.Holder;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.alchemy.PotionContents;
import org.jetbrains.annotations.NotNull;
public class PotionSubtypeInterpreter implements IIngredientSubtypeInterpreter<ItemStack> {
public static final PotionSubtypeInterpreter INSTANCE = new PotionSubtypeInterpreter();
private PotionSubtypeInterpreter() {
}
@Override
public @NotNull String apply(ItemStack itemStack, @NotNull UidContext context) {
if (itemStack.getComponentsPatch().isEmpty()) {
return IIngredientSubtypeInterpreter.NONE;
}
PotionContents contents = itemStack.getOrDefault(DataComponents.POTION_CONTENTS, PotionContents.EMPTY);
String itemDescriptionId = itemStack.getItem().getDescriptionId();
String potionEffectId = contents.potion().map(Holder::getRegisteredName).orElse("none");
return itemDescriptionId + ".effect_id." + potionEffectId;
}
}

Some files were not shown because too many files have changed in this diff Show More