Skip to content

Commit

Permalink
add invis armor stands. add hide item names. add frame sound; Close #7
Browse files Browse the repository at this point in the history
  • Loading branch information
SFort committed Aug 25, 2022
1 parent ec31254 commit b809c56
Show file tree
Hide file tree
Showing 12 changed files with 223 additions and 23 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ org.gradle.jvmargs=-Xmx1G
loader_version=0.12.6

# Mod Properties
mod_version = 2.1.1
mod_version = 2.2.0
maven_group = tf.ssf.sfort
archives_base_name = invisframes
66 changes: 54 additions & 12 deletions src/main/java/tf/ssf/sfort/invisframes/mixin/FrameConf.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package tf.ssf.sfort.invisframes.mixin;

import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.item.ItemStack;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
Expand All @@ -17,9 +19,15 @@ public class FrameConf implements IMixinConfigPlugin {
public static Logger LOGGER = LogManager.getLogger();

public static boolean clientForceInvis = false;
public static boolean allowProjectile = false;
public static boolean allowFrameProjectile = false;
public static boolean allowStandProjectile = false;
public static boolean playFrameSound = true;
public static boolean enableInvisFrames = true;
public static boolean enableInvisStands = true;
//byte0-client, byte1-server
public static int itemCheck = 1;
public static int frameItemCheck = 1;
public static int standItemCheck = 1;
public static int clientHideFrameNames = 0;

@Override
public void onLoad(String mixinPackage) {
Expand All @@ -33,20 +41,42 @@ public void onLoad(String mixinPackage) {
List<String> la = Files.readAllLines(confFile.toPath());
List<String> defaultDesc = Arrays.asList(
"^-Should client always make frames with items invisible [false] true | false // You would want to use this if the mod is installed client side only",
"^-Allow the use of projectiles for changing visibility [false] true | false //snowballs arrows etc",
"^-Frame has item check [client] client | server | both | none"
"^-Allow the use of projectiles for changing frame visibility [false] true | false //snowballs arrows etc",
"^-Frame has item check [client] client | server | both | none",
"^-Frame hides item names [never] never | always | invis_only // client-side only",
"^-Frame plays equip sound on being toggled [true] true | false",
"^-Enable invis item frames [true] true | false",
"^-Enable invis armor stands [true] true | false",
"^-Allow the use of projectiles for changing armor stand visibility [false] true | false",
"^-Armor Stand has item check [client] client | server | both | none"
);
String[] ls = la.toArray(new String[Math.max(la.size(), defaultDesc.size() * 2)|1]);
for (int i = 0; i<defaultDesc.size();++i)
ls[i*2+1]= defaultDesc.get(i);

try{clientForceInvis = ls[0].contains("true");}catch (Exception ignore){}
ls[0] = String.valueOf(clientForceInvis);
try{allowProjectile = ls[2].contains("true");}catch (Exception ignore){}
ls[2] = String.valueOf(allowProjectile);
try{
itemCheck = (ls[4].contains("both")? 3 : ls[4].contains("server")? 2 : ls[4].contains("none")? 0 : 1);}catch (Exception ignore){}
ls[4] = itemCheck == 3 ? "both" : itemCheck == 2 ? "server": itemCheck == 0 ? "none" : "client";
allowFrameProjectile = ls[2].contains("true");}catch (Exception ignore){}
ls[2] = String.valueOf(allowFrameProjectile);
try{
frameItemCheck = (ls[4].contains("both")? 3 : ls[4].contains("server")? 2 : ls[4].contains("none")? 0 : 1);}catch (Exception ignore){}
ls[4] = frameItemCheck == 3 ? "both" : frameItemCheck == 2 ? "server": frameItemCheck == 0 ? "none" : "client";
try {
clientHideFrameNames = ls[6].contains("always") ? 1 : ls[6].contains("invis_only") ? 2 : 0;
} catch (Exception ignore) {}
ls[6] = clientHideFrameNames == 2 ? "invis_only" : clientHideFrameNames == 1 ? "always" : "never";
try{playFrameSound = !ls[8].contains("false");}catch (Exception ignore){}
ls[8] = String.valueOf(playFrameSound);
try{enableInvisFrames = !ls[10].contains("false");}catch (Exception ignore){}
ls[10] = String.valueOf(enableInvisFrames);
try{enableInvisStands = !ls[12].contains("false");}catch (Exception ignore){}
ls[12] = String.valueOf(enableInvisStands);
try{allowStandProjectile = ls[14].contains("true");}catch (Exception ignore){}
ls[14] = String.valueOf(allowStandProjectile);
try{
standItemCheck = (ls[16].contains("both")? 3 : ls[16].contains("server")? 2 : ls[16].contains("none")? 0 : 1);}catch (Exception ignore){}
ls[16] = standItemCheck == 3 ? "both" : standItemCheck == 2 ? "server": standItemCheck == 0 ? "none" : "client";

Files.write(confFile.toPath(), Arrays.asList(ls));
LOGGER.log(Level.INFO,"tf.ssf.sfort.invisframes successfully loaded config file");
Expand All @@ -59,10 +89,15 @@ public void onLoad(String mixinPackage) {
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
return switch (mixinClassName) {
case mixin + ".FrameEntity" -> (itemCheck & 2) == 0;
case mixin + ".FrameEntityServer" -> (itemCheck & 2) != 0;
case mixin + ".FrameRender" -> (itemCheck & 1) != 0 && !clientForceInvis;
case mixin + ".FrameRenderForce" -> (itemCheck & 1) != 0 && clientForceInvis;
case mixin + ".FrameEntity" -> enableInvisFrames && (frameItemCheck & 2) == 0;
case mixin + ".FrameEntityServer" -> enableInvisFrames && (frameItemCheck & 2) != 0;
case mixin + ".FrameRender" -> (frameItemCheck & 1) != 0 && !clientForceInvis;
case mixin + ".FrameRenderForce" -> (frameItemCheck & 1) != 0 && clientForceInvis;
case mixin + ".FrameName" -> clientHideFrameNames == 2;
case mixin + ".FrameNameAlways" -> clientHideFrameNames == 1;
case mixin + ".StandRender" -> (standItemCheck & 1) != 0;
case mixin + ".StandEntity" -> enableInvisStands && (standItemCheck & 2) == 0;
case mixin + ".StandEntityServer" -> enableInvisStands && (standItemCheck & 2) != 0;
default -> true;
};
}
Expand All @@ -71,4 +106,11 @@ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
@Override public List<String> getMixins() { return null; }
@Override public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { }
@Override public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) { }

public static boolean IsEmpty(ArmorStandEntity entity) {
for(ItemStack item : entity.getArmorItems())
if(!item.isEmpty())
return false;
return true;
}
}
11 changes: 9 additions & 2 deletions src/main/java/tf/ssf/sfort/invisframes/mixin/FrameEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.decoration.AbstractDecorationEntity;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.world.World;
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.CallbackInfoReturnable;

@Mixin(value = ItemFrameEntity.class, priority = 2111)
@Mixin(ItemFrameEntity.class)
public abstract class FrameEntity extends AbstractDecorationEntity {
protected FrameEntity(EntityType<? extends AbstractDecorationEntity> entityType, World world) {
super(entityType, world);
Expand All @@ -20,9 +23,13 @@ protected FrameEntity(EntityType<? extends AbstractDecorationEntity> entityType,
@Inject(method = "damage",at =@At("HEAD"),cancellable = true)
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
Entity attacker = source.getAttacker();
if (attacker !=null && attacker.isSneaky() && (FrameConf.allowProjectile || source.getName().equals("player"))) {
if (attacker !=null && attacker.isSneaky() && (FrameConf.allowFrameProjectile || source.getName().equals("player"))) {
if (FrameConf.playFrameSound && world instanceof ServerWorld) {
world.playSound(null, getBlockPos(), SoundEvents.ITEM_ARMOR_EQUIP_GENERIC, SoundCategory.PLAYERS, 1, .7f + random.nextFloat()*.3f);
}
this.setInvisible(!this.isInvisible());
info.setReturnValue(true);
info.cancel();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,17 @@
import net.minecraft.entity.decoration.AbstractDecorationEntity;
import net.minecraft.entity.decoration.ItemFrameEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;

@Mixin(value = ItemFrameEntity.class, priority = 2111)
@Mixin(ItemFrameEntity.class)
public abstract class FrameEntityServer extends AbstractDecorationEntity {
protected FrameEntityServer(EntityType<? extends AbstractDecorationEntity> entityType, World world) {
super(entityType, world);
Expand All @@ -24,10 +27,15 @@ protected FrameEntityServer(EntityType<? extends AbstractDecorationEntity> entit
@Inject(method = "damage",at =@At("HEAD"),cancellable = true)
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
Entity attacker = source.getAttacker();
if (attacker !=null && attacker.isSneaky() && (FrameConf.allowProjectile || source.getName().equals("player"))) {
if (attacker !=null && attacker.isSneaky() && (FrameConf.allowFrameProjectile || source.getName().equals("player"))) {
if (FrameConf.playFrameSound && world instanceof ServerWorld) {
world.playSound(null, getBlockPos(), SoundEvents.ITEM_ARMOR_EQUIP_GENERIC, SoundCategory.PLAYERS, 1, .7f + random.nextFloat()*.3f);
}
this.setInvisible(!(this.isInvisible() || this.getHeldItemStack().isEmpty()));
info.setReturnValue(true);
}else
info.cancel();
} else {
this.setInvisible(false);
}
}
}
19 changes: 19 additions & 0 deletions src/main/java/tf/ssf/sfort/invisframes/mixin/FrameName.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package tf.ssf.sfort.invisframes.mixin;

import net.minecraft.client.render.entity.ItemFrameEntityRenderer;
import net.minecraft.entity.decoration.ItemFrameEntity;
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.CallbackInfoReturnable;

@Mixin(ItemFrameEntityRenderer.class)
public abstract class FrameName {
@Inject(method="hasLabel(Lnet/minecraft/entity/decoration/ItemFrameEntity;)Z",at=@At("HEAD"), cancellable = true)
public void itemHideName(ItemFrameEntity itemFrameEntity, CallbackInfoReturnable<Boolean> cir) {
if (itemFrameEntity.isInvisible()&&!itemFrameEntity.getHeldItemStack().isEmpty()) {
cir.setReturnValue(false);
cir.cancel();
}
}
}
17 changes: 17 additions & 0 deletions src/main/java/tf/ssf/sfort/invisframes/mixin/FrameNameAlways.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package tf.ssf.sfort.invisframes.mixin;

import net.minecraft.client.render.entity.ItemFrameEntityRenderer;
import net.minecraft.entity.decoration.ItemFrameEntity;
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.CallbackInfoReturnable;

@Mixin(ItemFrameEntityRenderer.class)
public abstract class FrameNameAlways {
@Inject(method="hasLabel(Lnet/minecraft/entity/decoration/ItemFrameEntity;)Z",at=@At("HEAD"), cancellable = true)
public void itemHideName(ItemFrameEntity itemFrameEntity, CallbackInfoReturnable<Boolean> cir) {
cir.setReturnValue(false);
cir.cancel();
}
}
4 changes: 2 additions & 2 deletions src/main/java/tf/ssf/sfort/invisframes/mixin/FrameRender.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(value = ItemFrameEntityRenderer.class, priority = 2111)
@Mixin(ItemFrameEntityRenderer.class)
public abstract class FrameRender {
@Redirect(method = "render",at =@At(value = "INVOKE",target = "Lnet/minecraft/entity/decoration/ItemFrameEntity;isInvisible()Z",ordinal = 0))
@Redirect(method="render",at =@At(value = "INVOKE",target = "Lnet/minecraft/entity/decoration/ItemFrameEntity;isInvisible()Z",ordinal = 0))
public boolean itemBeInvis(ItemFrameEntity itemFrameEntity) {
return itemFrameEntity.isInvisible()&&!itemFrameEntity.getHeldItemStack().isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(value = ItemFrameEntityRenderer.class, priority = 2111)
@Mixin(ItemFrameEntityRenderer.class)
public abstract class FrameRenderForce {
@Redirect(method = "render",at =@At(value = "INVOKE",target = "Lnet/minecraft/entity/decoration/ItemFrameEntity;isInvisible()Z",ordinal = 0))
public boolean itemBeInvis(ItemFrameEntity itemFrameEntity) {
Expand Down
29 changes: 29 additions & 0 deletions src/main/java/tf/ssf/sfort/invisframes/mixin/StandEntity.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package tf.ssf.sfort.invisframes.mixin;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.world.World;
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.CallbackInfoReturnable;

@Mixin(ArmorStandEntity.class)
public abstract class StandEntity extends LivingEntity {
protected StandEntity(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
}

@Inject(method="damage", at=@At("HEAD"), cancellable = true)
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
Entity attacker = source.getAttacker();
if (attacker !=null && attacker.isSneaky() && (FrameConf.allowStandProjectile || source.getName().equals("player"))) {
this.setInvisible(!this.isInvisible());
info.setReturnValue(true);
info.cancel();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package tf.ssf.sfort.invisframes.mixin;

import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.decoration.ArmorStandEntity;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
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(ArmorStandEntity.class)
public abstract class StandEntityServer extends LivingEntity {
@Shadow public abstract void setInvisible(boolean invisible);

protected StandEntityServer(EntityType<? extends LivingEntity> entityType, World world) {
super(entityType, world);
}

@Inject(method="damage", at=@At("HEAD"), cancellable = true)
public void damage(DamageSource source, float amount, CallbackInfoReturnable<Boolean> info) {
Entity attacker = source.getAttacker();
if (attacker !=null && attacker.isSneaky() && (FrameConf.allowStandProjectile || source.getName().equals("player"))) {
this.setInvisible(!(this.isInvisible() || FrameConf.IsEmpty((ArmorStandEntity) (Object) this)));
info.setReturnValue(true);
info.cancel();
} else {
this.setInvisible(false);
}
}
@Inject(method="equipStack(Lnet/minecraft/entity/EquipmentSlot;Lnet/minecraft/item/ItemStack;)V", at=@At("RETURN"))
public void update(CallbackInfo ci) {
if (FrameConf.IsEmpty((ArmorStandEntity) (Object) this)) {
this.setInvisible(false);
}
}
}
32 changes: 32 additions & 0 deletions src/main/java/tf/ssf/sfort/invisframes/mixin/StandRender.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package tf.ssf.sfort.invisframes.mixin;

import net.minecraft.client.render.entity.ArmorStandEntityRenderer;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.decoration.ArmorStandEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyVariable;

@Mixin(ArmorStandEntityRenderer.class)
public abstract class StandRender {
private boolean survivalflight$secondBool = false;

@ModifyVariable(method="getRenderLayer(Lnet/minecraft/entity/LivingEntity;ZZZ)Lnet/minecraft/client/render/RenderLayer;", at=@At("HEAD"), ordinal=0, argsOnly=true)
public boolean getRenderLayer(boolean old, LivingEntity entity, boolean bl) {
if (entity instanceof ArmorStandEntity) {
if (FrameConf.IsEmpty((ArmorStandEntity) entity)) {
survivalflight$secondBool = false;
return true;
} else {
survivalflight$secondBool = !old;
}
}
return old;
}
@ModifyVariable(method="getRenderLayer(Lnet/minecraft/entity/LivingEntity;ZZZ)Lnet/minecraft/client/render/RenderLayer;", at=@At("HEAD"), ordinal=1, argsOnly=true)
public boolean getRenderLayer2(boolean old, LivingEntity entity, boolean bl) {
if (survivalflight$secondBool) return false;
return old;
}

}
9 changes: 7 additions & 2 deletions src/main/resources/invisframes.mixins.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,16 @@
"plugin": "tf.ssf.sfort.invisframes.mixin.FrameConf",
"mixins": [
"FrameEntity",
"FrameEntityServer"
"FrameEntityServer",
"StandEntity",
"StandEntityServer"
],
"client": [
"FrameRender",
"FrameRenderForce"
"FrameRenderForce",
"FrameName",
"FrameNameAlways",
"StandRender"
],
"injectors": {
"defaultRequire": 1
Expand Down

0 comments on commit b809c56

Please sign in to comment.