Skip to content

Commit 38592c4

Browse files
authored
Merge pull request #1 from CampioneBase/IronGolemNbt
铁傀儡的手动生锈,去锈,涂蜡
2 parents b57b550 + 99694c6 commit 38592c4

8 files changed

Lines changed: 403 additions & 1 deletion

File tree

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package com.adccadc.rust.manager;
2+
3+
import com.adccadc.rust.Rust;
4+
import net.minecraft.item.Item;
5+
import net.minecraft.item.ItemStack;
6+
import org.jetbrains.annotations.Nullable;
7+
8+
/**
9+
* 锈蚀管理器
10+
* @author CampioneBase
11+
* @version 1.0
12+
*/
13+
public class RustManager {
14+
public static final String[] RUST_TEXT = {"", "斑驳的", "锈蚀的", "氧化的"};
15+
public static final String WAXED_TEXT = "涂蜡的";
16+
// 锈蚀状态
17+
private final RustState state = new RustState();
18+
// 锈蚀最大等级
19+
private final int maxLevel;
20+
// 锈蚀物品类型
21+
private final ItemStack rust;
22+
23+
/**
24+
* @param rust 附着的锈蚀物品堆
25+
* @param max 锈蚀最大等级
26+
*/
27+
public RustManager(ItemStack rust, int max){
28+
this.maxLevel = max;
29+
this.rust = rust;
30+
}
31+
32+
public void setState(RustState state){
33+
this.state.level = state.level;
34+
this.state.isWaxed = state.isWaxed;
35+
}
36+
37+
/**
38+
* 尝试上锈
39+
* @return 是否成功上锈
40+
*/
41+
public boolean tryRusted(){
42+
if (this.state.isWaxed) return false;
43+
if (this.state.level >= maxLevel) return false;
44+
this.state.level++;
45+
return true;
46+
}
47+
48+
/**
49+
* 尝试去锈
50+
* @return 去锈时的掉落物,null 表示失败
51+
*/
52+
@Nullable
53+
public ItemStack tryDerusted(){
54+
// 脱蜡
55+
if (this.state.isWaxed) {
56+
this.state.isWaxed = false;
57+
return ItemStack.EMPTY;
58+
}
59+
if (this.state.level <= 0) return null;
60+
this.state.level--;
61+
return rust.copy();
62+
}
63+
64+
/**
65+
* 上蜡
66+
* @return 是否成功上蜡
67+
*/
68+
public boolean tryWaxed(){
69+
// 是否已经上蜡
70+
if (this.state.isWaxed) return false;
71+
// 成功上蜡
72+
this.state.isWaxed = true;
73+
return true;
74+
}
75+
76+
public RustState getState(){
77+
return state;
78+
}
79+
80+
public void setLevel(int level) {
81+
this.state.level = level;
82+
}
83+
84+
public void setWaxed(boolean isWaxed){
85+
this.state.isWaxed = isWaxed;
86+
}
87+
88+
public String getName(){
89+
return (this.state.isWaxed ? WAXED_TEXT : "") + RUST_TEXT[this.state.level];
90+
}
91+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.adccadc.rust.manager;
2+
3+
// 锈蚀状态
4+
public class RustState {
5+
// 锈蚀等级
6+
public int level;
7+
// 是否涂蜡
8+
public boolean isWaxed;
9+
}
Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,169 @@
1+
package com.adccadc.rust.mixin.entity.iromGolem;
2+
3+
import com.adccadc.rust.Rust;
4+
import com.adccadc.rust.item.Moditems;
5+
import com.adccadc.rust.manager.RustManager;
6+
import com.adccadc.rust.proxy.IronGolemEntityProxy;
7+
import net.fabricmc.api.EnvType;
8+
import net.fabricmc.api.Environment;
9+
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
10+
import net.minecraft.block.Blocks;
11+
import net.minecraft.entity.EntityType;
12+
import net.minecraft.entity.ItemEntity;
13+
import net.minecraft.entity.passive.GolemEntity;
14+
import net.minecraft.entity.passive.IronGolemEntity;
15+
import net.minecraft.entity.player.PlayerEntity;
16+
import net.minecraft.item.*;
17+
import net.minecraft.particle.ParticleTypes;
18+
import net.minecraft.registry.tag.ItemTags;
19+
import net.minecraft.registry.tag.TagKey;
20+
import net.minecraft.server.world.ServerWorld;
21+
import net.minecraft.sound.SoundEvents;
22+
import net.minecraft.storage.ReadView;
23+
import net.minecraft.storage.WriteView;
24+
import net.minecraft.text.Text;
25+
import net.minecraft.util.ActionResult;
26+
import net.minecraft.util.Hand;
27+
import net.minecraft.world.World;
28+
import org.spongepowered.asm.mixin.Mixin;
29+
import org.spongepowered.asm.mixin.Unique;
30+
import org.spongepowered.asm.mixin.injection.At;
31+
import org.spongepowered.asm.mixin.injection.Inject;
32+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
33+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
34+
35+
@Mixin(IronGolemEntity.class)
36+
public abstract class IronGolemEntityMixin extends GolemEntity implements IronGolemEntityProxy
37+
{
38+
// 锈蚀控制器
39+
@Unique
40+
public RustManager rust = new RustManager(new ItemStack(Moditems.IRON_RUST, 2), 3);
41+
42+
public IronGolemEntityMixin(EntityType<? extends IronGolemEntity> entityType, World world) {
43+
super(entityType, world);
44+
}
45+
46+
@Unique
47+
public IronGolemEntityProxy proxy(){
48+
return this;
49+
}
50+
51+
@Unique
52+
public RustManager getRust(){
53+
return this.rust;
54+
}
55+
56+
@Inject(method = "writeCustomData",
57+
/*at = @At(value = "INVOKE",
58+
target = "Lnet/minecraft/iromGolem/mob/Angerable;writeAngerToData(Lnet/minecraft/world/World;Lnet/minecraft/storage/WriteView;)V",
59+
shift = At.Shift.BEFORE
60+
)*/
61+
at = @At("HEAD")
62+
)
63+
private void writeCustomDataWithRust(WriteView view, CallbackInfo info){
64+
view.putInt("RustLevel", this.rust.getState().level);
65+
view.putBoolean("IsWaxed", this.rust.getState().isWaxed);
66+
}
67+
68+
@Inject(method = "readCustomData",
69+
/*at = @At(value = "INVOKE",
70+
target = "Lnet/minecraft/iromGolem/mob/Angerable;readAngerFromData(Lnet/minecraft/world/World;Lnet/minecraft/storage/WriteView;)V",
71+
shift = At.Shift.BEFORE
72+
)*/
73+
at = @At("HEAD")
74+
)
75+
private void readCustomDataWithRust(ReadView view, CallbackInfo info){
76+
this.rust.setLevel(view.getInt("RustLevel", 0));
77+
this.rust.setWaxed(view.getBoolean("IsWaxed", false));
78+
}
79+
80+
@Inject(
81+
method = "interactMob",
82+
at = @At("HEAD"),
83+
cancellable = true
84+
)
85+
protected void interactMobWithRustActions(PlayerEntity player, Hand hand, CallbackInfoReturnable<ActionResult> cir){
86+
ItemStack itemStack = player.getStackInHand(hand);
87+
// 是否为水桶
88+
if (itemStack.isOf(Items.WATER_BUCKET)){
89+
// 处理物品
90+
if(!player.isCreative()){
91+
// 将水桶换成空桶
92+
ItemStack newItemStack = ItemUsage.exchangeStack(itemStack, player, Items.BUCKET.getDefaultStack());
93+
player.setStackInHand(hand, newItemStack);
94+
}
95+
// 尝试执行一次锈蚀
96+
if(!(this.rust.tryRusted())){
97+
// 生锈失败
98+
cir.setReturnValue(ActionResult.FAIL);
99+
}else{
100+
cir.setReturnValue(ActionResult.SUCCESS);
101+
}
102+
// 物品是否含有斧头标签
103+
} else if (itemStack.isIn(ItemTags.AXES)){
104+
// 执行一次除锈
105+
ItemStack dropStack;
106+
if (((dropStack = this.rust.tryDerusted()) == null)){
107+
// 除锈失败
108+
cir.setReturnValue(ActionResult.FAIL);
109+
} else {
110+
World world = this.getWorld();
111+
if (world instanceof ServerWorld serverWorld) {
112+
// 生成掉落物
113+
ItemEntity drop = this.dropStack(serverWorld, dropStack, 1.5F);
114+
// 播放音效
115+
this.playSound(SoundEvents.ITEM_AXE_WAX_OFF, 1.0F, 1.0F);
116+
// 播放粒子
117+
serverWorld.spawnParticles(
118+
ParticleTypes.WAX_OFF,
119+
this.getX(),
120+
this.getY() + 1.0F,
121+
this.getZ(),
122+
35,
123+
0.4F,
124+
0.8F,
125+
0.4F,
126+
0.1F
127+
);
128+
// 处理物品
129+
itemStack.damage(1, player);
130+
cir.setReturnValue(ActionResult.SUCCESS);
131+
}
132+
}
133+
// 物品是否为蜜脾
134+
} else if (itemStack.isOf(Items.HONEYCOMB) && itemStack.getCount() >= 2) {
135+
// 尝试上蜡
136+
if (!this.rust.tryWaxed()){
137+
// 上蜡失败
138+
cir.setReturnValue(ActionResult.FAIL);
139+
} else {
140+
World world = this.getWorld();
141+
if(world instanceof ServerWorld serverWorld){
142+
// 播放音效
143+
this.playSound(SoundEvents.ITEM_HONEYCOMB_WAX_ON, 1.0F, 1.0F);
144+
// 播放粒子
145+
serverWorld.spawnParticles(
146+
ParticleTypes.WAX_ON,
147+
this.getX(),
148+
this.getY() + 1.0F,
149+
this.getZ(),
150+
35,
151+
0.4F,
152+
0.8F,
153+
0.4F,
154+
0.1F
155+
);
156+
// 处理物品
157+
itemStack.decrementUnlessCreative(2, player);
158+
cir.setReturnValue(ActionResult.SUCCESS);
159+
}
160+
}
161+
}
162+
}
163+
164+
@Override
165+
// 在名称前添加锈蚀状态
166+
protected Text getDefaultName(){
167+
return Text.of(this.rust.getName() + this.getType().getName().getString());
168+
}
169+
}
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package com.adccadc.rust.mixin.render;
2+
3+
import com.adccadc.rust.manager.RustState;
4+
import com.adccadc.rust.proxy.IronGolemEntityProxy;
5+
import com.adccadc.rust.proxy.IronGolemEntityRenderStateProxy;
6+
import com.google.common.collect.ImmutableMap;
7+
import net.fabricmc.api.EnvType;
8+
import net.fabricmc.api.Environment;
9+
import net.minecraft.client.render.entity.EntityRendererFactory;
10+
import net.minecraft.client.render.entity.IronGolemEntityRenderer;
11+
import net.minecraft.client.render.entity.MobEntityRenderer;
12+
import net.minecraft.client.render.entity.model.IronGolemEntityModel;
13+
import net.minecraft.client.render.entity.state.IronGolemEntityRenderState;
14+
import net.minecraft.entity.passive.IronGolemEntity;
15+
import net.minecraft.util.Identifier;
16+
import org.spongepowered.asm.mixin.Mixin;
17+
import org.spongepowered.asm.mixin.injection.At;
18+
import org.spongepowered.asm.mixin.injection.Inject;
19+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
20+
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
21+
22+
@Environment(EnvType.CLIENT)
23+
@Mixin(IronGolemEntityRenderer.class)
24+
public abstract class IronGolemEntityRendererMixin extends MobEntityRenderer<IronGolemEntity, IronGolemEntityRenderState, IronGolemEntityModel> {
25+
private static final ImmutableMap<Integer, Identifier> TEXTURES;
26+
private static final ImmutableMap<Integer, Identifier> WAXED_TEXTURES;
27+
28+
public IronGolemEntityRendererMixin(EntityRendererFactory.Context context, IronGolemEntityModel entityModel, float f) {
29+
super(context, entityModel, f);
30+
}
31+
32+
@Inject(
33+
method = "getTexture",
34+
at = @At("HEAD"),
35+
cancellable = true
36+
)
37+
public void getTextureWithRust(IronGolemEntityRenderState state, CallbackInfoReturnable<Identifier> cir){
38+
IronGolemEntityRenderStateProxy stateProxy = ((IronGolemEntityRenderStateProxy) state);
39+
RustState rustState = stateProxy.getRustState();
40+
int level = Math.max(0, Math.min(3, rustState.level));
41+
if(rustState.isWaxed)
42+
cir.setReturnValue(WAXED_TEXTURES.get(level));
43+
else
44+
cir.setReturnValue(TEXTURES.get(level));
45+
}
46+
47+
@Inject(
48+
method = "updateRenderState",
49+
at = @At("TAIL")
50+
)
51+
public void updateRenderStateWithRust(
52+
IronGolemEntity entity,
53+
IronGolemEntityRenderState state,
54+
float f,
55+
CallbackInfo ci
56+
){
57+
IronGolemEntityRenderStateProxy stateProxy = ((IronGolemEntityRenderStateProxy) state);
58+
IronGolemEntityProxy entityProxy = ((IronGolemEntityProxy) entity);
59+
stateProxy.setRustState(entityProxy.getRust().getState());
60+
}
61+
62+
static {
63+
TEXTURES = ImmutableMap.of(
64+
0, Identifier.ofVanilla("textures/entity/iron_golem/iron_golem.png"),
65+
1, Identifier.of("rust", "textures/entity/exposed_iron_golem.png"),
66+
2, Identifier.of("rust", "textures/entity/weathered_iron_golem.png"),
67+
3, Identifier.of("rust", "textures/entity/oxidized_iron_golem.png")
68+
);
69+
WAXED_TEXTURES = ImmutableMap.of(
70+
0, Identifier.of("rust", "textures/entity/waxed_iron_golem.png"),
71+
1, Identifier.of("rust", "textures/entity/waxed_exposed_iron_golem.png"),
72+
2, Identifier.of("rust", "textures/entity/waxed_weathered_iron_golem.png"),
73+
3, Identifier.of("rust", "textures/entity/waxed_oxidized_iron_golem.png")
74+
);
75+
}
76+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.adccadc.rust.mixin.render.state;
2+
3+
import com.adccadc.rust.manager.RustState;
4+
import com.adccadc.rust.proxy.IronGolemEntityRenderStateProxy;
5+
import net.fabricmc.api.EnvType;
6+
import net.fabricmc.api.Environment;
7+
import net.minecraft.client.render.entity.state.IronGolemEntityRenderState;
8+
import org.spongepowered.asm.mixin.Mixin;
9+
import org.spongepowered.asm.mixin.Unique;
10+
11+
@Environment(EnvType.CLIENT)
12+
@Mixin(IronGolemEntityRenderState.class)
13+
public class IronGolemEntityRenderStateMixin implements IronGolemEntityRenderStateProxy {
14+
@Unique
15+
public RustState rustState;
16+
17+
@Override
18+
public void setRustState(RustState state) {
19+
this.rustState = state;
20+
}
21+
22+
@Override
23+
public RustState getRustState() {
24+
return rustState;
25+
}
26+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.adccadc.rust.proxy;
2+
3+
import com.adccadc.rust.manager.RustManager;
4+
import net.fabricmc.api.EnvType;
5+
import net.fabricmc.api.Environment;
6+
7+
@Environment(EnvType.CLIENT)
8+
public interface IronGolemEntityProxy {
9+
10+
default IronGolemEntityProxy proxy(){
11+
return this;
12+
}
13+
14+
RustManager getRust();
15+
}

0 commit comments

Comments
 (0)