Expanded on how new sounds are allowed to be registered, shovel effectiveness for soul sand, ghasts insta dying from their own fireballs and ladder climbing SFX

master
Wynd 2024-08-07 21:25:44 +03:00
parent 95c9317572
commit 7976cfabff
11 changed files with 140 additions and 39 deletions

View File

@ -1,9 +1,13 @@
package xyz.pixelatedw.finalbeta;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import net.fabricmc.api.ModInitializer;
public class MainMod implements ModInitializer {
public static final Logger LOGGER = LogManager.getLogger();
@Override
public void onInitialize() {
ModConfig.instance();

View File

@ -36,6 +36,8 @@ public class ModConfig {
"Allows 2 or more items of the same type to be repaired using a crafting table using the same formula as modern day vanilla uses");
public static final Option<Boolean> ENABLE_WHITE_WOOL_RECIPE = make("Enable White Wool Recipe", true,
"Allows dyed wool to be dyed back white using bone meal");
public static final Option<Boolean> ENABLE_GHASTS_INSTA_DEATH = make("Enable Ghast Insta Death", true,
"Allows ghasts to die in 1 shot when their fireballs get reflected at them");
public static final Option<Boolean> FIX_BOW_MODEL = make("Fix bow model", true,
"Makes the box model held by players and skeletons bigger and facing forward");
@ -51,6 +53,8 @@ public class ModConfig {
"Fixes pickaxes not being effective agaist certain blocks that it should be effective on");
public static final Option<Boolean> FIX_AXE_EFFECTIVENESS = make("Fix axe effectiveness", true,
"Fixes axes not being effective agaist certain blocks that it should be effective on");
public static final Option<Boolean> FIX_SHOVEL_EFFECTIVENESS = make("Fix shovel effectiveness", true,
"Fixes shovels not being effective agaist certain blocks that it should be effective on");
public static final Option<Boolean> FIX_SADDLES_NOT_DROPPING = make("Fix saddles not dropping", true,
"Fixes saddles not dropping when killing saddled pigs");
public static final Option<Boolean> FIX_FURNACE_LAVA_BUCKET = make("Fix furnace lava bucket", true,

View File

@ -2,7 +2,6 @@ package xyz.pixelatedw.finalbeta;
import java.lang.management.ManagementFactory;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.Duration;
import java.util.HashMap;
@ -10,10 +9,7 @@ import java.util.HashMap;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.Player;
import net.minecraft.item.ItemInstance;
import net.minecraft.item.ItemType;
import net.minecraft.recipe.RecipeRegistry;
import net.minecraft.tile.Tile;
import net.minecraft.tile.WoolTile;
public class WyHelper {
@ -22,7 +18,6 @@ public class WyHelper {
public static final String PLAY_TIME_TAG = "PlayTime";
public static long playTime;
// Look if they're allowed to hold all block and item data in fucking arrays
// I am also allowed to abuse maps to extend the shitty metadata excuse
// doors have ok ? I don't even care about the overhead at this point.
@ -93,29 +88,11 @@ public class WyHelper {
public static float clamp(float val, float min, float max) {
return val < min ? min : Math.min(val, max);
}
public static void registerWhiteWoolRecipe() {
Method method = getMethod(RecipeRegistry.class, new String[] { "addShapelessRecipe", "method_542" }, ItemInstance.class, Object[].class);
if (method == null) {
return;
}
try {
// Makes new recipes for all colored wools so they can be dyed back
// white using bone meal
for (int colorId = 0; colorId < 16; ++colorId) {
method.invoke(RecipeRegistry.getInstance(), new ItemInstance(Tile.WOOL, 1, 0), new Object[]{
new ItemInstance(Tile.WOOL, 1, WoolTile.method_2(colorId)), new ItemInstance(ItemType.dyePowder, 1, 15)});
}
} catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
public static void cheatCommand(Player player) {
player.dropItem(new ItemInstance(ItemType.redstone, 64));
player.dropItem(new ItemInstance(Tile.LADDER, 64));
player.dropItem(new ItemInstance(Tile.WOOD, 64));
// player.dropItem(new ItemInstance(ItemType.snowball, 60));
player.level.setLevelTime(0);
player.level.getProperties().setRaining(false);

View File

@ -1,5 +1,8 @@
package xyz.pixelatedw.finalbeta.mixin;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@ -7,6 +10,11 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.container.Container;
import net.minecraft.inventory.CraftingInventory;
import net.minecraft.item.ItemInstance;
import net.minecraft.item.ItemType;
import net.minecraft.recipe.RecipeRegistry;
import net.minecraft.tile.Tile;
import net.minecraft.tile.WoolTile;
import xyz.pixelatedw.finalbeta.ModConfig;
import xyz.pixelatedw.finalbeta.WyHelper;
@ -18,8 +26,27 @@ public class CraftingInventoryMixin {
@Inject(method = "<init>", at = @At("TAIL"))
public void init(Container container, int x, int y, CallbackInfo ci) {
if (ModConfig.ENABLE_WHITE_WOOL_RECIPE.get() && !hasCustomRecipesRegistered) {
WyHelper.registerWhiteWoolRecipe();
registerWhiteWoolRecipe();
hasCustomRecipesRegistered = true;
}
}
private static void registerWhiteWoolRecipe() {
Method method = WyHelper.getMethod(RecipeRegistry.class, new String[] { "addShapelessRecipe", "method_542" }, ItemInstance.class, Object[].class);
if (method == null) {
return;
}
try {
// Makes new recipes for all colored wools so they can be dyed back
// white using bone meal
for (int colorId = 0; colorId < 16; ++colorId) {
method.invoke(RecipeRegistry.getInstance(), new ItemInstance(Tile.WOOL, 1, 0), new Object[]{
new ItemInstance(Tile.WOOL, 1, WoolTile.method_2(colorId)), new ItemInstance(ItemType.dyePowder, 1, 15)});
}
} catch (SecurityException | IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) {
ex.printStackTrace();
}
}
}

View File

@ -4,12 +4,18 @@ 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;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.animal.Chicken;
import net.minecraft.entity.animal.Pig;
import net.minecraft.entity.monster.Ghast;
import net.minecraft.entity.player.Player;
import net.minecraft.entity.projectile.Snowball;
import net.minecraft.item.ItemType;
import xyz.pixelatedw.finalbeta.ModConfig;
import xyz.pixelatedw.finalbeta.WyHelper;
@Mixin(LivingEntity.class)
public class LivingEntityMixin {
@ -33,4 +39,25 @@ public class LivingEntityMixin {
}
}
}
@Inject(method = "damage", at = @At("HEAD"), cancellable = true)
public void damage(Entity thrower, int damage, CallbackInfoReturnable<Boolean> cir) {
LivingEntity entity = (LivingEntity) (Object) this;
if (ModConfig.ENABLE_GHASTS_INSTA_DEATH.get() && thrower != null && entity instanceof Ghast && thrower instanceof Snowball) {
LivingEntity fireballThrower = ((Snowball) thrower).field_2193;
if (fireballThrower instanceof Player) {
entity.damage(fireballThrower, 1_000);
cir.setReturnValue(true);
}
}
}
@Inject(method = "travel", at = @At("HEAD"))
public void travel(float f, float f1, CallbackInfo ci) {
LivingEntity entity = (LivingEntity) (Object) this;
if (ModConfig.ADD_MORE_SOUNDS.get() && entity.isOnLadder() && entity.velocityY != 0 && entity.field_1645 % 20 == 0 && !entity.onGround) {
float pitch = WyHelper.clamp(0.85f + entity.level.rand.nextFloat() / 2, 0.0f, 1.0f);
entity.level.playSound(entity.x, entity.y, entity.z, "step.ladder", 0.3f, pitch);
}
}
}

View File

@ -57,7 +57,7 @@ public class MinecartMixin {
}
if (speed >= 0.01D && ModConfig.ADD_MORE_SOUNDS.get()) {
if (minecart.field_1645 % 33 == 1) {
if (minecart.field_1645 % 39 == 1) {
minecart.level.playSound(x, y, z, "minecart.base", volume, pitch);
}
}

View File

@ -12,11 +12,14 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.client.Minecraft;
import xyz.pixelatedw.finalbeta.MainMod;
import xyz.pixelatedw.finalbeta.ModConfig;
@Mixin(Minecraft.class)
public class MinecraftMixin {
private static final String[] ALLOWED_NEW_SOUNDS = {"minecart/", "step/ladder"};
@Redirect(method = "init()V", at = @At(value = "INVOKE", target = "Lorg/lwjgl/opengl/Display;create()V"), remap = false)
public void createDisplay() throws LWJGLException {
// Why the fuck is this even a thing ? What was its intended purpose ? I NEED TO KNOW
@ -26,15 +29,26 @@ public class MinecraftMixin {
@Inject(method = "loadSoundFromDir", at = @At("HEAD"))
public void loadSoundFromDir(String string, File file, CallbackInfo ci) {
if(ModConfig.ADD_MORE_SOUNDS.get()) {
if(!ModConfig.ADD_MORE_SOUNDS.get()) {
Minecraft mc = (Minecraft) (Object) this;
int split = string.indexOf("/");
String type = string.substring(0, split);
String newSound = string.substring(split + 1);
// For now only allow the minecart sounds, allowing all of them causes weird effects with same name sounds when the game decides which one to use
// XXX Could always incorporate the sound3 part into the sound's name and have it accessible as sound3.random.bow for example, which would avoid the overlap with current sounds
if (type.equalsIgnoreCase("sound3") && newSound.startsWith("minecart/")) {
mc.soundHelper.method_2011(newSound, file);
if (type.equalsIgnoreCase("sound3")) {
boolean registerSound = false;
for (String test : ALLOWED_NEW_SOUNDS) {
if (newSound.startsWith(test)) {
registerSound = true;
break;
}
}
if (registerSound) {
MainMod.LOGGER.info("Registered a new sound " + newSound + " from " + file);
mc.soundHelper.method_2011(newSound, file);
}
}
}
}

View File

@ -1,8 +1,6 @@
package xyz.pixelatedw.finalbeta.mixin;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.Constant;
import org.spongepowered.asm.mixin.injection.ModifyConstant;
import net.minecraft.client.util.ResourceDownloadThread;
@ -11,8 +9,8 @@ public class ResourceDownloadThreadMixin {
private static final String RESOURCES_URL = "http://mcresources.modification-station.net/MinecraftResources/";
@ModifyConstant(method = "run", constant = @Constant(stringValue = "http://s3.amazonaws.com/MinecraftResources/"), remap = false)
private String getResourcesUrl(String def) {
return RESOURCES_URL;
}
// @ModifyConstant(method = "run", constant = @Constant(stringValue = "http://s3.amazonaws.com/MinecraftResources/"), remap = false)
// private String getResourcesUrl(String def) {
// return RESOURCES_URL;
// }
}

View File

@ -0,0 +1,41 @@
package xyz.pixelatedw.finalbeta.mixin;
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;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.projectile.Snowball;
import net.minecraft.util.hit.HitResult;
import net.minecraft.util.maths.Vec3d;
import xyz.pixelatedw.finalbeta.ModConfig;
@Mixin(Snowball.class)
public class SnowballMixin {
// Note, this is actually the "fireball" used by Ghasts. I guess they didn't have the fire charges done yet
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;damage(Lnet/minecraft/entity/Entity;I)Z", shift = At.Shift.BEFORE), locals = LocalCapture.CAPTURE_FAILHARD, cancellable = true)
private void newDamageRouter(CallbackInfo ci, Vec3d _v1, Vec3d _v2, HitResult result) {
Snowball fireball = ((Snowball)(Object)this);
if (ModConfig.ENABLE_GHASTS_INSTA_DEATH.get() && result != null && !fireball.level.isClient) {
if (result.entity != null && result.entity.damage(fireball, 0)) {
}
fireball.level.createExplosion((Entity) null, fireball.x, fireball.y, fireball.z, 1.0F, true);
fireball.remove();
ci.cancel();
}
}
@Inject(method = "damage", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/Entity;getRotation()Lnet/minecraft/util/maths/Vec3d;"), cancellable = true)
public void damage(Entity attacker, int damage, CallbackInfoReturnable<Boolean> cir) {
Snowball fireball = ((Snowball)(Object)this);
if (ModConfig.ENABLE_GHASTS_INSTA_DEATH.get() && attacker instanceof LivingEntity) {
fireball.field_2193 = (LivingEntity) attacker;
}
}
}

View File

@ -8,6 +8,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import net.minecraft.item.tool.HatchetItem;
import net.minecraft.item.tool.PickaxeItem;
import net.minecraft.item.tool.ShovelItem;
import net.minecraft.item.tool.ToolItem;
import net.minecraft.item.tool.ToolMaterial;
import net.minecraft.tile.Tile;
@ -28,6 +29,11 @@ public class ToolItemMixin {
Tile.STAIRS_WOOD, Tile.DOOR_WOOD, Tile.WOODEN_PRESSURE_PLATE, Tile.JUKEBOX, Tile.NOTEBLOCK, Tile.PUMPKIN, Tile.LIT_PUMPKIN,
Tile.STANDING_SIGN, Tile.WALL_SIGN, Tile.TRAPDOOR, Tile.LADDER, Tile.WORKBENCH, Tile.FENCE};
private static final Tile[] SHOVEL_BLOCKS = new Tile[]{Tile.GRASS, Tile.DIRT, Tile.SAND, Tile.GRAVEL, Tile.SNOW, Tile.SNOW_BLOCK,
Tile.CLAY, Tile.FARMLAND,
// Here starts the list of blocks that are not affected by default
Tile.SOUL_SAND};
@Shadow
public Tile[] field_2712;
@ -39,6 +45,8 @@ public class ToolItemMixin {
this.field_2712 = PICKAXE_BLOCKS;
} else if (tool instanceof HatchetItem && ModConfig.FIX_AXE_EFFECTIVENESS.get()) {
this.field_2712 = HATCHET_BLOCKS;
} else if (tool instanceof ShovelItem && ModConfig.FIX_SHOVEL_EFFECTIVENESS.get()) {
this.field_2712 = SHOVEL_BLOCKS;
}
}
}

View File

@ -39,7 +39,8 @@
"DoorTileMixin",
"CraftingContainerMixin",
"CraftingInventoryMixin",
"RecipeRegistryMixin"
"RecipeRegistryMixin",
"SnowballMixin"
],
"injectors": {
"defaultRequire": -1