Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
91 changes: 91 additions & 0 deletions src/main/java/com/adccadc/rust/manager/RustManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package com.adccadc.rust.manager;

import com.adccadc.rust.Rust;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import org.jetbrains.annotations.Nullable;

/**
* 锈蚀管理器
* @author CampioneBase
* @version 1.0
*/
public class RustManager {
public static final String[] RUST_TEXT = {"", "斑驳的", "锈蚀的", "氧化的"};
public static final String WAXED_TEXT = "涂蜡的";
// 锈蚀状态
private final RustState state = new RustState();
// 锈蚀最大等级
private final int maxLevel;
// 锈蚀物品类型
private final ItemStack rust;

/**
* @param rust 附着的锈蚀物品堆
* @param max 锈蚀最大等级
*/
public RustManager(ItemStack rust, int max){
this.maxLevel = max;
this.rust = rust;
}

public void setState(RustState state){
this.state.level = state.level;
this.state.isWaxed = state.isWaxed;
}

/**
* 尝试上锈
* @return 是否成功上锈
*/
public boolean tryRusted(){
if (this.state.isWaxed) return false;
if (this.state.level >= maxLevel) return false;
this.state.level++;
return true;
}

/**
* 尝试去锈
* @return 去锈时的掉落物,null 表示失败
*/
@Nullable
public ItemStack tryDerusted(){
// 脱蜡
if (this.state.isWaxed) {
this.state.isWaxed = false;
return ItemStack.EMPTY;
}
if (this.state.level <= 0) return null;
this.state.level--;
return rust.copy();
}

/**
* 上蜡
* @return 是否成功上蜡
*/
public boolean tryWaxed(){
// 是否已经上蜡
if (this.state.isWaxed) return false;
// 成功上蜡
this.state.isWaxed = true;
return true;
}

public RustState getState(){
return state;
}

public void setLevel(int level) {
this.state.level = level;
}

public void setWaxed(boolean isWaxed){
this.state.isWaxed = isWaxed;
}

public String getName(){
return (this.state.isWaxed ? WAXED_TEXT : "") + RUST_TEXT[this.state.level];
}
}
9 changes: 9 additions & 0 deletions src/main/java/com/adccadc/rust/manager/RustState.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.adccadc.rust.manager;

// 锈蚀状态
public class RustState {
// 锈蚀等级
public int level;
// 是否涂蜡
public boolean isWaxed;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
package com.adccadc.rust.mixin.entity.iromGolem;

import com.adccadc.rust.Rust;
import com.adccadc.rust.item.Moditems;
import com.adccadc.rust.manager.RustManager;
import com.adccadc.rust.proxy.IronGolemEntityProxy;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.fabricmc.fabric.api.event.player.UseEntityCallback;
import net.minecraft.block.Blocks;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.passive.GolemEntity;
import net.minecraft.entity.passive.IronGolemEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.registry.tag.TagKey;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundEvents;
import net.minecraft.storage.ReadView;
import net.minecraft.storage.WriteView;
import net.minecraft.text.Text;
import net.minecraft.util.ActionResult;
import net.minecraft.util.Hand;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(IronGolemEntity.class)
public abstract class IronGolemEntityMixin extends GolemEntity implements IronGolemEntityProxy
{
// 锈蚀控制器
@Unique
public RustManager rust = new RustManager(new ItemStack(Moditems.IRON_RUST, 2), 3);

public IronGolemEntityMixin(EntityType<? extends IronGolemEntity> entityType, World world) {
super(entityType, world);
}

@Unique
public IronGolemEntityProxy proxy(){
return this;
}

@Unique
public RustManager getRust(){
return this.rust;
}

@Inject(method = "writeCustomData",
/*at = @At(value = "INVOKE",
target = "Lnet/minecraft/iromGolem/mob/Angerable;writeAngerToData(Lnet/minecraft/world/World;Lnet/minecraft/storage/WriteView;)V",
shift = At.Shift.BEFORE
)*/
at = @At("HEAD")
)
private void writeCustomDataWithRust(WriteView view, CallbackInfo info){
view.putInt("RustLevel", this.rust.getState().level);
view.putBoolean("IsWaxed", this.rust.getState().isWaxed);
}

@Inject(method = "readCustomData",
/*at = @At(value = "INVOKE",
target = "Lnet/minecraft/iromGolem/mob/Angerable;readAngerFromData(Lnet/minecraft/world/World;Lnet/minecraft/storage/WriteView;)V",
shift = At.Shift.BEFORE
)*/
at = @At("HEAD")
)
private void readCustomDataWithRust(ReadView view, CallbackInfo info){
this.rust.setLevel(view.getInt("RustLevel", 0));
this.rust.setWaxed(view.getBoolean("IsWaxed", false));
}

@Inject(
method = "interactMob",
at = @At("HEAD"),
cancellable = true
)
protected void interactMobWithRustActions(PlayerEntity player, Hand hand, CallbackInfoReturnable<ActionResult> cir){
ItemStack itemStack = player.getStackInHand(hand);
// 是否为水桶
if (itemStack.isOf(Items.WATER_BUCKET)){
// 处理物品
if(!player.isCreative()){
// 将水桶换成空桶
ItemStack newItemStack = ItemUsage.exchangeStack(itemStack, player, Items.BUCKET.getDefaultStack());
player.setStackInHand(hand, newItemStack);
}
// 尝试执行一次锈蚀
if(!(this.rust.tryRusted())){
// 生锈失败
cir.setReturnValue(ActionResult.FAIL);
}else{
cir.setReturnValue(ActionResult.SUCCESS);
}
// 物品是否含有斧头标签
} else if (itemStack.isIn(ItemTags.AXES)){
// 执行一次除锈
ItemStack dropStack;
if (((dropStack = this.rust.tryDerusted()) == null)){
// 除锈失败
cir.setReturnValue(ActionResult.FAIL);
} else {
World world = this.getWorld();
if (world instanceof ServerWorld serverWorld) {
// 生成掉落物
ItemEntity drop = this.dropStack(serverWorld, dropStack, 1.5F);
// 播放音效
this.playSound(SoundEvents.ITEM_AXE_WAX_OFF, 1.0F, 1.0F);
// 播放粒子
serverWorld.spawnParticles(
ParticleTypes.WAX_OFF,
this.getX(),
this.getY() + 1.0F,
this.getZ(),
35,
0.4F,
0.8F,
0.4F,
0.1F
);
// 处理物品
itemStack.damage(1, player);
cir.setReturnValue(ActionResult.SUCCESS);
}
}
// 物品是否为蜜脾
} else if (itemStack.isOf(Items.HONEYCOMB) && itemStack.getCount() >= 2) {
// 尝试上蜡
if (!this.rust.tryWaxed()){
// 上蜡失败
cir.setReturnValue(ActionResult.FAIL);
} else {
World world = this.getWorld();
if(world instanceof ServerWorld serverWorld){
// 播放音效
this.playSound(SoundEvents.ITEM_HONEYCOMB_WAX_ON, 1.0F, 1.0F);
// 播放粒子
serverWorld.spawnParticles(
ParticleTypes.WAX_ON,
this.getX(),
this.getY() + 1.0F,
this.getZ(),
35,
0.4F,
0.8F,
0.4F,
0.1F
);
// 处理物品
itemStack.decrementUnlessCreative(2, player);
cir.setReturnValue(ActionResult.SUCCESS);
}
}
}
}

@Override
// 在名称前添加锈蚀状态
protected Text getDefaultName(){
return Text.of(this.rust.getName() + this.getType().getName().getString());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package com.adccadc.rust.mixin.render;

import com.adccadc.rust.manager.RustState;
import com.adccadc.rust.proxy.IronGolemEntityProxy;
import com.adccadc.rust.proxy.IronGolemEntityRenderStateProxy;
import com.google.common.collect.ImmutableMap;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.entity.EntityRendererFactory;
import net.minecraft.client.render.entity.IronGolemEntityRenderer;
import net.minecraft.client.render.entity.MobEntityRenderer;
import net.minecraft.client.render.entity.model.IronGolemEntityModel;
import net.minecraft.client.render.entity.state.IronGolemEntityRenderState;
import net.minecraft.entity.passive.IronGolemEntity;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Environment(EnvType.CLIENT)
@Mixin(IronGolemEntityRenderer.class)
public abstract class IronGolemEntityRendererMixin extends MobEntityRenderer<IronGolemEntity, IronGolemEntityRenderState, IronGolemEntityModel> {
private static final ImmutableMap<Integer, Identifier> TEXTURES;
private static final ImmutableMap<Integer, Identifier> WAXED_TEXTURES;

public IronGolemEntityRendererMixin(EntityRendererFactory.Context context, IronGolemEntityModel entityModel, float f) {
super(context, entityModel, f);
}

@Inject(
method = "getTexture",
at = @At("HEAD"),
cancellable = true
)
public void getTextureWithRust(IronGolemEntityRenderState state, CallbackInfoReturnable<Identifier> cir){
IronGolemEntityRenderStateProxy stateProxy = ((IronGolemEntityRenderStateProxy) state);
RustState rustState = stateProxy.getRustState();
int level = Math.max(0, Math.min(3, rustState.level));
if(rustState.isWaxed)
cir.setReturnValue(WAXED_TEXTURES.get(level));
else
cir.setReturnValue(TEXTURES.get(level));
}

@Inject(
method = "updateRenderState",
at = @At("TAIL")
)
public void updateRenderStateWithRust(
IronGolemEntity entity,
IronGolemEntityRenderState state,
float f,
CallbackInfo ci
){
IronGolemEntityRenderStateProxy stateProxy = ((IronGolemEntityRenderStateProxy) state);
IronGolemEntityProxy entityProxy = ((IronGolemEntityProxy) entity);
stateProxy.setRustState(entityProxy.getRust().getState());
}

static {
TEXTURES = ImmutableMap.of(
0, Identifier.ofVanilla("textures/entity/iron_golem/iron_golem.png"),
1, Identifier.of("rust", "textures/entity/exposed_iron_golem.png"),
2, Identifier.of("rust", "textures/entity/weathered_iron_golem.png"),
3, Identifier.of("rust", "textures/entity/oxidized_iron_golem.png")
);
WAXED_TEXTURES = ImmutableMap.of(
0, Identifier.of("rust", "textures/entity/waxed_iron_golem.png"),
1, Identifier.of("rust", "textures/entity/waxed_exposed_iron_golem.png"),
2, Identifier.of("rust", "textures/entity/waxed_weathered_iron_golem.png"),
3, Identifier.of("rust", "textures/entity/waxed_oxidized_iron_golem.png")
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.adccadc.rust.mixin.render.state;

import com.adccadc.rust.manager.RustState;
import com.adccadc.rust.proxy.IronGolemEntityRenderStateProxy;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;
import net.minecraft.client.render.entity.state.IronGolemEntityRenderState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;

@Environment(EnvType.CLIENT)
@Mixin(IronGolemEntityRenderState.class)
public class IronGolemEntityRenderStateMixin implements IronGolemEntityRenderStateProxy {
@Unique
public RustState rustState;

@Override
public void setRustState(RustState state) {
this.rustState = state;
}

@Override
public RustState getRustState() {
return rustState;
}
}
15 changes: 15 additions & 0 deletions src/main/java/com/adccadc/rust/proxy/IronGolemEntityProxy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.adccadc.rust.proxy;

import com.adccadc.rust.manager.RustManager;
import net.fabricmc.api.EnvType;
import net.fabricmc.api.Environment;

@Environment(EnvType.CLIENT)
public interface IronGolemEntityProxy {

default IronGolemEntityProxy proxy(){
return this;
}

RustManager getRust();
}
Loading