entityType) {
Mob mob = ctx.spawnWithNoFreeWill(entityType, new BlockPos(0, 4, 0));
// TODO:
ctx.runAfterDelay(50, ctx::succeed);
}
}
================================================
FILE: src/gametest/java/dev/isxander/debugify/test/suites/MC72151.java
================================================
package dev.isxander.debugify.test.suites;
import net.fabricmc.fabric.api.gametest.v1.GameTest;
import net.minecraft.core.BlockPos;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.animal.wolf.Wolf;
import net.minecraft.world.entity.projectile.Snowball;
public class MC72151 {
@GameTest
public void mc72151(GameTestHelper ctx) {
BlockPos wolfPos = new BlockPos(4, 0, 4);
Wolf wolf = ctx.spawnWithNoFreeWill(EntityType.WOLF, wolfPos);
wolf.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0);
Snowball snowball = ctx.spawn(EntityType.SNOWBALL, 0, 0, 4);
double d = wolf.getEyeY() - 1.1F;
double e = wolf.getX() - snowball.getX();
double f = d - snowball.getY();
double g = wolf.getZ() - snowball.getZ();
double h = Math.sqrt(e * e + g * g) * 0.2F;
snowball.shoot(e, f + h, g, 1.6F, 0f);
ctx.succeedIf(() -> ctx.assertTrue(wolf.getHealth() == wolf.getMaxHealth(), Component.literal("Wolf shouldn't be damaged.")));
}
}
================================================
FILE: src/gametest/java/dev/isxander/debugify/test/suites/MC8187.java
================================================
package dev.isxander.debugify.test.suites;
import dev.isxander.debugify.test.DebugifyTestUtils;
import net.fabricmc.fabric.api.gametest.v1.GameTest;
import net.minecraft.core.BlockPos;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.network.chat.Component;
import net.minecraft.tags.BlockTags;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState;
/**
* Dedicated test suite for MC-8187.
*
* This is likely well over-engineered with asserting that the test will always work.
*
* @author Ampflower
* @since 1.20.1+1.2
**/
public class MC8187 {
private static final String TEMPLATE = "debugify:mc-8187";
// Adjust this if you move the center, as the tests assume this is accurate.
private static final int SIZE = 18;
// Subtracting one to get NW center.
private static final int CENTER = SIZE / 2 - 1;
private static final BlockPos CORNER = new BlockPos(CENTER, 1, CENTER);
private static final BlockPos START_CORNER = CORNER.above();
private static final BlockPos END_CORNER = CORNER.offset(1, 1, 1);
/**
* Tests that the tree will grow under random ticks.
*
* Side effect: Sets the time to day.
*/
private static void testTreeRandomTick(GameTestHelper ctx, Block sapling, Block log, BlockPos growCorner, boolean small) {
// Ensure that parameters are correct.
ctx.assertTrue(sapling instanceof SaplingBlock, Component.literal(sapling + " is not a sapling"));
testTreeParamCommon(ctx, sapling, log, growCorner, true);
// Setup
final BlockState saplingState = sapling.defaultBlockState().setValue(SaplingBlock.STAGE, 1);
ctx.onEachTick(() -> ctx.randomTick(growCorner));
testTreeCommon(ctx, saplingState, log, growCorner, small);
}
/**
* Tests that the tree will grow with bonemeal.
*/
private static void testTreeBonemeal(GameTestHelper ctx, Block sapling, Block log, BlockPos growCorner, boolean small) {
// Ensure that parameters are correct.
ctx.assertTrue(sapling instanceof SaplingBlock, Component.literal(sapling + " is not a sapling"));
testTreeParamCommon(ctx, sapling, log, growCorner, false);
// Setup
final BlockState saplingState = sapling.defaultBlockState().setValue(SaplingBlock.STAGE, 1);
DebugifyTestUtils.bonemealIndefinitely(ctx, growCorner);
testTreeCommon(ctx, saplingState, log, growCorner, small);
}
/**
* Tests that the azalea will grow with bonemeal.
*/
private static void testAzalea(GameTestHelper ctx, Block sapling, Block log, BlockPos growCorner) {
// Ensure that parameters are correct.
ctx.assertTrue(sapling instanceof AzaleaBlock, Component.literal(sapling + " is not a sapling"));
testTreeParamCommon(ctx, sapling, log, growCorner, false);
DebugifyTestUtils.bonemealIndefinitely(ctx, growCorner);
testTreeCommon(ctx, sapling.defaultBlockState(), log, growCorner, true);
}
/**
* Asserts that the given parameters are correct.
*
* This is to catch errors quickly as the input is sensitive to off by 1 errors.
*/
private static void testTreeParamCommon(GameTestHelper ctx, Block sapling, Block log, BlockPos growCorner, boolean requiresDay) {
ctx.assertTrue(log instanceof RotatedPillarBlock, Component.literal(log + " does not appear like a log"));
ctx.assertTrue(growCorner.getY() == START_CORNER.getY(),
Component.literal("Incorrect Y, got " + growCorner.getY() + ", expected " + START_CORNER.getY()));
// Ensure that the structure is correctly set up.
assertSuitable(ctx, requiresDay);
}
/**
* Continuously checks whether the tree has grown.
*/
private static void testTreeCommon(GameTestHelper ctx, BlockState sapling, Block log, BlockPos growCorner, boolean small) {
DebugifyTestUtils.fill(ctx, START_CORNER, END_CORNER, sapling);
if (small) {
ctx.succeedWhen(() -> ctx.assertBlock(growCorner, block -> block == log, block -> Component.literal("Incorrect log, expected " + log)));
} else {
ctx.succeedWhen(() -> DebugifyTestUtils.assertBlockFill(ctx, START_CORNER, END_CORNER, block -> block == log,
"Incorrect log, expected " + log));
}
}
@GameTest(structure = TEMPLATE, skyAccess = true)
public void oak_randomTick_NW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.OAK_SAPLING, Blocks.OAK_LOG, START_CORNER, true);
}
@GameTest(structure = TEMPLATE, skyAccess = true)
public void birch_randomTick_NW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.BIRCH_SAPLING, Blocks.BIRCH_LOG, START_CORNER, true);
}
@GameTest(structure = TEMPLATE, skyAccess = true)
public void spruce_randomTick_NW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.SPRUCE_SAPLING, Blocks.SPRUCE_LOG, START_CORNER, false);
}
@GameTest(structure = TEMPLATE, skyAccess = true)
public void jungle_randomTick_NW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.JUNGLE_SAPLING, Blocks.JUNGLE_LOG, START_CORNER, false);
}
@GameTest(structure = TEMPLATE, skyAccess = true)
public void acacia_randomTick_NW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.ACACIA_SAPLING, Blocks.ACACIA_LOG, START_CORNER, true);
}
@GameTest(structure = TEMPLATE, skyAccess = true)
public void darkOak_randomTick_NW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.DARK_OAK_SAPLING, Blocks.DARK_OAK_LOG, START_CORNER, false);
}
@GameTest(structure = TEMPLATE, skyAccess = true)
public void cherry_randomTick_NW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.CHERRY_SAPLING, Blocks.CHERRY_LOG, START_CORNER, true);
}
@GameTest(structure = TEMPLATE)
public void oak_bonemeal_NW(GameTestHelper ctx) {
testTreeBonemeal(ctx, Blocks.OAK_SAPLING, Blocks.OAK_LOG, START_CORNER, true);
}
@GameTest(structure = TEMPLATE)
public void birch_bonemeal_NW(GameTestHelper ctx) {
testTreeBonemeal(ctx, Blocks.BIRCH_SAPLING, Blocks.BIRCH_LOG, START_CORNER, true);
}
@GameTest(structure = TEMPLATE)
public void spruce_bonemeal_NW(GameTestHelper ctx) {
testTreeBonemeal(ctx, Blocks.SPRUCE_SAPLING, Blocks.SPRUCE_LOG, START_CORNER, false);
}
@GameTest(structure = TEMPLATE)
public void jungle_bonemeal_NW(GameTestHelper ctx) {
testTreeBonemeal(ctx, Blocks.JUNGLE_SAPLING, Blocks.JUNGLE_LOG, START_CORNER, false);
}
@GameTest(structure = TEMPLATE)
public void acacia_bonemeal_NW(GameTestHelper ctx) {
testTreeBonemeal(ctx, Blocks.ACACIA_SAPLING, Blocks.ACACIA_LOG, START_CORNER, true);
}
@GameTest(structure = TEMPLATE)
public void darkOak_bonemeal_NW(GameTestHelper ctx) {
testTreeBonemeal(ctx, Blocks.DARK_OAK_SAPLING, Blocks.DARK_OAK_LOG, START_CORNER, false);
}
@GameTest(structure = TEMPLATE)
public void cherry_bonemeal_NW(GameTestHelper ctx) {
testTreeBonemeal(ctx, Blocks.CHERRY_SAPLING, Blocks.CHERRY_LOG, START_CORNER, true);
}
// The following two needs to be special-cased.
@GameTest(structure = TEMPLATE)
public void azaleaNW(GameTestHelper ctx) {
testAzalea(ctx, Blocks.AZALEA, Blocks.OAK_LOG, START_CORNER);
}
// @GameTest(template = TEMPLATE)
public void mangroveNW(GameTestHelper ctx) {
testTreeRandomTick(ctx, Blocks.MANGROVE_PROPAGULE, Blocks.MANGROVE_LOG, START_CORNER, true);
}
/**
* Asserts that the input parameters are suitable for use.
*/
private static void assertSuitable(GameTestHelper ctx, boolean requiresDay) {
// Force it to be day for random-tick-based tests.
if (requiresDay) {
ctx.setDayTime(DebugifyTestUtils.TIME_OF_DAY_NOON);
}
// For some reason, + 1 is required.
final var pos = CORNER;
DebugifyTestUtils.assertBlockStateFill(ctx, pos, pos.offset(1, 0, 1), b -> b.is(BlockTags.DIRT), "Invalid template; not dirt");
DebugifyTestUtils.assertBlockFill(ctx, pos.above(), pos.offset(1, 1, 1), b -> b == Blocks.AIR, "Invalid template; not air");
ctx.assertBlockState(pos.offset(-1, 1, -1), b -> !b.canBeReplaced(), block -> Component.literal("Invalid template; NW block not solid"));
}
}
================================================
FILE: src/gametest/java/dev/isxander/debugify/test/suites/MC93018.java
================================================
package dev.isxander.debugify.test.suites;
import net.fabricmc.fabric.api.gametest.v1.GameTest;
import net.minecraft.gametest.framework.GameTestHelper;
import net.minecraft.network.chat.Component;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ai.attributes.Attributes;
import net.minecraft.world.entity.animal.wolf.Wolf;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.GameType;
public class MC93018 {
@GameTest
public void mc93018(GameTestHelper ctx) {
Player player = ctx.makeMockPlayer(GameType.SURVIVAL);
player.setItemInHand(InteractionHand.MAIN_HAND, Items.BONE.getDefaultInstance());
ctx.getLevel().addFreshEntity(player);
Wolf wolf = ctx.spawn(EntityType.WOLF, 2, 0, 0);
wolf.getAttribute(Attributes.MOVEMENT_SPEED).setBaseValue(0.0);
wolf.mobInteract(player, InteractionHand.MAIN_HAND);
ctx.succeedIf(() -> ctx.assertTrue(wolf.getInLoveTime() <= 0, Component.literal("Wolf shouldn't love player")));
}
}
================================================
FILE: src/gametest/resources/data/debugify/gametest/structures/mc-8187.snbt
================================================
{
DataVersion: 3463,
size: [18, 50, 18],
data: [
{pos: [8, 0, 8], state: "minecraft:grass_block{snowy:false}"},
{pos: [8, 0, 9], state: "minecraft:grass_block{snowy:false}"},
{pos: [9, 0, 8], state: "minecraft:grass_block{snowy:false}"},
{pos: [9, 0, 9], state: "minecraft:grass_block{snowy:false}"},
{pos: [7, 1, 7], state: "minecraft:stone"},
{pos: [7, 1, 8], state: "minecraft:stone"},
{pos: [7, 1, 9], state: "minecraft:stone"},
{pos: [7, 1, 10], state: "minecraft:stone"},
{pos: [8, 1, 7], state: "minecraft:stone"},
{pos: [8, 1, 10], state: "minecraft:stone"},
{pos: [9, 1, 7], state: "minecraft:stone"},
{pos: [9, 1, 10], state: "minecraft:stone"},
{pos: [10, 1, 7], state: "minecraft:stone"},
{pos: [10, 1, 8], state: "minecraft:stone"},
{pos: [10, 1, 9], state: "minecraft:stone"},
{pos: [10, 1, 10], state: "minecraft:stone"}
],
entities: [],
palette: [
"minecraft:grass_block{snowy:false}",
"minecraft:stone"
]
}
================================================
FILE: src/gametest/resources/fabric.mod.json
================================================
{
"schemaVersion": 1,
"id": "debugify-test",
"version": "1.0.0",
"name": "Debugify (Game Test)",
"license": "LGPLv3",
"environment": "*",
"icon": "debugify.png",
"entrypoints": {
"fabric-gametest": [
"dev.isxander.debugify.test.suites.MC72151",
"dev.isxander.debugify.test.suites.MC8187",
"dev.isxander.debugify.test.suites.MC93018",
"dev.isxander.debugify.test.suites.MC30391",
"dev.isxander.debugify.test.suites.MC100991"
],
"debugify": [
"dev.isxander.debugify.test.DebugifyApiTest"
]
},
"depends": {
"debugify": "*",
"fabric-gametest-api-v1": "*"
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/Debugify.java
================================================
package dev.isxander.debugify;
import dev.isxander.debugify.config.DebugifyConfig;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.error.DebugifyErrorHandler;
import net.fabricmc.api.EnvType;
import net.fabricmc.loader.api.FabricLoader;
import net.fabricmc.loader.api.Version;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.spongepowered.asm.mixin.Mixins;
import java.util.List;
import java.util.Map;
public class Debugify {
public static final Logger LOGGER = LoggerFactory.getLogger("Debugify");
public static final Version VERSION = FabricLoader.getInstance().getModContainer("debugify").orElseThrow().getMetadata().getVersion();
public static final DebugifyConfig CONFIG = new DebugifyConfig();
/**
* Called from mixin plugin to manage
* disabled bug fixes
*/
public static void onPreInitialize() {
CONFIG.preload();
Mixins.registerErrorHandlerClass(DebugifyErrorHandler.class.getName());
}
public static void onInitialize() {
List enabledBugs = CONFIG.getBugFixes().entrySet()
.stream()
.filter(Map.Entry::getValue)
.map(entry -> entry.getKey().bugId())
.toList();
LOGGER.info("Enabled {} bug fixes: {}", enabledBugs.size(), enabledBugs);
LOGGER.info("Successfully Debugify'd your game!");
}
public static BugFix.Env getEnv() {
return FabricLoader.getInstance().getEnvironmentType() == EnvType.CLIENT ? BugFix.Env.CLIENT : BugFix.Env.SERVER;
}
public static boolean isGameplayFixesEnabled() {
return Debugify.CONFIG.gameplayFixesInMultiplayer;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/api/DebugifyApi.java
================================================
package dev.isxander.debugify.api;
import java.util.Map;
import java.util.Set;
public interface DebugifyApi {
/**
* Returns an array of bug ids (e.g. MC-577) to disable due to this mod
*/
default String[] getDisabledFixes() {
return new String[0];
}
/**
* Provides a map of mod id to a set of bug ids to disable fixes
* due to other mods.
*/
default Map> getProvidedDisabledFixes() {
return Map.of();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/config/DebugifyConfig.java
================================================
package dev.isxander.debugify.config;
import dev.isxander.debugify.Debugify;
import dev.isxander.debugify.fixes.BugFixData;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonObject;
import net.fabricmc.loader.api.FabricLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.stream.Collectors;
public class DebugifyConfig {
private final Path configPath = Path.of("config", "debugify.json");
private final Gson gson = new GsonBuilder().setPrettyPrinting().create();
private final Map jsonBugFixes = new HashMap<>();
private final Map bugFixes = new TreeMap<>();
public boolean defaultDisabled = false;
public boolean optOutUpdater = false;
public boolean gameplayFixesInMultiplayer = false;
private boolean preloaded = false;
public void registerBugFix(BugFixData bugFix) {
if (bugFixes.containsKey(bugFix))
return;
boolean enabled = jsonBugFixes.getOrDefault(bugFix.bugId(), bugFix.enabledByDefault() && !defaultDisabled);
bugFixes.put(bugFix, enabled);
}
public void preload() {
if (preloaded) return;
preloaded = true;
if (!Files.exists(configPath)) {
if (FabricLoader.getInstance().isModLoaded("yosbr")
&& Files.exists(configPath.getParent().resolve("yosbr/" + configPath.getFileName().toString()))) {
throw new YosbrError();
}
return;
}
Debugify.LOGGER.info("Preloading Debugify");
try {
String jsonString = Files.readString(configPath);
JsonObject json = gson.fromJson(jsonString, JsonObject.class);
if (json.has("opt_out_updater")) {
optOutUpdater = json.get("opt_out_updater").getAsBoolean();
}
if (json.has("default_disabled")) {
defaultDisabled = json.get("default_disabled").getAsBoolean();
}
if (json.has("gameplay_fixes_in_multiplayer")) {
gameplayFixesInMultiplayer = json.get("gameplay_fixes_in_multiplayer").getAsBoolean();
}
Map bugFixes = json.entrySet().stream()
.filter((entry) -> entry.getKey().startsWith("MC-") && entry.getValue().isJsonPrimitive() && entry.getValue().getAsJsonPrimitive().isBoolean())
.map((entry) -> new AbstractMap.SimpleEntry<>(entry.getKey(), entry.getValue().getAsBoolean()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
jsonBugFixes.clear();
jsonBugFixes.putAll(bugFixes);
} catch (Exception e) {
e.printStackTrace();
}
}
public void save() {
Debugify.LOGGER.info("Saving Debugify");
try {
Files.deleteIfExists(configPath);
JsonObject json = new JsonObject();
bugFixes.forEach((fix, enabled) -> {
if (!defaultDisabled || enabled) json.addProperty(fix.bugId(), enabled);
});
json.addProperty("opt_out_updater", optOutUpdater);
json.addProperty("gameplay_fixes_in_multiplayer", gameplayFixesInMultiplayer);
json.addProperty("default_disabled", defaultDisabled);
Files.createFile(configPath);
Files.writeString(configPath, gson.toJson(json));
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isBugFixEnabled(BugFixData bug) {
return bugFixes.getOrDefault(bug, false);
}
public Map getBugFixes() {
return bugFixes;
}
public boolean doesJsonHaveIdenticalKeys() {
return jsonBugFixes.keySet().containsAll(bugFixes.keySet().stream().map(BugFixData::bugId).collect(Collectors.toSet()))
&& jsonBugFixes.size() == bugFixes.size();
}
private static class YosbrError extends Error {
public YosbrError() {
super("Debugify config loaded using YOSBR mod! This doesn't work! Please move 'debugify.json' out of the 'yosbr' folder!");
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/error/CrashReportInjector.java
================================================
package dev.isxander.debugify.error;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Set;
/**
* Adds details to crash report if Debugify recovered from a mixin application error.
* This is needed because in some cases, partial mixin application may lead to runtime crashes,
* and crash reports will not include the original mixin application error details that Debugify
* logs in {@link DebugifyErrorHandler}.
*/
public class CrashReportInjector {
public static void addDetailsToCrashReport(StringBuilder sb) {
Set erroredFixes = DebugifyErrorHandler.getErroredFixes();
if (!erroredFixes.isEmpty()) {
sb.append("\n-- Debugify recovered from mixin application errors --\n");
sb.append("Some bug fixes failed to apply, which could have led to this crash.\n");
sb.append("This log does not mean Debugify caused the crash, but it could have.\n\n");
for (var entry : erroredFixes) {
sb.append(stringifyErrorEntry(entry)).append("\n");
}
}
}
private static String stringifyErrorEntry(MixinErrorEntry entry) {
var stringWriter = new StringWriter();
var printWriter = new PrintWriter(stringWriter);
entry.throwable().printStackTrace(printWriter);
String stacktrace = stringWriter.toString();
return "%s fix failed to fully apply due to %s during %s\n%s".formatted(
entry.fix().bugId(),
entry.mixinInfo().getName(),
entry.errorStage().name(),
stacktrace
);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/error/DebugifyErrorHandler.java
================================================
package dev.isxander.debugify.error;
import dev.isxander.debugify.Debugify;
import dev.isxander.debugify.fixes.BugFixData;
import dev.isxander.debugify.mixinplugin.BugFixDataCache;
import org.spongepowered.asm.mixin.extensibility.IMixinConfig;
import org.spongepowered.asm.mixin.extensibility.IMixinErrorHandler;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.Set;
public class DebugifyErrorHandler implements IMixinErrorHandler {
private static final Set ERRORED_FIXES = new HashSet<>();
@Override
public ErrorAction onPrepareError(IMixinConfig config, Throwable th, IMixinInfo mixin, ErrorAction action) {
return handleError(action, mixin, th, ErrorStage.PREPARE);
}
@Override
public ErrorAction onApplyError(String targetClassName, Throwable th, IMixinInfo mixin, ErrorAction action) {
return handleError(action, mixin, th, ErrorStage.APPLY);
}
private ErrorAction handleError(ErrorAction usualAction, IMixinInfo mixin, Throwable th, ErrorStage stage) {
Optional bugFix = BugFixDataCache.getIfResolved(mixin.getClassName());
if (bugFix.isEmpty())
return usualAction;
BugFixData fix = bugFix.get();
ERRORED_FIXES.add(new MixinErrorEntry(fix, mixin, th, stage));
// no need to add exception here, it's already logged under ErrorAction.WARN
Debugify.LOGGER.error("Failed to fully apply bug fix {}, mixin class {} will not be applied! This may cause runtime errors if a partial injection occurs.", fix.bugId(), mixin.getName());
return ErrorAction.WARN;
}
public static boolean hasErrored(BugFixData fix) {
return ERRORED_FIXES.stream().anyMatch(entry -> entry.fix().equals(fix));
}
public static Set getErroredFixes() {
return Collections.unmodifiableSet(ERRORED_FIXES);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/error/ErrorStage.java
================================================
package dev.isxander.debugify.error;
public enum ErrorStage {
PREPARE,
APPLY
}
================================================
FILE: src/main/java/dev/isxander/debugify/error/MixinErrorEntry.java
================================================
package dev.isxander.debugify.error;
import dev.isxander.debugify.fixes.BugFixData;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
public record MixinErrorEntry(BugFixData fix, IMixinInfo mixinInfo, Throwable throwable, ErrorStage errorStage) {
}
================================================
FILE: src/main/java/dev/isxander/debugify/fixes/BugFix.java
================================================
package dev.isxander.debugify.fixes;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface BugFix {
String id();
FixCategory category();
Env env();
boolean enabled() default true;
String[] modConflicts() default {};
OS os() default OS.UNKNOWN;
String description() default "";
enum Env {
CLIENT("debugify.env.client"),
SERVER("debugify.env.server");
private final String displayName;
Env(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return displayName;
}
public String getDescriptionKey() {
return getDisplayName() + ".desc";
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/fixes/BugFixData.java
================================================
package dev.isxander.debugify.fixes;
import dev.isxander.debugify.mixinplugin.DebugifyDebugFlags;
import net.fabricmc.loader.api.FabricLoader;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
import java.util.stream.Collectors;
public record BugFixData(String bugId, FixCategory category, BugFix.Env env, boolean enabledByDefault, List conflicts, OS requiredOs, @Nullable String description) implements Comparable {
private static final Map> externalModConflicts = new HashMap<>();
public static void registerApiConflict(String modId, String bugId) {
externalModConflicts.computeIfAbsent(bugId, b -> new HashSet<>()).add(modId);
}
public Set getActiveConflicts() {
Set conflicts = conflicts().stream().filter(id -> FabricLoader.getInstance().isModLoaded(id)).collect(Collectors.toSet());
Set apiConflicts = externalModConflicts.get(bugId());
if (apiConflicts != null) conflicts.addAll(apiConflicts);
return conflicts;
}
public boolean satisfiesOSRequirement() {
return requiredOs() == OS.UNKNOWN || requiredOs() == OS.getOperatingSystem()
|| (requiredOs() == OS.LINUX && DebugifyDebugFlags.FORCE_LINUX_FIXES)
|| (requiredOs() == OS.WINDOWS && DebugifyDebugFlags.FORCE_WINDOWS_FIXES)
|| (requiredOs() == OS.MAC && DebugifyDebugFlags.FORCE_MACOS_FIXES);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof BugFixData bugFixData)
return bugFixData.bugId.equals(bugId);
return false;
}
@Override
public int compareTo(@NotNull BugFixData o) {
if (o.bugId.length() == bugId.length()) {
return bugId.compareTo(o.bugId);
}
return Integer.compare(bugId.length(), o.bugId.length());
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/fixes/FixCategory.java
================================================
package dev.isxander.debugify.fixes;
public enum FixCategory {
BASIC("debugify.basic"),
GAMEPLAY("debugify.gameplay");
private final String displayName;
FixCategory(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return this.displayName;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/fixes/OS.java
================================================
package dev.isxander.debugify.fixes;
import java.util.Locale;
/**
* Cannot use {@link net.minecraft.Util.OS} because
* this code needs to be run from a Mixin plugin, where you can't access
* Minecraft classes.
*/
public enum OS {
WINDOWS("debugify.os.windows"),
MAC("debugify.os.macos"),
LINUX("debugify.os.linux"),
SOLARIS("debugify.os.solaris"),
UNKNOWN("debugify.os.unknown");
public static OS getOperatingSystem() {
String string = System.getProperty("os.name").toLowerCase(Locale.ROOT);
if (string.contains("win")) {
return OS.WINDOWS;
} else if (string.contains("mac")) {
return OS.MAC;
} else if (string.contains("solaris")) {
return OS.SOLARIS;
} else if (string.contains("sunos")) {
return OS.SOLARIS;
} else if (string.contains("linux")) {
return OS.LINUX;
} else {
return string.contains("unix") ? OS.LINUX : OS.UNKNOWN;
}
}
private final String displayName;
OS(String displayName) {
this.displayName = displayName;
}
public String getDisplayName() {
return this.displayName;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixinplugin/BugFixDataCache.java
================================================
package dev.isxander.debugify.mixinplugin;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.BugFixData;
import dev.isxander.debugify.fixes.FixCategory;
import dev.isxander.debugify.fixes.OS;
import org.jetbrains.annotations.Nullable;
import org.objectweb.asm.tree.AnnotationNode;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.service.MixinService;
import org.spongepowered.asm.util.Annotations;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class BugFixDataCache {
private static final Map bugFixDataByMixinClass = new HashMap<>();
public static Optional getOrResolve(String mixinClassName) {
return Optional.ofNullable(
bugFixDataByMixinClass.computeIfAbsent(mixinClassName, BugFixDataCache::resolve)
.data()
);
}
public static Optional getIfResolved(String mixinClassName) {
return Optional.ofNullable(bugFixDataByMixinClass.get(mixinClassName))
.flatMap(resolved -> Optional.ofNullable(resolved.data()));
}
private static ResolvedBugFixData resolve(String mixinClassName) {
ClassNode classNode = getClassNode(mixinClassName);
if (classNode == null) {
return new ResolvedBugFixData(null);
}
AnnotationNode annotationNode = Annotations.getVisible(classNode, BugFix.class);
if (annotationNode == null) {
return new ResolvedBugFixData(null);
}
String id = Annotations.getValue(annotationNode, "id");
FixCategory category = getAnnotationEnumValue(annotationNode, "category", FixCategory.class);
BugFix.Env env = getAnnotationEnumValue(annotationNode, "env", BugFix.Env.class);
boolean enabledByDefault = Annotations.getValue(annotationNode, "enabled", Boolean.valueOf(true));
List conflicts = Annotations.getValue(annotationNode, "modConflicts", true);
OS requiredOS = Annotations.getValue(annotationNode, "os", OS.class, OS.UNKNOWN);
String description = Annotations.getValue(annotationNode, "description");
if ("".equals(description)) {
description = null;
}
return new ResolvedBugFixData(new BugFixData(id, category, env, enabledByDefault, conflicts, requiredOS, description));
}
private static ClassNode getClassNode(String className) {
try {
return MixinService.getService().getBytecodeProvider().getClassNode(className);
} catch (ClassNotFoundException | IOException e) {
return null;
}
}
private static > T getAnnotationEnumValue(AnnotationNode annotation, String key, Class enumClass) {
String[] value = Annotations.getValue(annotation, key);
return Enum.valueOf(enumClass, value[1]);
}
record ResolvedBugFixData(@Nullable BugFixData data) {}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixinplugin/DebugifyDebugFlags.java
================================================
package dev.isxander.debugify.mixinplugin;
public class DebugifyDebugFlags {
public static final boolean FORCE_LINUX_FIXES = boolProp("debugify.forceLinuxFixes");
public static final boolean FORCE_WINDOWS_FIXES = boolProp("debugify.forceWindowsFixes");
public static final boolean FORCE_MACOS_FIXES = boolProp("debugify.forceMacFixes");
private static boolean boolProp(String property) {
return Boolean.parseBoolean(System.getProperty(property));
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixinplugin/MixinPlugin.java
================================================
package dev.isxander.debugify.mixinplugin;
import dev.isxander.debugify.Debugify;
import dev.isxander.debugify.api.DebugifyApi;
import dev.isxander.debugify.error.DebugifyErrorHandler;
import dev.isxander.debugify.fixes.BugFixData;
import net.fabricmc.loader.api.FabricLoader;
import org.objectweb.asm.tree.ClassNode;
import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
import java.util.*;
public class MixinPlugin implements IMixinConfigPlugin {
@Override
public void onLoad(String mixinPackage) {
Debugify.onPreInitialize();
var entrypoints = FabricLoader.getInstance().getEntrypointContainers("debugify", DebugifyApi.class);
entrypoints.forEach(container -> {
DebugifyApi api = container.getEntrypoint();
String containerModId = container.getProvider().getMetadata().getId();
for (String bugId : api.getDisabledFixes()) {
BugFixData.registerApiConflict(containerModId, bugId);
}
api.getProvidedDisabledFixes().forEach((modId, bugs) -> {
if (FabricLoader.getInstance().isModLoaded(modId)) {
bugs.forEach(bugId -> BugFixData.registerApiConflict(modId, bugId));
}
});
});
}
@Override
public String getRefMapperConfig() {
return null;
}
@Override
public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
Optional bugFixOptional = BugFixDataCache.getOrResolve(mixinClassName);
if (bugFixOptional.isEmpty())
return true;
BugFixData bugFix = bugFixOptional.get();
var multipleMixins = Debugify.CONFIG.getBugFixes().containsKey(bugFix);
Debugify.CONFIG.registerBugFix(bugFix);
if (DebugifyErrorHandler.hasErrored(bugFix)) {
Debugify.LOGGER.warn("Preventing loading of {} mixin, {} because another mixin for the same bug fix failed to apply.", bugFix.bugId(), mixinClassName);
return false;
}
Set conflicts = bugFix.getActiveConflicts();
if (!conflicts.isEmpty()) {
if (Debugify.CONFIG.isBugFixEnabled(bugFix) && !multipleMixins)
Debugify.LOGGER.warn("Force disabled {} because it's conflicting with: {}", bugFix.bugId(), String.join(", ", conflicts));
return false;
} else if (!bugFix.satisfiesOSRequirement()) {
if (Debugify.CONFIG.isBugFixEnabled(bugFix) && !multipleMixins)
Debugify.LOGGER.warn("Force disabled {} because it only applies to OS: {}", bugFix.bugId(), bugFix.requiredOs().name());
return false;
}
return Debugify.CONFIG.isBugFixEnabled(bugFix);
}
@Override
public void acceptTargets(Set myTargets, Set otherTargets) {}
@Override
public List 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) {}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc100991/FishingHookMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc100991;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.level.Level;
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;
@BugFix(id = "MC-100991", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Killing entities with a fishing rod doesn't count as a kill")
@Mixin(FishingHook.class)
public abstract class FishingHookMixin extends Projectile {
public FishingHookMixin(EntityType extends Projectile> type, Level level) {
super(type, level);
}
/**
* notifies the combat tracker
*/
@Inject(
method = "pullEntity",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Entity;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V"
)
)
private void onPullEntity(Entity entity, CallbackInfo ci) {
if (entity instanceof LivingEntity livingEntity) {
livingEntity.getCombatTracker().recordDamage(
level().damageSources().thrown((FishingHook)(Object) this, getOwner()),
livingEntity.getHealth()
);
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc119754/FireworkRocketEntityMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc119754;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-119754", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Firework boosting on elytra continues in spectator mode")
@Mixin(FireworkRocketEntity.class)
public class FireworkRocketEntityMixin {
@Shadow @Nullable
private LivingEntity attachedToEntity;
@ModifyExpressionValue(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/LivingEntity;isFallFlying()Z"
)
)
private boolean shouldFly(boolean elytraFlying) {
return elytraFlying && !attachedToEntity.isSpectator();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc121706/RangedBowAttackGoalMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc121706;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.ai.goal.RangedBowAttackGoal;
import net.minecraft.world.entity.monster.Monster;
import org.spongepowered.asm.mixin.Final;
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;
@BugFix(id = "MC-121706", env = BugFix.Env.SERVER, category = FixCategory.BASIC, description = "Skeletons and illusioners aren't looking up / down at their target while strafing")
@Mixin(RangedBowAttackGoal.class)
public abstract class RangedBowAttackGoalMixin {
@Shadow @Final private T mob;
@Inject(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/monster/Monster;lookAt(Lnet/minecraft/world/entity/Entity;FF)V",
shift = At.Shift.AFTER
)
)
private void lookAtTarget(CallbackInfo ci) {
mob.getLookControl().setLookAt(mob.getTarget(), 30f, 30f);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc121903/MinecraftCommandBlockMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc121903;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.vehicle.minecart.MinecartCommandBlock;
import net.minecraft.world.level.storage.ValueInput;
import net.minecraft.world.level.storage.ValueOutput;
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;
@BugFix(id = "MC-121903", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Command block minecarts do not save execution cooldown to NBT")
@Mixin(MinecartCommandBlock.class)
public class MinecraftCommandBlockMixin {
@Shadow private int lastActivated;
@Inject(method = "readAdditionalSaveData", at = @At("RETURN"))
private void readNbt(ValueInput input, CallbackInfo ci) {
input.getInt("LastExecuted").ifPresent(lastExecuted -> {
lastActivated = lastExecuted;
});
}
@Inject(method = "addAdditionalSaveData", at = @At("RETURN"))
private void writeNbt(ValueOutput output, CallbackInfo ci) {
output.putInt("LastExecuted", lastActivated);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc123450/ItemFrameMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc123450;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.decoration.ItemFrame;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-123450", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Item frames play sounds when the item within them is read from NBT")
@Mixin(ItemFrame.class)
public class ItemFrameMixin {
@WrapWithCondition(
method = "setItem(Lnet/minecraft/world/item/ItemStack;Z)V",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/decoration/ItemFrame;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V"
)
)
private boolean playSound(ItemFrame instance, SoundEvent soundEvent, float volume, float pitch, @Local(argsOnly = true, name = "updateNeighbours") boolean updateNeighbours) {
// the targeted method is only given `updateNeighbours = false` when reading from NBT.
// technically, this means mods who want neighbourless updates will no longer play a sound.
// ideally, this would be an additional boolean in the method, but we don't have that privilige.
return updateNeighbours;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc129909/ServerPlayerMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc129909;
import com.mojang.authlib.GameProfile;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.GameType;
import net.minecraft.world.level.Level;
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;
@BugFix(id = "MC-129909", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Players in spectator mode continue to consume foods and liquids shortly after switching game modes")
@Mixin(ServerPlayer.class)
public abstract class ServerPlayerMixin extends Player {
public ServerPlayerMixin(Level world, GameProfile gameProfile) {
super(world, gameProfile);
}
/**
* Also fixes
* MC-81773, MC-206705
*/
@Inject(
method = "setGameMode",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerPlayer;stopRiding()V"
)
)
private void onChangeToSpectator(GameType mode, CallbackInfoReturnable cir) {
releaseUsingItem();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc131562/ServerGamePacketListenerImplMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc131562;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.network.chat.Component;
import net.minecraft.network.protocol.game.ServerboundSetCommandMinecartPacket;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerGamePacketListenerImpl;
import net.minecraft.util.StringUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-131562", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Pressing the \"Done\" button in empty command block minecarts prints the message \"Command set: \" in chat")
@Mixin(ServerGamePacketListenerImpl.class)
public class ServerGamePacketListenerImplMixin {
/**
* Add a condition to only send the success message if the command is not empty.
* This is parity with the command block behaviour.
*/
@Definition(id = "sendSystemMessage", method = "Lnet/minecraft/server/level/ServerPlayer;sendSystemMessage(Lnet/minecraft/network/chat/Component;)V")
@Expression("?.?.sendSystemMessage(?(?, ?))")
@WrapWithCondition(method = "handleSetCommandMinecart", at = @At("MIXINEXTRAS:EXPRESSION"))
private boolean checkEmptyCommandBeforeMessage(ServerPlayer instance, Component message, @Local(argsOnly = true, name = "packet") ServerboundSetCommandMinecartPacket packet) {
return !StringUtil.isNullOrEmpty(packet.getCommand());
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc132878/ArmorStandMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc132878;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.decoration.ArmorStand;
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;
@BugFix(id = "MC-132878", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Armor stands destroyed by explosions/lava/fire don't produce particles")
@Mixin(ArmorStand.class)
public abstract class ArmorStandMixin {
@Shadow protected abstract void showBreakingParticles();
@Inject(
method = "hurtServer",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByAnything(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V",
ordinal = 0
)
)
private void breakParticlesExplosion(CallbackInfoReturnable cir) {
this.showBreakingParticles();
}
@Inject(
method = "causeDamage",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/decoration/ArmorStand;brokenByAnything(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;)V",
ordinal = 0
)
)
private void breakParticlesFire(CallbackInfo ci) {
this.showBreakingParticles();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc133218/ServerPlayerMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc133218;
import com.mojang.authlib.GameProfile;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
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;
@BugFix(id = "MC-133218", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Usable items continue to be used on the death screen after dying when the keepInventory gamerule is set to enabled")
@Mixin(ServerPlayer.class)
public abstract class ServerPlayerMixin extends Player {
public ServerPlayerMixin(Level level, GameProfile gameProfile) {
super(level, gameProfile);
}
@Inject(method = "die", at = @At("RETURN"))
private void stopUsingItemOnDeath(CallbackInfo ci) {
this.stopUsingItem();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc134110/ChestBlockMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc134110;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.level.block.ChestBlock;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import static net.minecraft.world.level.block.ChestBlock.TYPE;
@BugFix(id = "MC-134110", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Structure mirroring breaking apart double chests")
@Mixin(ChestBlock.class)
public class ChestBlockMixin {
@WrapMethod(method = "mirror")
private BlockState fixChestRotations(BlockState state, Mirror mirror, Operation original) {
BlockState result = original.call(state, mirror);
return mirror == Mirror.NONE ? result : result.setValue(TYPE, result.getValue(TYPE).getOpposite());
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc139041/FishingRodItemMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc139041;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.item.FishingRodItem;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@BugFix(id = "MC-139041", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "The sounds of fishing bobbers aren't controlled by the \"Players\" sound slider")
@Mixin(FishingRodItem.class)
public class FishingRodItemMixin {
@ModifyArg(
method = "use",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V"
)
)
private SoundSource modifyFishingBobberSounds(SoundSource soundSource) {
return SoundSource.PLAYERS;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc147659/CatSpawnerMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc147659;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.animal.feline.Cat;
import net.minecraft.world.entity.npc.CatSpawner;
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;
@BugFix(id = "MC-147659", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Some witch huts spawn the incorrect cat")
@Mixin(CatSpawner.class)
public class CatSpawnerMixin {
@WrapWithCondition(
method = "spawnCat",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/animal/feline/Cat;snapTo(Lnet/minecraft/core/BlockPos;FF)V"
)
)
private boolean removeOldCatSnap(Cat instance, BlockPos blockPos, float yaw, float pitch) {
return false;
}
@Inject(
method = "spawnCat",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/animal/feline/Cat;finalizeSpawn(Lnet/minecraft/world/level/ServerLevelAccessor;Lnet/minecraft/world/DifficultyInstance;Lnet/minecraft/world/entity/EntitySpawnReason;Lnet/minecraft/world/entity/SpawnGroupData;)Lnet/minecraft/world/entity/SpawnGroupData;"
)
)
private void addNewCatSnap(BlockPos spawnPos, ServerLevel level, boolean makePersistent, CallbackInfo ci, @Local(name = "cat") Cat cat) {
cat.snapTo(spawnPos, 0, 0);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc153010/FoxMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc153010;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.animal.fox.Fox;
import net.minecraft.world.level.gamerules.GameRules;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-153010", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "doMobLoot gamerule doesn't prevent foxes from dropping their items")
@Mixin(Fox.class)
public class FoxMixin {
// gate dropping death loot with gamerule check
@ModifyExpressionValue(
method = "dropAllDeathLoot",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/item/ItemStack;isEmpty()Z"
)
)
private boolean preventLootDropIfGameruleIsFalse(boolean isEmpty, ServerLevel level) {
return isEmpty || !level.getGameRules().get(GameRules.MOB_DROPS);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc155509/PufferfishMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc155509;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.animal.fish.Pufferfish;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-155509", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Dying puffed pufferfish can still sting players")
@Mixin(Pufferfish.class)
public class PufferfishMixin {
@ModifyExpressionValue(
method = "playerTouch",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/player/Player;hurtServer(Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z"
)
)
private boolean shouldStingPlayer(boolean damaged) {
return damaged && ((Pufferfish)(Object) this).isAlive();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc158900/PlayerListMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc158900;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.players.NameAndId;
import net.minecraft.server.players.PlayerList;
import net.minecraft.server.players.UserBanList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-158900", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "\"bad packet id 26\" disconnect after first-login after a temporary ban expires")
@Mixin(PlayerList.class)
public class PlayerListMixin {
@WrapOperation(
method = "canPlayerLogin",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/players/UserBanList;isBanned(Lnet/minecraft/server/players/NameAndId;)Z"
)
)
private boolean removeExpiredBeforeCheck(UserBanList instance, NameAndId user, Operation original) {
instance.get(user); // get will remove expired bans
return original.call(instance, user);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc159283/DensityFunctionsMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc159283;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.util.Mth;
import net.minecraft.world.level.levelgen.DensityFunctions;
import net.minecraft.world.level.levelgen.synth.SimplexNoise;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
/**
* Taken from Thorium
* https://github.com/PotassiumMC/thorium
* under LGPLv3 license
*
* @author NoahvdAa
*/
@BugFix(id = "MC-159283", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "The End terrain does not generate in multiple rings centered around the world center")
@Mixin(DensityFunctions.EndIslandDensityFunction.class)
public class DensityFunctionsMixin {
/**
* Explicitly cast `x` and `z` to long (from int) to prevent integer overflow when squaring.
* We use a WrapOperation instead of ModifyArg so we don't do the math twice (one bugged one fixed)
*/
@Definition(id = "sqrt", method = "Lnet/minecraft/util/Mth;sqrt(F)F")
@Definition(id = "sectionX", local = @Local(type = int.class, name = "sectionX", argsOnly = true))
@Definition(id = "sectionZ", local = @Local(type = int.class, name = "sectionZ", argsOnly = true))
@Expression("sqrt((float) (sectionX * sectionX + sectionZ * sectionZ))")
@WrapOperation(method = "getHeightValue", at = @At("MIXINEXTRAS:EXPRESSION"))
private static float castToLongs(float x, Operation original, SimplexNoise islandNoise, int sectionX, int sectionZ) {
return Mth.sqrt((long) sectionX * (long) sectionX + (long) sectionZ * (long) sectionZ);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc160095/CactusBlockMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc160095;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.world.level.LevelReader;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.CactusBlock;
import net.minecraft.world.level.block.piston.PistonMovingBlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-160095", category = FixCategory.BASIC, env = BugFix.Env.SERVER, modConflicts = "carpet-fixes", description = "Partial blocks break cactus when moved by pistons")
@Mixin(CactusBlock.class)
public class CactusBlockMixin {
@Definition(id = "getBlockState", method = "Lnet/minecraft/world/level/LevelReader;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")
@Definition(id = "pos", local = @Local(type = BlockPos.class, name = "pos", argsOnly = true))
@Definition(id = "relative", method = "Lnet/minecraft/core/BlockPos;relative(Lnet/minecraft/core/Direction;)Lnet/minecraft/core/BlockPos;")
@Definition(id = "direction", local = @Local(type = Direction.class, name = "direction"))
@Expression("?.getBlockState(pos.relative(direction))")
@WrapOperation(method = "canSurvive", at = @At("MIXINEXTRAS:EXPRESSION"))
private BlockState replaceBlockState(LevelReader instance, BlockPos blockPos, Operation original) {
BlockState state = original.call(instance, blockPos);
// If it is a moving piston we check the block its moving not the moving piston block itself.
if (state.is(Blocks.MOVING_PISTON) && instance.getBlockEntity(blockPos) instanceof PistonMovingBlockEntity pistonBlock) {
return pistonBlock.getMovedState();
}
return state;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc168573/BlocksAttacksMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc168573;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.EquipmentSlot;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.BlocksAttacks;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-168573", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "After breaking a shield, the player's off-hand can't finish using some items")
@Mixin(BlocksAttacks.class)
public class BlocksAttacksMixin {
/**
* We need to check if the shield is going to break and only stop using the item after it is broken.
* We can't use isBroken here, so instead we check if the next damage will break the blockable, then do the damage call after.
*/
@WrapOperation(
method = "hurtBlockingItem",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/item/ItemStack;hurtAndBreak(ILnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/EquipmentSlot;)V"
)
)
private void fixShieldBreakItemUse(
ItemStack instance,
int amount,
LivingEntity owner,
EquipmentSlot slot,
Operation original,
@Local(argsOnly = true, name = "item") ItemStack item
) {
boolean isBroken = item.nextDamageWillBreak();
original.call(instance, amount, owner, slot);
if (isBroken) {
owner.stopUsingItem();
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc170462/MobEffectsMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc170462;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.effect.MobEffects;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@BugFix(id = "MC-170462", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Bad Omen is considered a positive effect in potion item tooltips")
@Mixin(MobEffects.class)
public class MobEffectsMixin {
@ModifyArg(
method = "",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/effect/BadOmenMobEffect;(Lnet/minecraft/world/effect/MobEffectCategory;I)V"
)
)
private static MobEffectCategory badOmenEffectCategory(MobEffectCategory arg) {
return MobEffectCategory.HARMFUL;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc176806/RespawnAnchorBlockMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc176806;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.block.RespawnAnchorBlock;
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;
@BugFix(id = "MC-176806", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Scoreboard criteria for using glowstone doesn't increase score when charging a respawn anchor")
@Mixin(RespawnAnchorBlock.class)
public class RespawnAnchorBlockMixin {
@Inject(
method = "useItemOn",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/item/ItemStack;consume(ILnet/minecraft/world/entity/LivingEntity;)V"
)
)
private void awardGlowstoneStat(
CallbackInfoReturnable cir,
@Local(argsOnly = true, name = "itemStack") ItemStack itemStack,
@Local(argsOnly = true, name = "player") Player player
) {
player.awardStat(Stats.ITEM_USED.get(itemStack.getItem()));
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc177381/LocateCommandMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc177381;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.commands.LocateCommand;
import org.spongepowered.asm.mixin.Mixin;
@BugFix(id = "MC-177381", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Game does not count the distance properly if you locate a structure from more than 46340 blocks away")
@Mixin(LocateCommand.class)
public class LocateCommandMixin {
@WrapMethod(method = "dist")
private static float distanceHypot(int x1, int z1, int x2, int z2, Operation original) {
return (float) Math.hypot(x2 - x1, z2 - z1);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc179072/SwellGoalMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc179072;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.ai.goal.SwellGoal;
import org.jetbrains.annotations.Nullable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-179072", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Creepers do not defuse when switching from Survival to Creative/Spectator")
@Mixin(SwellGoal.class)
public class SwellGoalMixin {
@Shadow private @Nullable LivingEntity target;
@ModifyExpressionValue(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/ai/sensing/Sensing;hasLineOfSight(Lnet/minecraft/world/entity/Entity;)Z"
)
)
private boolean shouldIgniteCreeper(boolean canSeeTarget) {
return canSeeTarget && (target == null || target.canBeSeenAsEnemy());
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc183990/MobMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc183990;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.Mob;
import org.jetbrains.annotations.Nullable;
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;
@BugFix(id = "MC-183990", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Group AI of some mobs breaks when their target dies")
@Mixin(Mob.class)
public abstract class MobMixin {
@Shadow private @Nullable LivingEntity target;
@Shadow public abstract void setTarget(@Nullable LivingEntity target);
@Inject(
method = "baseTick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/util/profiling/ProfilerFiller;pop()V"
)
)
private void clearTargetIfDead(CallbackInfo ci) {
if (target != null && target.isDeadOrDying()) {
setTarget(null);
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc187100/EnderDragonMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc187100;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.boss.enderdragon.EndCrystal;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import org.jetbrains.annotations.Nullable;
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;
@BugFix(id = "MC-187100", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "End crystals try to heal dying Ender dragons")
@Mixin(EnderDragon.class)
public class EnderDragonMixin {
@Shadow
public int dragonDeathTime;
@Shadow
@Nullable
public EndCrystal nearestCrystal;
@WrapMethod(method = "checkCrystals")
private void dontFindNearestCrystalIfDying(Operation original) {
if (this.dragonDeathTime > 0) {
this.nearestCrystal = null;
} else {
original.call();
}
}
@Inject(method = "tickDeath", at = @At("HEAD"))
private void clearNearestCrystalOnDeath(CallbackInfo ci) {
this.nearestCrystal = null;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc200418/ZombieVillagerMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc200418;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.animal.chicken.Chicken;
import net.minecraft.world.entity.monster.zombie.ZombieVillager;
import net.minecraft.world.entity.npc.villager.Villager;
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;
@BugFix(id = "MC-200418", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Cured baby zombie villagers stay as jockey variant")
@Mixin(ZombieVillager.class)
public class ZombieVillagerMixin {
@Inject(method = "lambda$finishConversion$0", at = @At("RETURN"))
private void dismountIfJockey(ServerLevel level, Villager villager, CallbackInfo ci) {
if (villager.isPassenger() && villager.getVehicle() instanceof Chicken && villager.isBaby()) {
villager.removeVehicle();
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc201374/CampfireBlockMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc201374;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.CampfireBlock;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@BugFix(id = "MC-201374", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Wrong position passed to getCollisionShape from CampfireBlock#isSmokingBlockAt")
@Mixin(CampfireBlock.class)
public class CampfireBlockMixin {
@ModifyArg(
method = "isSmokeyPos",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;getCollisionShape(Lnet/minecraft/world/level/BlockGetter;Lnet/minecraft/core/BlockPos;Lnet/minecraft/world/phys/shapes/CollisionContext;)Lnet/minecraft/world/phys/shapes/VoxelShape;"
)
)
private static BlockPos fixedBlockPos(BlockPos pos, @Local(name = "posToCheck") BlockPos posToCheck) {
return posToCheck;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc202637/FoodPropertiesMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc202637;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.food.FoodProperties;
import net.minecraft.world.item.component.Consumable;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@BugFix(id = "MC-202637", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Last sound clip of eating will still play when Players volume is set to 0%")
@Mixin(FoodProperties.class)
public class FoodPropertiesMixin {
@Definition(id = "playSound", method = "Lnet/minecraft/world/level/Level;playSound(Lnet/minecraft/world/entity/Entity;DDDLnet/minecraft/sounds/SoundEvent;Lnet/minecraft/sounds/SoundSource;FF)V")
@Definition(id = "consumable", local = @Local(type = Consumable.class, name = "consumable", argsOnly = true))
@Definition(id = "sound", method = "Lnet/minecraft/world/item/component/Consumable;sound()Lnet/minecraft/core/Holder;")
@Expression("?.playSound(?, ?, ?, ?, (?) consumable.sound().?(), ?, ?, ?)")
@ModifyArg(method = "onConsume", at = @At("MIXINEXTRAS:EXPRESSION"))
private SoundSource modifyEatSoundSource(SoundSource soundSource) {
return SoundSource.PLAYERS;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc206922/EntityMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc206922;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LightningBolt;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@BugFix(id = "MC-206922", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Items dropped by entities that are killed by lightning instantly disappear")
@Mixin(Entity.class)
public class EntityMixin {
@Shadow public int tickCount;
@WrapMethod(method = "thunderHit")
protected void bypassStruckByLightning(ServerLevel level, LightningBolt lightningBolt, Operation operation) {
operation.call(level, lightningBolt);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc206922/ItemEntityMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc206922;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.LightningBolt;
import net.minecraft.world.entity.item.ItemEntity;
import org.spongepowered.asm.mixin.Mixin;
@BugFix(id = "MC-206922", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Items dropped by entities that are killed by lightning instantly disappear")
@Mixin(ItemEntity.class)
public abstract class ItemEntityMixin extends EntityMixin {
@Override
protected void bypassStruckByLightning(ServerLevel world, LightningBolt lightning, Operation operation) {
if (tickCount > 8) {
super.bypassStruckByLightning(world, lightning, operation);
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc215530/ServerPlayerMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc215530;
import com.mojang.authlib.GameProfile;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Level;
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;
@BugFix(id = "MC-215530", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "The freezing effect isn't immediately removed upon switching into spectator mode")
@Mixin(ServerPlayer.class)
public abstract class ServerPlayerMixin extends Player {
public ServerPlayerMixin(Level world, GameProfile gameProfile) {
super(world, gameProfile);
}
@Inject(
method = "setGameMode",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerPlayer;stopRiding()V"
)
)
private void onChangeToSpectator(CallbackInfoReturnable cir) {
setTicksFrozen(0);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc221257/ShulkerBulletMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc221257;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.projectile.Projectile;
import net.minecraft.world.entity.projectile.ShulkerBullet;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.Vec3;
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;
@BugFix(id = "MC-221257", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Shulker bullets don't produce bubble particles when moving through water")
@Mixin(ShulkerBullet.class)
public abstract class ShulkerBulletMixin extends Projectile {
public ShulkerBulletMixin(EntityType extends Projectile> entityType, Level level) {
super(entityType, level);
}
/**
* Code taken from {@link net.minecraft.world.entity.projectile.arrow.AbstractArrow}
*/
@Inject(method = "tick", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/projectile/ShulkerBullet;setPos(Lnet/minecraft/world/phys/Vec3;)V"))
private void addMissingBubbleParticles(CallbackInfo ci) {
if (this.isInWater()) {
Vec3 vec3 = this.position();
Vec3 vec32 = this.getDeltaMovement();
for (int i = 0; i < 4; ++i) {
this.level().addParticle(ParticleTypes.BUBBLE, vec3.x - vec32.x * (double) 0.25F, vec3.y - vec32.y * (double) 0.25F, vec3.z - vec32.z * (double) 0.25F, vec32.x, vec32.y, vec32.z);
}
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc223153/BlocksMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc223153;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.block.state.BlockBehaviour;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@BugFix(id = "MC-223153", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Block of Raw Copper uses stone sounds instead of copper sounds")
@Mixin(Blocks.class)
public class BlocksMixin {
@Definition(id = "register", method = "Lnet/minecraft/world/level/block/Blocks;register(Ljava/lang/String;Lnet/minecraft/world/level/block/state/BlockBehaviour$Properties;)Lnet/minecraft/world/level/block/Block;")
@Expression("register('raw_copper_block', ?)")
@ModifyArg(method = "", at = @At("MIXINEXTRAS:EXPRESSION"))
private static BlockBehaviour.Properties addCopperSound(BlockBehaviour.Properties settings) {
return settings.sound(SoundType.COPPER);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc224729/ChunkMapMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc224729;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ChunkHolder;
import net.minecraft.server.level.ChunkMap;
import net.minecraft.world.level.chunk.ChunkAccess;
import net.minecraft.world.level.chunk.ProtoChunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
import java.util.function.Predicate;
@BugFix(id = "MC-224729", category = FixCategory.BASIC, env = BugFix.Env.SERVER, modConflicts = {"chunksavingfix", "moonrise"}, description = "Partially generated chunks are not saved in some situations")
@Mixin(ChunkMap.class)
public class ChunkMapMixin {
@Definition(id = "filter", method = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;")
@Definition(id = "wasAccessibleSinceLastSave", method = "Lnet/minecraft/server/level/ChunkHolder;wasAccessibleSinceLastSave()Z")
@Expression("?.filter(::wasAccessibleSinceLastSave)")
@ModifyArg(method = "saveAllChunks", at = @At("MIXINEXTRAS:EXPRESSION"))
private Predicate alwaysAccessibleFlushSave(Predicate predicate) {
return (chunkHolder) -> true;
}
@ModifyArg(method = "saveAllChunks", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;filter(Ljava/util/function/Predicate;)Ljava/util/stream/Stream;", ordinal = 1))
private Predicate saveProtoChunks(Predicate predicate) {
return (c) -> predicate.test(c) || c instanceof ProtoChunk;
}
@ModifyExpressionValue(method = "saveChunkIfNeeded", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/level/ChunkHolder;wasAccessibleSinceLastSave()Z"))
private boolean alwaysAccessibleChunkSave(boolean accessible) {
return true;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc226961/ExperienceOrbMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc226961;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.ExperienceOrb;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-226961", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Experience Orbs treat flowing lava as a full block")
@Mixin(ExperienceOrb.class)
public abstract class ExperienceOrbMixin extends Entity {
public ExperienceOrbMixin(EntityType> entityType, Level level) {
super(entityType, level);
}
@Definition(id = "getFluidState", method = "Lnet/minecraft/world/level/Level;getFluidState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/material/FluidState;")
@Definition(id = "is", method = "Lnet/minecraft/world/level/material/FluidState;is(Lnet/minecraft/tags/TagKey;)Z")
@Definition(id = "LAVA", field = "Lnet/minecraft/tags/FluidTags;LAVA:Lnet/minecraft/tags/TagKey;")
@Expression("?.getFluidState(?).is(LAVA)")
@ModifyExpressionValue(method = "tick", at = @At("MIXINEXTRAS:EXPRESSION"))
private boolean checkEyeLevel(boolean original) {
return this.isEyeInFluid(FluidTags.LAVA);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc227008/EnderManMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc227008;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.monster.EnderMan;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-227008", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Enderman constantly tries to teleport when in a boat or a minecart under daylight")
@Mixin(EnderMan.class)
public class EnderManMixin {
// Target getLightLevelDependentMagicValue so we get an EnderMan instance without needing to cast `this`. As long as this returns <= 0.5F the enderman won't teleport
@WrapOperation(
method = "customServerAiStep",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/monster/EnderMan;getLightLevelDependentMagicValue()F"
)
)
private float checkRiding(EnderMan instance, Operation original) {
return instance.isPassenger() ? 0F : original.call(instance);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc227337/ShulkerBulletMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc227337;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.world.entity.projectile.ShulkerBullet;
import net.minecraft.world.phys.EntityHitResult;
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;
@BugFix(id = "MC-227337", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "When a shulker bullet hits an entity, the explodes sound is not played and particles are not produced")
@Mixin(ShulkerBullet.class)
public class ShulkerBulletMixin {
@Inject(
method = "onHitEntity",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/phys/EntityHitResult;getEntity()Lnet/minecraft/world/entity/Entity;"
)
)
private void playSoundAndDisplayParticles(EntityHitResult hitResult, CallbackInfo ci) {
ShulkerBullet instance = (ShulkerBullet) (Object) this;
((ServerLevel) instance.level()).sendParticles(ParticleTypes.EXPLOSION, instance.getX(), instance.getY(), instance.getZ(), 2, 0.2D, 0.2D, 0.2D, 0.0D);
instance.playSound(SoundEvents.SHULKER_BULLET_HIT, 1.0F, 1.0F);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc231743/FlowerPotBlockMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc231743;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResult;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.FlowerPotBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.BlockHitResult;
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;
@BugFix(id = "MC-231743", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "\"minecraft.used:minecraft.\" doesn't increase when placing plants into flower pots")
@Mixin(FlowerPotBlock.class)
public class FlowerPotBlockMixin {
@Inject(
method = "useItemOn",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/player/Player;awardStat(Lnet/minecraft/resources/Identifier;)V"
)
)
private void onIncrementPottedPlantStat(
CallbackInfoReturnable cir,
@Local(argsOnly = true, name = "player") Player player,
@Local(argsOnly = true, name = "hand") InteractionHand hand
) {
player.awardStat(Stats.ITEM_USED.get(player.getItemInHand(hand).getItem()));
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc232869/StriderMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc232869;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.Difficulty;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.monster.Strider;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-232869", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Adult striders can spawn with saddles in peaceful mode")
@Mixin(Strider.class)
public abstract class StriderMixin extends Animal {
protected StriderMixin(EntityType extends Animal> entityType, Level world) {
super(entityType, world);
}
@Definition(id = "nextInt", method = "Lnet/minecraft/util/RandomSource;nextInt(I)I")
@Expression("?.nextInt(30) == 0")
@ModifyExpressionValue(method = "finalizeSpawn", at = @At("MIXINEXTRAS:EXPRESSION"))
private boolean preventPeacefulJocky(boolean original) {
return original && level().getDifficulty() != Difficulty.PEACEFUL;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc245394/RaidMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc245394;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.sounds.SoundSource;
import net.minecraft.world.entity.raid.Raid;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@BugFix(id = "MC-245394", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "The sounds of raid horns blaring aren't controlled by the correct sound slider")
@Mixin(Raid.class)
public class RaidMixin {
@ModifyArg(
method = "playSound",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/network/protocol/game/ClientboundSoundPacket;(Lnet/minecraft/core/Holder;Lnet/minecraft/sounds/SoundSource;DDDFFJ)V"
)
)
private SoundSource modifyRaidSoundSource(SoundSource soundSource) {
return SoundSource.HOSTILE;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc263999/BreakDoorGoalMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc263999;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import com.llamalad7.mixinextras.sugar.Share;
import com.llamalad7.mixinextras.sugar.ref.LocalRef;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.ai.goal.BreakDoorGoal;
import net.minecraft.world.entity.ai.goal.DoorInteractGoal;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.state.BlockState;
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;
/**
* removeBlock is called before querying the block state of the door,
* which breaks the level event that causes particles
*/
@BugFix(id = "MC-263999", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Zombies breaking doors do not show break particles")
@Mixin(BreakDoorGoal.class)
public class BreakDoorGoalMixin extends DoorInteractGoal {
public BreakDoorGoalMixin(Mob mob) {
super(mob);
}
// Store the block state before removal
@Inject(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/Level;removeBlock(Lnet/minecraft/core/BlockPos;Z)Z"
)
)
private void storeBlockStatePreRemoval(
CallbackInfo ci,
@Share("blockState") LocalRef blockStateRef
) {
blockStateRef.set(this.mob.level().getBlockState(this.doorPos));
}
// Use the stored block state for the level event
@Definition(id = "levelEvent", method = "Lnet/minecraft/world/level/Level;levelEvent(ILnet/minecraft/core/BlockPos;I)V")
@Definition(id = "getId", method = "Lnet/minecraft/world/level/block/Block;getId(Lnet/minecraft/world/level/block/state/BlockState;)I")
@Definition(id = "getBlockState", method = "Lnet/minecraft/world/level/Level;getBlockState(Lnet/minecraft/core/BlockPos;)Lnet/minecraft/world/level/block/state/BlockState;")
@Definition(id = "doorPos", field = "Lnet/minecraft/world/entity/ai/goal/BreakDoorGoal;doorPos:Lnet/minecraft/core/BlockPos;")
@Expression("?.levelEvent(2001, ?, getId(@(?.getBlockState(?.doorPos))))")
@WrapOperation(method = "tick", at = @At("MIXINEXTRAS:EXPRESSION"))
private BlockState injectCorrectBlockState(
Level instance, BlockPos pos, Operation original,
@Share("blockState") LocalRef blockStateRef
) {
return blockStateRef.get();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc264285/CreeperMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc264285;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.component.DataComponents;
import net.minecraft.world.entity.monster.Creeper;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-264285", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Unbreakable flint and steels are completely consumed when igniting a creeper")
@Mixin(Creeper.class)
public class CreeperMixin {
/**
* Igniting a creeper shrinks the stack size by 1 if the item is not damageable.
* The intention of this was for consumable items which have no durability (has no max damage tag).
* However, items with the unbreakable tag makes them not damageable, so they get consumed incorrectly.
*
* The injection point is within a `!` gate, so the return value is true if the stack is not to be shrunk.
*/
@WrapOperation(
method = "mobInteract",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/item/ItemStack;isDamageableItem()Z"
)
)
private boolean shouldNotShrinkStack(ItemStack instance, Operation original) {
return instance.has(DataComponents.MAX_DAMAGE);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc264979/SettingsMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc264979;
import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.dedicated.Settings;
import org.spongepowered.asm.mixin.Mixin;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Properties;
@BugFix(id = "MC-264979", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Fresh installations print NoSuchFileException when attempting to load server.properties")
@Mixin(Settings.class)
public class SettingsMixin {
@WrapMethod(method = "loadFromFile")
private static Properties dontLoadMissingFile(Path file, Operation original) {
if (Files.notExists(file)) {
return new Properties();
}
return original.call(file);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc267125/PlayerListMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc267125;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.players.PlayerList;
import org.spongepowered.asm.mixin.Final;
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 java.util.List;
@BugFix(id = "MC-267125", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Command suggestions for reloadable content are not affected by /reload")
@Mixin(PlayerList.class)
public abstract class PlayerListMixin {
@Shadow
@Final
private List players;
@Shadow
public abstract void sendPlayerPermissionLevel(ServerPlayer player);
@Inject(method = "reloadResources", at = @At("RETURN"))
private void sendCommandSuggestions(CallbackInfo ci) {
for (ServerPlayer player : this.players) {
this.sendPlayerPermissionLevel(player);
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc268617/FileUtilMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc268617;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.util.FileUtil;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.ModifyArg;
@BugFix(id = "MC-268617", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Structures can't be saved if the game directory is named in a certain way")
@Mixin(FileUtil.class)
public class FileUtilMixin {
/**
* Updates the valid path RegEx to include more valid file paths. This new filter will properly match all reserved file names, including many undocumented by Microsoft.
* This fixes structure blocks for normal installations on old Modrinth instances or certain Linux scenarios such as Flatpak installations.
* Can be tested on Windows by naming an instance "com.example".
*/
@Definition(id = "RESERVED_WINDOWS_FILENAMES", field = "Lnet/minecraft/util/FileUtil;RESERVED_WINDOWS_FILENAMES:Ljava/util/regex/Pattern;")
@Definition(id = "compile", method = "Ljava/util/regex/Pattern;compile(Ljava/lang/String;I)Ljava/util/regex/Pattern;")
@Expression("RESERVED_WINDOWS_FILENAMES = @(compile(?, ?))")
@ModifyArg(method = "", at = @At("MIXINEXTRAS:EXPRESSION"))
private static String fixWindowsReservedFilename(String regex) {
return ".*\\.|(?:CON|PRN|AUX|NUL|CLOCK\\$|CONIN\\$|CONOUT\\$|(?:COM|LPT)[¹²³0-9])(?:\\..*)?";
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc271899/StructureTemplateMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc271899;
import com.google.common.collect.Maps;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.levelgen.structure.templatesystem.StructureTemplate;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import java.util.List;
import java.util.Map;
@BugFix(id = "MC-271899", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "StructureTemplate Palette's caches are not thread safe")
@Mixin(StructureTemplate.Palette.class)
public class StructureTemplateMixin {
@Mutable
@Shadow
@Final
private Map> cache = Maps.newConcurrentMap();
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc272431/EnderDragonMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc272431;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-272431", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Ender Dragon incorrect vertical velocity causes erratic behavior")
@Mixin(EnderDragon.class)
public class EnderDragonMixin {
@Definition(id = "yRotA", field = "Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;yRotA:F")
@Expression("this.yRotA * @(0.01)")
@ModifyExpressionValue(method = "aiStep", at = @At("MIXINEXTRAS:EXPRESSION"))
private float fixTargetPath(float original) {
return 0.1f;
}
@Definition(id = "setDeltaMovement", method = "Lnet/minecraft/world/entity/boss/enderdragon/EnderDragon;setDeltaMovement(Lnet/minecraft/world/phys/Vec3;)V")
@Definition(id = "add", method = "Lnet/minecraft/world/phys/Vec3;add(DDD)Lnet/minecraft/world/phys/Vec3;")
@Definition(id = "ydd", local = @Local(type = double.class, name = "ydd"))
@Expression("this.setDeltaMovement(?.add(0.0, ydd * @(0.01), 0.0))")
@ModifyExpressionValue(method = "aiStep", at = @At("MIXINEXTRAS:EXPRESSION"))
private double fixVerticalVelocity(double value) {
return 0.1;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc297837/WaypointTransmitterMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc297837;
import com.llamalad7.mixinextras.injector.wrapoperation.Operation;
import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.waypoints.WaypointTransmitter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-297837", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Locator bar shows players above you as being below you when they are high enough")
@Mixin(WaypointTransmitter.class)
public interface WaypointTransmitterMixin {
/**
* {@link WaypointTransmitter#isReallyFar(LivingEntity, ServerPlayer)} was being used to determine whether
* waypoints should use azimuth distance (far away) or chunk/block distance (close/closer by).
*
* The azimuth distance provides only relative yRot, which means the pitch uses the horizon,
* not the waypoint itself.
*
* Even when the waypoint is in the same chunk as the entity, the azimuth distance was used because it was
* over 332 blocks away, just vertically, not horizontally, as I assume it was intended.
*
* This mixin fixes the bug by using the block distance instead of the azimuth distance,
* by changing the distance calculation to only use horizontal distance.
*/
@WrapOperation(
method = "isReallyFar",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/LivingEntity;distanceTo(Lnet/minecraft/world/entity/Entity;)F"
)
)
private static float useOnlyHorizontalDistance(LivingEntity entity1, Entity entity2, Operation original) {
double xDist = entity1.getX() - entity2.getX();
double zDist = entity1.getZ() - entity2.getZ();
return (float) Math.hypot(xDist, zDist);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc298066/LivingEntityMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc298066;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.Level;
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;
@BugFix(id = "MC-298066", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Directly entering a bed from a mount places the player in the wrong place")
@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin extends Entity {
public LivingEntityMixin(EntityType> entityType, Level level) {
super(entityType, level);
}
// This is just a hacky fix to force the player into the correct position
@Inject(method = "setPosToBed", at = @At("TAIL"))
private void teleportToBed(BlockPos bedPosition, CallbackInfo ci) {
this.teleportTo(bedPosition.getX() + 0.5, bedPosition.getY() + 0.6875, bedPosition.getZ() + 0.5);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc30391/LivingEntityMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc30391;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.animal.chicken.Chicken;
import net.minecraft.world.entity.boss.wither.WitherBoss;
import net.minecraft.world.entity.monster.Blaze;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-30391", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Chickens, blazes and the wither emit particles when landing from a height, despite falling slowly")
@Mixin(LivingEntity.class)
public class LivingEntityMixin {
@ModifyExpressionValue(
method = "checkFallDamage",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/level/block/state/BlockState;isAir()Z"
)
)
private boolean shouldntSpawnParticles(boolean isAir) {
LivingEntity self = (LivingEntity) (Object) this;
return isAir || self instanceof Chicken || self instanceof Blaze || self instanceof WitherBoss;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc44654/EntityMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc44654;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
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;
@BugFix(id = "MC-44654", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Some entities don't update position to the client when teleported")
@Mixin(Entity.class)
public abstract class EntityMixin {
@Shadow
public abstract EntityType> getType();
@Shadow
public boolean needsSync;
/**
* Since the update interval is set to infinity, the position will never get updated.
* To fix, we mark velocity as dirty via needsSync to force an update.
*
* We inject precisely here as the target is only called when `!firstTick && isServerLevel`,
* since this is where the issue occurs.
*/
@Inject(
method = "setPosRaw",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Entity;isRemoved()Z"
)
)
private void forceClientUpdate(CallbackInfo ci) {
if (this.getType().updateInterval() == Integer.MAX_VALUE) {
this.needsSync = true;
}
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc7569/RconConsoleSourceMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc7569;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.network.chat.Component;
import net.minecraft.server.rcon.RconConsoleSource;
import org.spongepowered.asm.mixin.Final;
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;
@BugFix(id = "MC-7569", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "RCON output has newlines removed")
@Mixin(RconConsoleSource.class)
public class RconConsoleSourceMixin {
@Shadow @Final private StringBuffer buffer;
@Inject(method = "sendSystemMessage", at = @At("RETURN"))
private void appendNewline(Component message, CallbackInfo ci) {
buffer.append(System.lineSeparator());
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc82263/EnderDragonMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc82263;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.boss.enderdragon.EnderDragon;
import net.minecraft.world.level.Level;
import org.spongepowered.asm.mixin.Mixin;
@BugFix(id = "MC-82263", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Ender dragon produces regular hurt sound on final hit")
@Mixin(EnderDragon.class)
public class EnderDragonMixin extends Mob {
protected EnderDragonMixin(EntityType extends Mob> entityType, Level level) {
super(entityType, level);
}
// The death sound plays regardless of what this is set to, it's not set in the target class and instead uses LivingEntity's GENERIC_DEATH
@Override
protected SoundEvent getDeathSound() {
return null;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc84661/MobEffectsMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc84661;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.effect.MobEffectCategory;
import net.minecraft.world.effect.MobEffects;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-84661", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Glowing is considered a positive effect in potion item tooltips")
@Mixin(MobEffects.class)
public class MobEffectsMixin {
@Definition(id = "NEUTRAL", field = "Lnet/minecraft/world/effect/MobEffectCategory;NEUTRAL:Lnet/minecraft/world/effect/MobEffectCategory;")
@Expression("new ?(@(NEUTRAL), 745784)") // this colour refers to bad omen effect exclusively
@ModifyExpressionValue(method = "", at = @At("MIXINEXTRAS:EXPRESSION"))
private static MobEffectCategory badOmenEffectCategory(MobEffectCategory arg) {
return MobEffectCategory.HARMFUL;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc88371/DragonLandingPhaseMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc88371;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.boss.enderdragon.phases.DragonLandingPhase;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-88371", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Ender Dragon flies down in the void when the exit portal is destroyed")
@Mixin(DragonLandingPhase.class)
public class DragonLandingPhaseMixin {
@ModifyExpressionValue(
method = "doServerTick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/level/ServerLevel;getHeightmapPos(Lnet/minecraft/world/level/levelgen/Heightmap$Types;Lnet/minecraft/core/BlockPos;)Lnet/minecraft/core/BlockPos;"
)
)
private BlockPos getLandingPos(BlockPos pos) {
if (pos.getY() == 0) {
// average height of portal
return pos.atY(65);
}
return pos;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc89146/ChunkAccessMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc89146;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.chunk.ChunkAccess;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import java.util.Map;
@BugFix(id = "MC-89146", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Pistons forget update when being reloaded")
@Mixin(ChunkAccess.class)
public class ChunkAccessMixin {
@Shadow @Final @Mutable
protected Map blockEntities = new Object2ObjectLinkedOpenHashMap<>();
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc93018/AnimalMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc93018;
import com.llamalad7.mixinextras.injector.v2.WrapWithCondition;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.animal.Animal;
import net.minecraft.world.entity.animal.wolf.Wolf;
import net.minecraft.world.entity.player.Player;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-93018", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Wild wolves show breeding hearts but do not breed")
@Mixin(Animal.class)
public class AnimalMixin {
/**
* Only make wolves love player if they are tamed when fed
*/
@WrapWithCondition(
method = "mobInteract",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/animal/Animal;setInLove(Lnet/minecraft/world/entity/player/Player;)V"
)
)
private boolean loveCondition(Animal animal, Player player) {
return !(animal instanceof Wolf wolf) || wolf.isTame();
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/basic/mc94054/WallClimberNavigationMixin.java
================================================
package dev.isxander.debugify.mixins.basic.mc94054;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.ai.navigation.WallClimberNavigation;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-94054", category = FixCategory.BASIC, env = BugFix.Env.SERVER, description = "Cave spiders spin around when walking")
@Mixin(WallClimberNavigation.class)
public class WallClimberNavigationMixin {
@ModifyExpressionValue(
method = "tick",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/world/entity/Mob;getBbWidth()F"
)
)
private float fixSpiderSpinning(float bbWidth) {
return Math.max(bbWidth, 1.0F);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/errorhandler/CrashReportMixin.java
================================================
package dev.isxander.debugify.mixins.errorhandler;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import dev.isxander.debugify.error.CrashReportInjector;
import net.minecraft.CrashReport;
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;
@Mixin(CrashReport.class)
public class CrashReportMixin {
@Definition(id = "systemReport", field = "Lnet/minecraft/CrashReport;systemReport:Lnet/minecraft/SystemReport;")
@Definition(id = "appendToCrashReportString", method = "Lnet/minecraft/SystemReport;appendToCrashReportString(Ljava/lang/StringBuilder;)V")
@Expression("this.systemReport.appendToCrashReportString(?)")
@Inject(method = "getDetails(Ljava/lang/StringBuilder;)V", at = @At("MIXINEXTRAS:EXPRESSION"))
private void appendCrashReport(StringBuilder sb, CallbackInfo ci) {
CrashReportInjector.addDetailsToCrashReport(sb);
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/gameplay/mc136249/LivingEntityMixin.java
================================================
package dev.isxander.debugify.mixins.gameplay.mc136249;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.world.entity.LivingEntity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@BugFix(id = "MC-136249", category = FixCategory.GAMEPLAY, env = BugFix.Env.SERVER, description = "Wearing boots enchanted with depth strider decreases the strength of the riptide enchantment")
@Mixin(LivingEntity.class)
public abstract class LivingEntityMixin{
@Shadow
public abstract boolean isAutoSpinAttack();
@Definition(id = "getAttributeValue", method = "Lnet/minecraft/world/entity/LivingEntity;getAttributeValue(Lnet/minecraft/core/Holder;)D")
@Definition(id = "WATER_MOVEMENT_EFFICIENCY", field = "Lnet/minecraft/world/entity/ai/attributes/Attributes;WATER_MOVEMENT_EFFICIENCY:Lnet/minecraft/core/Holder;")
@Expression("this.getAttributeValue(WATER_MOVEMENT_EFFICIENCY)")
@ModifyExpressionValue(method = "travelInWater", at = @At("MIXINEXTRAS:EXPRESSION"))
private double checkRiptide(double original) {
return this.isAutoSpinAttack() ? 0 : original;
}
}
================================================
FILE: src/main/java/dev/isxander/debugify/mixins/gameplay/mc8187/TreeFeatureMixin.java
================================================
/*
* Copyright (C) 2023, Ampflower
*
* This software is subject to the terms of the Zlib License.
* If a copy was not distributed with this file, you can obtain one at
* https://github.com/Modflower/8187/blob/trunk/LICENSE
*
* Source: https://github.com/Modflower/8187
* SPDX-License-Identifier: Zlib
*/
package dev.isxander.debugify.mixins.gameplay.mc8187;
import com.llamalad7.mixinextras.expression.Definition;
import com.llamalad7.mixinextras.expression.Expression;
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
import com.llamalad7.mixinextras.sugar.Local;
import dev.isxander.debugify.Debugify;
import dev.isxander.debugify.fixes.BugFix;
import dev.isxander.debugify.fixes.FixCategory;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.LevelSimulatedReader;
import net.minecraft.world.level.levelgen.feature.TreeFeature;
import net.minecraft.world.level.levelgen.feature.configurations.TreeConfiguration;
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.ModifyVariable;
import org.spongepowered.asm.mixin.injection.Slice;
/**
* Fixes the offsets for 2x2 saplings at starting height
* fixing MC-8187.
*
* This code is provided as-is minus differences in mappings by Ampflower.
*
* Original mod: {@literal flwr-8187}
* (GitHub).
*
* @author Ampflower
* @since 1.20.1+1.2
**/
@BugFix(id = "MC-8187", category = FixCategory.GAMEPLAY, env = BugFix.Env.SERVER, modConflicts = "flwr-8187", description = "Two-by-two arrangements of jungle or spruce saplings cannot grow when there are adjacent blocks located north or west of the sapling formation")
@Mixin(TreeFeature.class)
public class TreeFeatureMixin {
/**
* Corrects the starting value if the trunk's minimum size is {@literal 1}
* and the starting value is {@literal -1} by returning {@literal 0}.
*
* I should note there: This isn't an optimal bugfix as it is possible for poorly implemented 3x3 trees to erroneously check only a 2x2.
*/
// 2026 Xander: holy moly i just expressionified the hell out of this mixin you're so welcome
@Definition(id = "x", local = @Local(type = int.class, name = "x"))
@Definition(id = "z", local = @Local(type = int.class, name = "z"))
@Definition(id = "r", local = @Local(type = int.class, name = "r"))
@Expression({
"x = @(-r)",
"z = @(-r)"
})
@ModifyExpressionValue(method = "getMaxFreeTreeHeight", at = @At("MIXINEXTRAS:EXPRESSION"))
private int fixOffsetNew(
int start,
@Local(argsOnly = true, name = "maxTreeHeight") int maxTreeHeight,
@Local(argsOnly = true, name = "config") TreeConfiguration config
) {
// Roughly height == 0 && trunk == 1
if (Debugify.isGameplayFixesEnabled() && start == -1 && config.minimumSize.getSizeAtHeight(maxTreeHeight, 0) == 1) {
return 0;
}
return start;
}
}
================================================
FILE: src/main/resources/assets/debugify/lang/el_gr.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Βασικές Διορθώσεις",
"debugify.gameplay": "Διορθώσεις Gameplay",
"debugify.gameplay.warning": "ΠΡΟΣΟΧΗ: Αυτή η κατηγορία περιέχει διορθώσεις οι οποίες μπορεί να σου δίνουν άδικα πλεονέκτηματα!",
"debugify.gameplay.enable_in_multiplayer": "Ενεργοποίηση στο Παιχνίδι Πολλαπλών Παικτών",
"debugify.misc": "Διάφορα",
"debugify.misc.default_disabled": "Αυτόματη Απενεργοποίηση",
"debugify.misc.default_disabled.description": "Απενεργοποιεί τις νεές προσθήκες διορθώσεων.",
"debugify.env.client": "Πελάτη",
"debugify.env.server": "Διακομιστή"
}
================================================
FILE: src/main/resources/assets/debugify/lang/en_us.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Basic Fixes",
"debugify.gameplay": "Gameplay Fixes",
"debugify.gameplay.warning": "WARNING: This category contains fixes that may be an unfair advantage!",
"debugify.gameplay.enable_in_multiplayer": "Enable In Multiplayer",
"debugify.fix.enabled": "Fixed",
"debugify.fix.disabled": "Not fixed",
"debugify.fix.unavailable": "Unavailable",
"debugify.error.conflict": "%s fix is incompatible with the mod '%s'",
"debugify.error.os": "%s only applies to %s",
"debugify.error.mixin_error": "Failed to load %s, check the log for more information.",
"debugify.error.mixin_error.text": "Errored",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Misc",
"debugify.misc.default_disabled": "Default to Disabled",
"debugify.misc.default_disabled.description": "Default new bug fixes to be disabled rather than enabled.",
"debugify.env.client": "Client",
"debugify.env.client.desc": "Fixes that only apply on the client.",
"debugify.env.server": "Main",
"debugify.env.server.desc": "Fixes that apply to both the client and the server, and common code between them.",
"debugify.no_yacl.title": "YetAnotherConfigLib not installed!",
"debugify.no_yacl.description": "To configure Debugify using a GUI, you must install %s, this is the library used to make this functionality available. Otherwise, you can configure using the JSON file stored at '%s'.",
"debugify.mc_237493.header": "Telemetry Disabled By Debugify",
"debugify.mc_237493.line": "You chose '%s' on the telemetry option, so Debugify is preventing any connection with telemetry services from Mojang. This is provided by Debugify for fix MC-237493.",
"debugify.mc_237493.tooltip.off": "'%s' completely disables any connection to Mojang telemetry services. (Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "'%s' includes only the information Mojang deems required.",
"debugify.mc_237493.tooltip.all": "'%s' includes all of minimal and option telemetry.",
"debugify.fix_explanation.mc-46503": "Clears shader effects on respawn.",
"debugify.fix_explanation.mc-55347": "Clears titles on disconnect.",
"debugify.fix_explanation.mc-61489": "Disabled by default because some players or mods might prefer the original book GUI position.",
"debugify.fix_explanation.mc-79545": "Clamps the experience level to the integer limit only when rendering.",
"debugify.fix_explanation.mc-93384": "Adds the eye height to the particle spawn location.",
"debugify.fix_explanation.mc-105068": "Make shield break sound a local sound.",
"debugify.fix_explanation.mc-108948": "The issue is that the client does not run the same calculations as the server. When no one is controlling the boat, the client does not run physics on the boat, causing a client de-sync. This fix simply tells the client to run some physics calculations on the boat.",
"debugify.fix_explanation.mc-111516": "Modifies a math acos calculation to make sure the result is not more than 1.0.",
"debugify.fix_explanation.mc-118740": "Displays the crosshair attack cooldown when performing a right click action.",
"debugify.fix_effect.mc-118740": "This also fixes MC-116510: Attack indicator doesn't indicate (most of the time) that breaking instantly-mineable blocks resets your attack",
"debugify.fix_explanation.mc-112730": "Prevents beacons and other block entities from being added to the local block entity renderer list if they are already added to the global list.",
"debugify.fix_explanation.mc-122477": "Prevents first two keyboard polls after an edit box is initialized, e.g. the chat box.",
"debugify.fix_explanation.mc-123739": "Sorts recipe book entries by their identifier.",
"debugify.fix_explanation.mc-143474": "Copies over the selected item slot when generating the new local player after respawn.",
"debugify.fix_effect.mc-143474": "This also fixes MC-12062: Hotbar selection resets to the far left when exiting the end",
"debugify.fix_explanation.mc-159163": "Removes pose data from entity data packet handling.",
"debugify.fix_effect.mc-159163": "This will prevent the client from syncing pose data with the server, and purely uses the client to decide the pose.",
"debugify.fix_explanation.mc-162253": "Stops a client light update when entering a chunk.",
"debugify.fix_explanation.mc-165381": "Cancels destroying block when the client drops an item.",
"debugify.fix_explanation.mc-176559": "Does not consider item durability when comparing a change in item when checking if block breaking should reset.",
"debugify.fix_explanation.mc-197260": "Overrides the light level passed to the armour stand renderer with a maximum of: the block below the armor stand, bottom of the armor stand, top of the armor stand and the block above of the armor stand.",
"debugify.fix_explanation.mc-237493": "Adds an option in the telemetry menu to completely disable telemetry. Telemetry is disabled by overriding all outgoing telemetry events to be an empty telemetry event, which is not sent.",
"debugify.fix_explanation.mc-231097": "When dropping an item, the client will send a \"release using item\" packet, if the player is currently using an item.",
"debugify.fix_effect.mc-231097": "This can cause very strict anti-cheats, such as Anti-Gaming-Chair, to flag \"invalid packet order\", which may result in a ban.",
"debugify.fix_explanation.mc-2025": "Due to floating point inaccuracies, sometimes the hitbox of entities end up being slightly smaller than desired. Then, if this happens before the entities are pushed against each-other, they will intersect with the wall. Then, when the AABB is recalculated on chunk load, they will be determined as inside the wall, where they are then pushed. This fix simply writes an 'AABB' tag to entity NBT data with double-precision hitbox sizes which then get loaded back in.",
"debugify.fix_effect.mc-2025": "This fix means loading Debugify for the first time will not fix the issue until the chunks are saved and loaded with Debugify.",
"debugify.fix_explanation.mc-7569": "Appends a new line to the end of every system message.",
"debugify.fix_explanation.mc-30391": "Adds edge-case checks for chicken, blaze and the wither to fall damage spawn particles to not spawn them.",
"debugify.fix_explanation.mc-69216": "Discards fishing hook entity on change to spectator.",
"debugify.fix_explanation.mc-72151": "Wolves have a custom function to modify the amount of damage they take, which transforms input damage 0 to 0.5, this fix checks if the damage is 0.5 and changes it back to 0.",
"debugify.fix_explanation.mc-88371": "Sets the dragon landing Y position to 65 if the center spawn has been destroyed.",
"debugify.fix_explanation.mc-89146": "Provides a strict save order of tile entities, to match the update order which then allows initial update of tile entities to be in the correct order.",
"debugify.fix_explanation.mc-93018": "Only initiate breeding if the wolf is tamed.",
"debugify.fix_explanation.mc-100991": "Notifies the damage tracker of a thrown fishing hook damaging the entity with 0 damage, like snowballs.",
"debugify.fix_explanation.mc-119417": "Stops player from sleeping when they change to spectator.",
"debugify.fix_explanation.mc-119754": "Tells firework entities that players are not elytra flying if in spectator.",
"debugify.fix_explanation.mc-121706": "Entities with a ranged bow attack goal are forced to look at their target.",
"debugify.fix_explanation.mc-121903": "Adds NBT tag 'LastExecuted' to command blocks to save and load their last executed property.",
"debugify.fix_explanation.mc-124117": "Sends players packets to update all their effects, their experience and their abilities after cross dimensional teleport.",
"debugify.fix_explanation.mc-132878": "Spawns breaking particles when armour stands are hurt.",
"debugify.fix_explanation.mc-134110": "Correctly rotates double chests when a structure that is mirrored is placed.",
"debugify.fix_explanation.mc-135971": "Overrides CTRL+Q behaviour in crafting slot to repeatedly CTRL+Q until there are no items left in the crafting slot.",
"debugify.fix_explanation.mc-155509": "Checks if the pufferfish is alive before attempting to sting the player.",
"debugify.fix_explanation.mc-159283": "Casts 32-bit integers to 64-bit equivalents to prevent integer overflow at high X and Z values.",
"debugify.fix_effect.mc-159283": "Affects world generation.",
"debugify.fix_explanation.mc-160095": "If cacti encounter a piston head, the block that is being moved by the piston is considered instead of the piston.",
"debugify.fix_explanation.mc-179072": "Checks if the entity the creeper sees is an enemy before igniting.",
"debugify.fix_explanation.mc-183990": "When a mob is ticked, it checks to see if its target is dead, and removes it if so. This fix also applies to a long list of entities that have group attacks, not just silverfish.",
"debugify.fix_explanation.mc-193343": "Removes soul speed if player is a spectator.",
"debugify.fix_explanation.mc-199467": "Modifies the input to sin and cos functions, which wraps the input from 0 to 2pi. This prevents any integer overflows occurring. Whilst this issue is reportedly an issue of the client, the root cause is in both environments, hence it's located in main.",
"debugify.fix_explanation.mc-200418": "Dismounts baby villagers from chickens upon conversion.",
"debugify.fix_explanation.mc-206922": "Items with an age less than 9 ticks are not removed from lightning strikes.",
"debugify.fix_explanation.mc-215530": "Resets frozen time when the player changes to spectator.",
"debugify.fix_explanation.mc-219981": "Sets the zombie's health to its new max health minus whatever damage it has taken.",
"debugify.fix_explanation.mc-224729": "Always saves ProtoChunks even if the chunk save predicate returns false.",
"debugify.fix_explanation.mc-226961": "Uses XP Orbs' eye height to determine if it is inside lava.",
"debugify.fix_effect.mc-226961": "XP Orbs are killed shortly upon touching lava instead of bouncing.",
"debugify.fix_explanation.mc-298225": "Fixes skybox getting cut off (i.e. holes/gaps) at low render distances by increasing far plane distance.",
"debugify.fix_explanation.mc-268617": "Updates the RegEx filter to include all valid path locations. This allows using structure blocks in certain launchers such as Modrinth or any Linux Flatpak launcher.",
"debugify.fix_explanation.mc-272431": "Fixes the dragon's velocity when traveling to path nodes, making it able to properly traverse to its destination and not circle above it.",
"debugify.fix_effect.mc-272431": "Prevents zero and one-cycling the dragon as the dragon will no longer slowly perch on the end fountain or above travel nodes.",
"debugify.fix_explanation.mc-297837": "Only use horizontal distance when calculating which waypoint transmitter to use, since large distances use azimuthal distance, which guesses pitch via horizon angle.",
"debugify.fix_effect.mc-297837": "This allows clients to get exact position of players even when they are far away, but only vertically.",
"debugify.fix_explanation.mc-299115": "The owner's reference is converted to an entity on deflection. This conversion fails if the owner is offline."
}
================================================
FILE: src/main/resources/assets/debugify/lang/es_ar.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Arreglos básicos",
"debugify.gameplay": "Arreglos de jugabilidad",
"debugify.gameplay.warning": "ADVERTENCIA: ¡Esta categoría contiene arreglos que podrían ser una ventaja injusta!",
"debugify.gameplay.enable_in_multiplayer": "Habilitar en multijugador",
"debugify.fix.enabled": "Arreglado",
"debugify.fix.disabled": "No arreglado",
"debugify.fix.unavailable": "No disponible",
"debugify.error.conflict": "La corrección %s es incompatible con el mod '%s'",
"debugify.error.os": "%s solo se aplica a %s",
"debugify.error.mixin_error": "Falló la carga de %s, revisá el registro para más información.",
"debugify.error.mixin_error.text": "Error",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Misceláneo",
"debugify.misc.default_disabled": "Predeterminado desactivado",
"debugify.misc.default_disabled.description": "Por defecto, las nuevas correcciones de errores estarán desactivadas en vez de activadas.",
"debugify.env.client": "Cliente",
"debugify.env.client.desc": "Arreglos que solo se aplican en el cliente.",
"debugify.env.server": "Principal",
"debugify.env.server.desc": "Arreglos que se aplican tanto al cliente como al servidor, y al código común entre ambos.",
"debugify.no_yacl.title": "¡YetAnotherConfigLib no instalado!",
"debugify.no_yacl.description": "Para configurar Debugify desde una interfaz gráfica, necesitás instalar %s. Es la librería que habilita esta funcionalidad. Si no, podés configurarlo manualmente desde el archivo JSON ubicado en '%s'.",
"debugify.mc_237493.header": "Telemetría deshabilitada por Debugify",
"debugify.mc_237493.line": "Elegiste '%s' en la opción de telemetría, así que Debugify está bloqueando cualquier conexión a servicios de telemetría de Mojang. Esto lo proporciona Debugify para corregir el error MC-237493.",
"debugify.mc_237493.tooltip.off": "'%s' desactiva completamente cualquier conexión a los servicios de telemetría de Mojang. (Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "'%s' solo incluye la información que Mojang considera necesaria.",
"debugify.mc_237493.tooltip.all": "'%s' incluye toda la información mínima y opcional de telemetría.",
"debugify.fix_explanation.mc-46503": "Limpia los efectos de sombreado al reaparecer.",
"debugify.fix_explanation.mc-55347": "Limpia los títulos al desconectarse.",
"debugify.fix_explanation.mc-79545": "Restringe el nivel de experiencia al límite de enteros solamente al renderizar.",
"debugify.fix_explanation.mc-93384": "Agrega la altura de los ojos a la ubicación de aparición de partículas.",
"debugify.fix_explanation.mc-105068": "Hace que el sonido de ruptura de escudo sea local.",
"debugify.fix_explanation.mc-108948": "El cliente no ejecuta los mismos cálculos de física del bote que el servidor. Esta corrección hace que el cliente también realice esos cálculos cuando nadie está controlando el bote.",
"debugify.fix_explanation.mc-111516": "Corrige un cálculo matemático de 'acos' para que el resultado no supere 1.0.",
"debugify.fix_explanation.mc-118740": "Muestra el cooldown del ataque en la mira al hacer clic derecho.",
"debugify.fix_effect.mc-118740": "También corrige MC-116510: El indicador de ataque no muestra (la mayoría de las veces) que romper bloques instantáneos reinicia el ataque.",
"debugify.fix_explanation.mc-112730": "Evita que faros y otras entidades de bloque se agreguen a la lista local de renderizado si ya están en la lista global.",
"debugify.fix_explanation.mc-122477": "Evita que las dos primeras entradas de teclado afecten después de abrir un cuadro de texto, como el chat.",
"debugify.fix_explanation.mc-123739": "Ordena las entradas del libro de recetas por su identificador.",
"debugify.fix_explanation.mc-143474": "Copia la ranura de objeto seleccionada al regenerar el jugador tras reaparecer.",
"debugify.fix_effect.mc-143474": "También corrige MC-12062: La selección de la barra rápida se reinicia a la izquierda al salir del End.",
"debugify.fix_explanation.mc-159163": "Elimina la sincronización de datos de pose del servidor al cliente.",
"debugify.fix_effect.mc-159163": "Esto hará que la pose del jugador se determine solamente del lado del cliente.",
"debugify.fix_explanation.mc-162253": "Evita una actualización de iluminación del cliente al cargar un chunk.",
"debugify.fix_explanation.mc-165381": "Cancela la destrucción de bloques si el jugador tira un objeto.",
"debugify.fix_explanation.mc-176559": "Ignora la durabilidad al comparar cambios de objetos durante la ruptura de bloques.",
"debugify.fix_explanation.mc-197260": "Corrige la iluminación de las armaduras considerando su entorno inmediato.",
"debugify.fix_explanation.mc-237493": "Agrega una opción en el menú de telemetría para desactivar completamente la telemetría.",
"debugify.fix_explanation.mc-2025": "Corrige imprecisiones en las hitboxes de entidades escribiendo valores de mayor precisión en los datos NBT.",
"debugify.fix_effect.mc-2025": "Esta corrección requiere guardar y volver a cargar los chunks afectados.",
"debugify.fix_explanation.mc-7569": "Agrega un salto de línea a cada mensaje del sistema.",
"debugify.fix_explanation.mc-30391": "Evita la aparición de partículas de daño para gallinas, blaze y el wither en caídas.",
"debugify.fix_explanation.mc-69216": "Descarta el anzuelo si el jugador cambia a espectador.",
"debugify.fix_explanation.mc-72151": "Corrige el cálculo de daño recibido por lobos cuando debería ser cero.",
"debugify.fix_explanation.mc-88371": "Corrige la altura de aterrizaje del dragón cuando el pilar central fue destruido.",
"debugify.fix_explanation.mc-89146": "Fuerza un orden de guardado de entidades de bloque consistente.",
"debugify.fix_explanation.mc-93018": "Sólo permite la reproducción de lobos domesticados.",
"debugify.fix_explanation.mc-100991": "Corrige el daño cero del anzuelo de pesca registrándolo correctamente.",
"debugify.fix_explanation.mc-119417": "Evita que un jugador siga durmiendo si cambia a espectador.",
"debugify.fix_explanation.mc-119754": "Corrige el estado de vuelo de elytra para jugadores en espectador.",
"debugify.fix_explanation.mc-121706": "Fuerza a entidades con ataque a distancia a mirar a su objetivo.",
"debugify.fix_explanation.mc-121903": "Agrega un tag NBT 'LastExecuted' para guardar el último estado de bloques de comando.",
"debugify.fix_explanation.mc-124117": "Actualiza los efectos, experiencia y habilidades de un jugador tras una teletransportación entre dimensiones.",
"debugify.fix_explanation.mc-132878": "Genera partículas de ruptura cuando dañan a un soporte de armaduras.",
"debugify.fix_explanation.mc-134110": "Rota correctamente cofres dobles al colocar estructuras espejadas.",
"debugify.fix_explanation.mc-135971": "Mejora el comportamiento de CTRL+Q para vaciar ranuras de crafteo.",
"debugify.fix_explanation.mc-155509": "Evita que el pez globo ataque si está muerto.",
"debugify.fix_explanation.mc-159283": "Convierte enteros de 32 bits a equivalentes de 64 para evitar desbordamientos numéricos en valores X y Z altos.",
"debugify.fix_effect.mc-159283": "Afecta la generación del mundo.",
"debugify.fix_explanation.mc-160095": "Corrige la colisión de cactus con cabezas de pistones móviles.",
"debugify.fix_explanation.mc-179072": "Los creepers sólo se encienden si ven un enemigo real.",
"debugify.fix_explanation.mc-183990": "Corrige que mobs sigan atacando objetivos muertos.",
"debugify.fix_explanation.mc-193343": "Elimina el efecto de 'Soul Speed' en modo espectador.",
"debugify.fix_explanation.mc-199467": "Corrige posibles desbordamientos enteros al usar funciones seno/coseno.",
"debugify.fix_explanation.mc-200418": "Hace que los aldeanos bebés desmonten pollos al convertirse.",
"debugify.fix_explanation.mc-206922": "Evita que rayos eliminen ítems con menos de 9 ticks de edad.",
"debugify.fix_explanation.mc-215530": "Resetea el congelamiento al cambiar a espectador.",
"debugify.fix_explanation.mc-224729": "Siempre guarda los ProtoChunks incluso si el predicado de guardado falla.",
"debugify.fix_explanation.mc-298225": "Corrige cortes en el skybox (agujeros) con baja distancia de render, aumentando la distancia del plano lejano.",
"debugify.fix_explanation.mc-268617": "Actualiza el filtro RegEx para incluir rutas válidas. Esto permite usar bloques de estructura en launchers como Modrinth o Flatpak en Linux."
}
================================================
FILE: src/main/resources/assets/debugify/lang/es_mx.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Correcciones Básicas",
"debugify.gameplay": "Correcciones de Jugabilidad",
"debugify.gameplay.warning": "ADVERTENCIA: ¡Esta categoría contiene correcciones que pueden ser una ventaja injusta!",
"debugify.gameplay.enable_in_multiplayer": "Habilitar en Multijugador",
"debugify.fix.enabled": "Corregido",
"debugify.fix.disabled": "No corregido",
"debugify.fix.unavailable": "No disponible",
"debugify.error.conflict": "La corrección %s es incompatible con el mod '%s'",
"debugify.error.os": "%s solo se aplica a %s",
"debugify.error.mixin_error": "Error al cargar %s, revisa el registro para obtener más información.",
"debugify.error.mixin_error.text": "Con errores",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Misceláneo",
"debugify.misc.default_disabled": "Desactivado por defecto",
"debugify.misc.default_disabled.description": "Configura las nuevas correcciones para que estén desactivadas en lugar de activadas.",
"debugify.env.client": "Cliente",
"debugify.env.client.desc": "Correcciones que solo se aplican en el cliente.",
"debugify.env.server": "Principal",
"debugify.env.server.desc": "Correcciones que se aplican tanto en el cliente como en el servidor, y código común entre ellos.",
"debugify.no_yacl.title": "¡YetAnotherConfigLib no está instalado!",
"debugify.no_yacl.description": "Para configurar Debugify utilizando una interfaz gráfica, debes instalar %s, esta es la biblioteca utilizada para hacer esta funcionalidad disponible. De lo contrario, puedes configurarlo utilizando el archivo JSON almacenado en '%s'.",
"debugify.mc_237493.header": "Telemetría desactivada por Debugify",
"debugify.mc_237493.line": "Seleccionaste '%s' en la opción de telemetría, por lo que Debugify está evitando cualquier conexión con los servicios de telemetría de Mojang. Esto es proporcionado por Debugify para solucionar MC-237493.",
"debugify.mc_237493.tooltip.off": "'%s' deshabilita por completo cualquier conexión a los servicios de telemetría de Mojang. (Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "'%s' incluye solo la información que Mojang considera necesaria.",
"debugify.mc_237493.tooltip.all": "'%s' incluye toda la información de minimal y telemetría opcional.",
"debugify.fix_explanation.mc-55347": "Borra los títulos al desconectar.",
"debugify.fix_explanation.mc-79545": "Limita el nivel de experiencia al límite entero solo al renderizar.",
"debugify.fix_explanation.mc-93384": "Agrega la altura de los ojos a la ubicación de generación de partículas.",
"debugify.fix_explanation.mc-108948": "El problema es que el cliente no ejecuta los mismos cálculos que el servidor. Cuando nadie está controlando el bote, el cliente no ejecuta la física en el bote, lo que causa una desincronización del cliente. Esta corrección simplemente le indica al cliente que ejecute algunos cálculos de física en el bote.",
"debugify.fix_explanation.mc-111516": "Modifica un cálculo de acos matemático para asegurarse de que el resultado no sea mayor a 1.0",
"debugify.fix_explanation.mc-112730": "Evita que los bloques de faros y otras entidades de bloque se agreguen a la lista de renderizado de entidades de bloque local si ya se han agregado a la lista global.",
"debugify.fix_explanation.mc-122477": "Evita las dos primeras actualizaciones de teclado después de inicializar un cuadro de edición, por ejemplo, el cuadro de chat.",
"debugify.fix_explanation.mc-123739": "Ordena las entradas del libro de recetas por su identificador.",
"debugify.fix_explanation.mc-143474": "Copia la ranura de objeto seleccionada al generar el nuevo jugador local después de reaparecer.",
"debugify.fix_explanation.mc-159163": "Elimina los datos de postura del manejo de paquetes de datos de entidad.",
"debugify.fix_effect.mc-159163": "Esto evitará que el cliente sincronice los datos de postura con el servidor y utiliza únicamente el cliente para decidir la postura.",
"debugify.fix_explanation.mc-162253": "Detiene una actualización de luz del cliente al ingresar a un fragmento.",
"debugify.fix_explanation.mc-165381": "Cancela la destrucción del bloque cuando el cliente suelta un objeto",
"debugify.fix_explanation.mc_176559": "No considera la durabilidad del objeto al comparar un cambio en el objeto al verificar si se debe restablecer la rotura del bloque.",
"debugify.fix_explanation.mc-197260": "Anula el nivel de luz pasado al renderizador de soportes de armadura con un máximo de: el bloque debajo del soporte de armadura, la parte inferior del soporte de armadura, la parte superior del soporte de armadura y el bloque encima del soporte de armadura.",
"debugify.fix_explanation.mc-237493": "Agrega una opción en el menú de telemetría para desactivar completamente la telemetría. La telemetría se desactiva al anular todos los eventos de telemetría salientes y convertirlos en eventos de telemetría vacíos, que no se envían.",
"debugify.fix_explanation.mc-2025": "Debido a imprecisiones de punto flotante, a veces la caja de colisión de las entidades termina siendo ligeramente más pequeña de lo deseado. Entonces, si esto sucede antes de que las entidades se empujen una contra la otra, se intersecarán con la pared. Luego, cuando la AABB se recalcula al cargar el chunk, se determinará que están dentro de la pared, donde entonces se las empuja. Esta corrección simplemente escribe una etiqueta 'AABB' en los datos NBT de la entidad con tamaños de caja de colisión de doble precisión que luego se cargarán nuevamente.",
"debugify.fix_effect.mc-2025": "Esta corrección significa que cargar Debugify por primera vez no solucionará el problema hasta que se guarden y carguen los chunks con Debugify.",
"debugify.fix_explanation.mc-7569": "Agrega una nueva línea al final de cada mensaje del sistema.",
"debugify.fix_explanation.mc-30391": "Agrega verificaciones de casos especiales para partículas de spawn de caída de pollos, blazes y el wither para no generarlas.",
"debugify.fix_explanation.mc-69216": "Descarta la entidad de caña de pescar al cambiar al modo espectador.",
"debugify.fix_explanation.mc-72151": "Los lobos tienen una función personalizada para modificar la cantidad de daño que reciben, que transforma el daño de entrada de 0 a 0.5, esta corrección verifica si el daño es 0.5 y lo cambia de vuelta a 0.",
"debugify.fix_explanation.mc-88371": "Establece la posición Y de aterrizaje del dragón en 65 si el punto central de aparición ha sido destruido.",
"debugify.fix_explanation.mc-89146": "Proporciona un orden estricto de guardado de entidades de bloques para que coincida con el orden de actualización, lo que permite que la actualización inicial de las entidades de bloques se realice en el orden correcto.",
"debugify.fix_explanation.mc-93018": "Solo inicia el apareamiento si el lobo está domesticado.",
"debugify.fix_explanation.mc-100991": "Notifica al rastreador de daños que un anzuelo de pesca lanzado daña a la entidad con 0 de daño, como las bolas de nieve.",
"debugify.fix_explanation.mc-119417": "Impide que el jugador duerma cuando cambia a espectador.",
"debugify.fix_explanation.mc-119754": "Indica a las entidades de fuegos artificiales que los jugadores no están volando con el elytra si están en modo espectador.",
"debugify.fix_explanation.mc-121706": "Obliga a las entidades con un objetivo de ataque a distancia con arco a mirar a su objetivo.",
"debugify.fix_explanation.mc-121903": "Agrega la etiqueta NBT 'LastExecuted' a los bloques de comandos para guardar y cargar su última propiedad ejecutada.",
"debugify.fix_explanation.mc-124117": "Envía a los jugadores paquetes para actualizar todos sus efectos, su experiencia y sus habilidades después de un teletransporte entre dimensiones.",
"debugify.fix_explanation.mc-132878": "Genera partículas de rotura cuando los soportes de armadura son dañados.",
"debugify.fix_explanation.mc-135971": "Cambia el comportamiento de CTRL+Q en la ranura de crafteo para repetir CTRL+Q hasta que no queden objetos en la ranura de crafteo.",
"debugify.fix_explanation.mc-155509": "Verifica si el pez globo está vivo antes de intentar picar al jugador.",
"debugify.fix_explanation.mc-160095": "Si los cactus encuentran una cabeza de pistón, se considera el bloque que está siendo movido por el pistón en lugar del pistón mismo.",
"debugify.fix_explanation.mc-179072": "Verifica si la entidad que ve el creeper es un enemigo antes de encenderse.",
"debugify.fix_explanation.mc-183990": "Cuando se actualiza una criatura, verifica si su objetivo está muerto y lo elimina en caso afirmativo. Esta corrección también se aplica a una larga lista de entidades que tienen ataques grupales, no solo a los silverfish.",
"debugify.fix_explanation.mc-193343": "Elimina la velocidad de alma si el jugador está en modo espectador.",
"debugify.fix_explanation.mc-199467": "Modifica la entrada de las funciones sin y cos para que el valor se encuentre en el rango de 0 a 2pi. Esto evita cualquier desbordamiento de enteros. Aunque este problema se informa como un problema del cliente, la causa raíz se encuentra en ambos entornos, por lo que se encuentra en el código principal.",
"debugify.fix_explanation.mc-200418": "Desmonta a los aldeanos bebés de los pollos al convertirse.",
"debugify.fix_explanation.mc-206922": "Los objetos con una edad menor a 9 ticks no se eliminan por los rayos.",
"debugify.fix_explanation.mc-215530": "Restablece el tiempo congelado cuando el jugador cambia a espectador.",
"debugify.fix_explanation.mc-224729": "Siempre guarda los ProtoChunks incluso si el predicado de guardado del chunk devuelve falso."
}
================================================
FILE: src/main/resources/assets/debugify/lang/fr_fr.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Corrections de base",
"debugify.gameplay": "Corrections du gameplay",
"debugify.gameplay.warning": "AVERTISSEMENT : Cette catégorie contient des correctifs qui peuvent constituer un avantage injuste.!",
"debugify.gameplay.enable_in_multiplayer": "Activer en multijoueur",
"debugify.fix.enabled": "Corrigé",
"debugify.fix.disabled": "Non corrigé",
"debugify.fix.unavailable": "Indisponible",
"debugify.error.conflict": "%s est déjà corrigé par le mod '%s'.",
"debugify.error.os": "%s ne s'applique qu'à %s",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Divers",
"debugify.misc.default_disabled": "Valeur par défaut : désactivé",
"debugify.misc.default_disabled.description": "Désactive par défaut les nouveaux correctifs de bugs au lieu de les activer.",
"debugify.env.client": "Client",
"debugify.env.client.desc": "Corrections qui ne s'appliquent qu'au client.",
"debugify.env.server": "Principal",
"debugify.env.server.desc": "Corrections qui s'appliquent à la fois au client et au serveur, et au code commun entre eux.",
"debugify.no_yacl.title": "YetAnotherConfigLib non installé !",
"debugify.no_yacl.description": "Pour configurer Debugify à l'aide d'une superposition, vous devez installer %s, qui est la bibliothèque utilisée pour rendre cette fonctionnalité disponible. Sinon, vous pouvez configurer en utilisant le fichier JSON stocké dans '%s'.",
"debugify.mc_237493.header": "Télémétrie désactivée par Debugify",
"debugify.mc_237493.line": "Vous avez choisi '%s' pour l'option de télémétrie, Debugify empêche donc toute connexion avec les services de télémétrie de Mojang. Cette option est fournie par Debugify pour la correction MC-237493.",
"debugify.mc_237493.tooltip.off": "'%s' désactive complètement toute connexion aux services de télémétrie de Mojang. (Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "Le fichier \"%s\" ne contient que les informations que Mojang juge nécessaires.",
"debugify.mc_237493.tooltip.all": "'%s' inclut toute la télémétrie minimale et optionnelle."
}
================================================
FILE: src/main/resources/assets/debugify/lang/it_it.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Correzioni di base",
"debugify.gameplay": "Correzioni di gameplay",
"debugify.gameplay.warning": "ATTENZIONE: Questa categoria contiene correzioni che potrebbero rappresentare un vantaggio sleale!",
"debugify.gameplay.enable_in_multiplayer": "Abilita in multiplayer",
"debugify.fix.enabled": "Corretto",
"debugify.fix.disabled": "Non corretto",
"debugify.fix.unavailable": "Non disponibile",
"debugify.error.conflict": "La correzione %s è incompatibile con la mod '%s'",
"debugify.error.os": "%s si applica solo a %s",
"debugify.error.mixin_error": "Impossibile caricare %s, controlla il log per ulteriori informazioni.",
"debugify.error.mixin_error.text": "Errore",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Varie",
"debugify.misc.default_disabled": "Disabilitato per default",
"debugify.misc.default_disabled.description": "Imposta le nuove correzioni di bug come disabilitate anziché abilitate di default.",
"debugify.env.client": "Client",
"debugify.env.client.desc": "Correzioni che si applicano solo al client.",
"debugify.env.server": "Server",
"debugify.env.server.desc": "Correzioni che si applicano sia al client che al server, e al codice comune tra di essi.",
"debugify.no_yacl.title": "YetAnotherConfigLib non installato!",
"debugify.no_yacl.description": "Per configurare Debugify utilizzando un'interfaccia grafica, è necessario installare %s, questa è la libreria utilizzata per rendere disponibile questa funzionalità. Altrimenti, puoi configurare utilizzando il file JSON memorizzato in '%s'.",
"debugify.mc_237493.header": "Telemetria disabilitata da Debugify",
"debugify.mc_237493.line": "Hai scelto '%s' per l'opzione di telemetria, quindi Debugify sta impedendo qualsiasi connessione con i servizi di telemetria di Mojang. Questo è fornito da Debugify per risolvere MC-237493.",
"debugify.mc_237493.tooltip.off": "'%s' disabilita completamente qualsiasi connessione ai servizi di telemetria di Mojang. (Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "'%s' include solo le informazioni che Mojang considera necessarie.",
"debugify.mc_237493.tooltip.all": "'%s' include tutto ciò che è minimo e l'opzione di telemetria.",
"debugify.fix_explanation.mc-55347": "Pulisce i titoli alla disconnessione.",
"debugify.fix_explanation.mc-79545": "Limita il livello di esperienza al valore intero solo durante il rendering.",
"debugify.fix_explanation.mc-93384": "Aggiunge l'altezza degli occhi alla posizione di generazione delle particelle.",
"debugify.fix_explanation.mc-105068": "Rende il suono di rottura dello scudo un suono locale.",
"debugify.fix_explanation.mc-108948": "Il problema è che il client non esegue gli stessi calcoli del server. Quando nessuno sta controllando la barca, il client non esegue la fisica sulla barca, causando una desincronizzazione del client. Questa correzione semplicemente dice al client di eseguire alcuni calcoli fisici sulla barca.",
"debugify.fix_explanation.mc-111516": "Modifica un calcolo matematico di `acos` per assicurarsi che il risultato non sia superiore a 1.0",
"debugify.fix_explanation.mc-112730": "Impede che i beacon e altre entità di blocco vengano aggiunti alla lista del renderer locale delle entità di blocco se sono già stati aggiunti alla lista globale.",
"debugify.fix_explanation.mc-122477": "Previene i primi due polling della tastiera dopo che una casella di modifica è stata inizializzata, ad esempio la casella di chat.",
"debugify.fix_explanation.mc-123739": "Ordina le voci del ricettario per il loro identificatore.",
"debugify.fix_explanation.mc-143474": "Copia lo slot dell'oggetto selezionato quando si genera il nuovo giocatore locale dopo il respawn.",
"debugify.fix_explanation.mc-159163": "Rimuove i dati della posa dalla gestione dei pacchetti dei dati delle entità.",
"debugify.fix_effect.mc-159163": "Questo impedirà al client di sincronizzare i dati della posa con il server e utilizzerà solo il client per decidere la posa.",
"debugify.fix_explanation.mc-162253": "Interrompe un aggiornamento della luce del client quando si entra in un chunk.",
"debugify.fix_explanation.mc-165381": "Annulla la distruzione del blocco quando il client lancia un oggetto.",
"debugify.fix_explanation.mc_176559": "Non considera la durabilità dell'oggetto quando si confronta un cambiamento dell'oggetto per verificare se la rottura del blocco dovrebbe essere reimpostata.",
"debugify.fix_explanation.mc-197260": "Sovrascrive il livello di luce passato al renderer del supporto armature con un massimo di: il blocco sotto il supporto armature, il fondo del supporto armature, la parte superiore del supporto armature e il blocco sopra il supporto armature.",
"debugify.fix_explanation.mc-237493": "Aggiunge un'opzione nel menu di telemetria per disabilitare completamente la telemetria. La telemetria è disabilitata sovrascrivendo tutti gli eventi di telemetria in uscita con un evento di telemetria vuoto, che non viene inviato.",
"debugify.fix_explanation.mc-2025": "A causa di imprecisioni nei numeri in virgola mobile, a volte la hitbox delle entità risulta leggermente più piccola del desiderato. Se questo accade prima che le entità vengano spostate l'una contro l'altra, esse intersecheranno il muro. Poi, quando l'AABB viene ricalcolato al caricamento del chunk, verranno determinate come dentro il muro, dove vengono quindi spostate. Questa correzione semplicemente aggiunge un tag 'AABB' ai dati NBT dell'entità con dimensioni della hitbox a doppia precisione, che vengono poi ricaricate.",
"debugify.fix_effect.mc-2025": "Questa correzione significa che caricare Debugify per la prima volta non risolverà il problema fino a quando i chunk non saranno salvati e ricaricati con Debugify.",
"debugify.fix_explanation.mc-7569": "Aggiunge una nuova riga alla fine di ogni messaggio di sistema.",
"debugify.fix_explanation.mc-30391": "Aggiunge controlli per casi limite per pollo, blaze e wither per impedire la generazione di particelle di danno da caduta.",
"debugify.fix_explanation.mc-69216": "Scarta l'entità del gancio da pesca al cambio in modalità spettatore.",
"debugify.fix_explanation.mc-72151": "I lupi hanno una funzione personalizzata per modificare la quantità di danno che ricevono, che trasforma il danno in ingresso da 0 a 0,5; questa correzione controlla se il danno è 0,5 e lo riporta a 0.",
"debugify.fix_explanation.mc-88371": "Imposta la posizione Y di atterraggio del drago a 65 se il centro di spawn è stato distrutto.",
"debugify.fix_explanation.mc-89146": "Fornisce un ordine di salvataggio rigoroso per le entità di tile, per abbinare l'ordine di aggiornamento, consentendo così l'aggiornamento iniziale delle entità di tile nell'ordine corretto.",
"debugify.fix_explanation.mc-93018": "Avvia la riproduzione solo se il lupo è addomesticato.",
"debugify.fix_explanation.mc-100991": "Notifica al tracker dei danni di un gancio da pesca lanciato che infligge danno 0 all'entità, come le palle di neve.",
"debugify.fix_explanation.mc-119417": "Impedisce al giocatore di dormire quando cambia in modalità spettatore.",
"debugify.fix_explanation.mc-119754": "Comunica alle entità dei fuochi d'artificio che i giocatori non stanno volando con l'elytra se sono in modalità spettatore.",
"debugify.fix_explanation.mc-121706": "Le entità con un obiettivo di attacco con arco a distanza sono costrette a guardare il loro bersaglio.",
"debugify.fix_explanation.mc-121903": "Aggiunge il tag NBT 'LastExecuted' ai blocchi di comando per salvare e caricare la loro proprietà dell'ultimo comando eseguito.",
"debugify.fix_explanation.mc-124117": "Invia pacchetti ai giocatori per aggiornare tutti i loro effetti, la loro esperienza e le loro abilità dopo il teletrasporto tra dimensioni.",
"debugify.fix_explanation.mc-132878": "Genera particelle di rottura quando i supporti per armature vengono danneggiati.",
"debugify.fix_explanation.mc-135971": "Sostituisce il comportamento di CTRL+Q nello slot di crafting per ripetere CTRL+Q fino a quando non ci sono più oggetti nello slot di crafting.",
"debugify.fix_explanation.mc-155509": "Controlla se il pesce palla è vivo prima di tentare di pungere il giocatore.",
"debugify.fix_explanation.mc-160095": "Se i cactus incontrano una testa di pistone, il blocco che viene spostato dal pistone viene considerato invece del pistone.",
"debugify.fix_explanation.mc-179072": "Controlla se l'entità che il creeper vede è un nemico prima di accendersi.",
"debugify.fix_explanation.mc-183990": "Quando un mob viene tickato, controlla se il suo bersaglio è morto e lo rimuove se è così. Questa correzione si applica anche a una lunga lista di entità che hanno attacchi di gruppo, non solo ai silverfish.",
"debugify.fix_explanation.mc-193343": "Rimuove la velocità dell'anima se il giocatore è in modalità spettatore.",
"debugify.fix_explanation.mc-199467": "Modifica l'input delle funzioni seno e coseno, avvolgendo l'input da 0 a 2pi. Questo previene eventuali overflow di interi. Sebbene questo problema venga segnalato come un problema del client, la causa principale si trova in entrambi gli ambienti, quindi è situata in main.",
"debugify.fix_explanation.mc-200418": "Smonta i villager baby dai polli al momento della conversione.",
"debugify.fix_explanation.mc-206922": "Gli oggetti con un'età inferiore a 9 tick non vengono rimossi dai fulmini.",
"debugify.fix_explanation.mc-215530": "Reimposta il tempo congelato quando il giocatore cambia in modalità spettatore.",
"debugify.fix_explanation.mc-224729": "Salva sempre i ProtoChunks anche se il predicato di salvataggio del chunk restituisce false."
}
================================================
FILE: src/main/resources/assets/debugify/lang/pt_br.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Correções básicas",
"debugify.gameplay": "Correções de jogabilidade",
"debugify.gameplay.warning": "AVISO: Esta categoria contém correções que podem ser uma vantagem injusta!",
"debugify.gameplay.enable_in_multiplayer": "Ativar no Multiplayer",
"debugify.fix.enabled": "consertado",
"debugify.fix.disabled": "Não consertado",
"debugify.fix.unavailable": "Indisponível",
"debugify.error.os": "%s aplica-se apenas a %s",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Diversos",
"debugify.misc.default_disabled": "Padrão para Desativado",
"debugify.misc.default_disabled.description": "Novas correções de bug padrão a serem desabilitadas em vez de habilitadas.",
"debugify.env.client": "Cliente",
"debugify.env.server": "Servidor",
"debugify.no_yacl.title": "YetAnotherConfigLib não instalado!",
"debugify.no_yacl.description": "Para configurar o Debugify usando uma GUI, você deve instalar o %s, esta é a biblioteca usada para disponibilizar esta funcionalidade. Caso contrário, você pode configurar usando o arquivo JSON armazenado em '%s'."
}
================================================
FILE: src/main/resources/assets/debugify/lang/ru_ru.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Основные исправления",
"debugify.gameplay": "Исправления игрового процесса",
"debugify.gameplay.warning": "ВНИМАНИЕ: Эта категория содержит исправления, которые могут являться несправедливым преимуществом!",
"debugify.gameplay.enable_in_multiplayer": "Включить в сетевой игре",
"debugify.fix.enabled": "Исправлено",
"debugify.fix.disabled": "Не исправлено",
"debugify.fix.unavailable": "Недоступно",
"debugify.error.conflict": "Исправление %s несовместимо с модом «%s»",
"debugify.error.os": "%s относится только к %s",
"debugify.error.mixin_error": "Не удалось загрузить %s, посмотрите логи для получения дополнительной информации.",
"debugify.error.mixin_error.text": "Ошибка",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Разное",
"debugify.misc.default_disabled": "Отключать по умолчанию",
"debugify.misc.default_disabled.description": "Все новые исправления будут по умолчанию отключены.",
"debugify.env.client": "Клиент",
"debugify.env.client.desc": "Исправления, применимые только к клиенту.",
"debugify.env.server": "Общие",
"debugify.env.server.desc": "Исправления, применимые как к клиенту, так и к серверу, а также к общему коду между ними.",
"debugify.no_yacl.title": "YetAnotherConfigLib не установлен!",
"debugify.no_yacl.description": "Для настройки Debugify через графический интерфейс требуется мод %s - это библиотека, используемая для предоставленияя данной функции. Иначе вы можете отредактировать настройки мода в JSON файле, хранящемся по пути «%s».",
"debugify.mc_237493.header": "Телеметрия отключена модом Debugify",
"debugify.mc_237493.line": "Вы выбрали «%s» в параметре телеметрии, поэтому Debugify предотвращает любое подключение к службам телеметрии Mojang. Это предусмотрено Debugify для исправления MC-237493.",
"debugify.mc_237493.tooltip.off": "«%s» полностью отключает любое подключение к службам телеметрии Mojang. (Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "«%s» включает только ту информацию, которую Mojang сочтёт необходимой.",
"debugify.mc_237493.tooltip.all": "«%s» включает в себя всю минимальную и дополнительную телеметрию.",
"debugify.fix_explanation.mc-55347": "Очищает текст на экране при отключении.",
"debugify.fix_explanation.mc-79545": "Ограничивает лимит уровней опыта только при рендере.",
"debugify.fix_explanation.mc-93384": "Добавляет к позиции спавна частиц высоту уровня глаз.",
"debugify.fix_explanation.mc-108948": "Проблема в том, что клиент не выполняет те же вычисления, что и сервер. Когда лодкой никто не управляет, клиент не запускает физику лодки, что приводит к рассинхронизации. Это исправление просто указывает клиенту выполнить некоторые физические вычисления у лодки.",
"debugify.fix_explanation.mc-111516": "Изменяет математический расчет acos, чтобы убедиться, что результат не превышает 1.0.",
"debugify.fix_explanation.mc-112730": "Предотвращает добавление маяков и других блоков-сущностей в список рендера локальных блоков-сущностей, если они уже добавлены в общий список.",
"debugify.fix_explanation.mc-122477": "Предотвращает первые два ввода с клавиатуры после открытия окна редактирования (например, окно чата).",
"debugify.fix_explanation.mc-123739": "Сортирует записи в книге рецептов по их идентификатору.",
"debugify.fix_explanation.mc-143474": "Копирует выбранный слот при появлении нового локального игрока после возрождения.",
"debugify.fix_explanation.mc-159163": "Удаляет данные о позе из обработки пакетов сущностей.",
"debugify.fix_effect.mc-159163": "Это отключит синхронизацию данных о позе клиента с сервером, для определения позы будет использоваться только клиент.",
"debugify.fix_explanation.mc-162253": "Останавливает обновление света на клиенте при входе в чанк.",
"debugify.fix_explanation.mc-165381": "Отменяет ломание блока, когда клиент выкидывает предмет.",
"debugify.fix_explanation.mc-176559": "Не учитывать прочность предмета при сравнении изменения предмета во время проверки на прерывание ломания блока.",
"debugify.fix_explanation.mc-197260": "Переопределяет уровень освещения у стойки для брони на максимум для: блока под стойкой, низа и верха стойки, блока над стойкой.",
"debugify.fix_explanation.mc-237493": "Добавляет настройку в меню телеметрии для её полного отключения. Телеметрия отключается путем замены всех исходящих событий телеметрии на пустые события, которые не отправляются.",
"debugify.fix_explanation.mc-2025": "Иногда хитбоксы сущностей оказываются меньше ожидаемых из-за неточностей с дробным значением. Если это произойдёт до того, как сущности окажутся прижатыми друг к другу, они будут заходить в блок. Затем, когда AABB будет пересчитан при загрузке чанков, они будут определены как находящиеся внутри стены, куда они затем будут помещены. Это исправление просто записывает тег AABB в данные NBT сущности с двойной точностью до размеров хитбокса, который затем загружается обратно.",
"debugify.fix_effect.mc-2025": "Это исправление означает, что загрузка Debugify в первый раз не устранит проблему до тех пор, пока чанки не будут сохранены и загружены с помощью Debugify.",
"debugify.fix_explanation.mc-7569": "Добавляет новую строку в конец каждого системного сообщения.",
"debugify.fix_explanation.mc-30391": "Добавляет дополнительные проверки для курицы, всполоха и визера для предотвращения появления частиц от падения.",
"debugify.fix_explanation.mc-69216": "Удаляет сущность крючка удочки при входе в режим наблюдателя.",
"debugify.fix_explanation.mc-72151": "У волков есть специальная функция для изменения количества наносимого им урона, которая преобразует входной урон от 0 до 0.5. Это исправление проверяет, равен ли урон 0.5, и изменяет его обратно на 0.",
"debugify.fix_explanation.mc-88371": "Устанавливает положение по Y для приземления дракона на 65, если центральный спавн был уничтожен.",
"debugify.fix_explanation.mc-89146": "Обеспечивает строгий порядок сохранения тайлов в соответствии с порядком обновления, который затем позволяет выполнять первоначальное обновление тайлов в правильном порядке.",
"debugify.fix_explanation.mc-93018": "Размножение начинается только в том случае, если волк приручен.",
"debugify.fix_explanation.mc-100991": "Уведомляет систему отслеживания урона о том, что крючок удочки наносит урон, равный 0, как снежки.",
"debugify.fix_explanation.mc-119417": "Не дает игроку спать, когда он переключается на режим наблюдателя.",
"debugify.fix_explanation.mc-119754": "Сообщает сущностям фейерверка, что игроки не летают на элитрах, если находятся в режиме наблюдателя.",
"debugify.fix_explanation.mc-121706": "Существа, нацеленные на дальнюю атаку из лука, вынуждены смотреть на свою цель.",
"debugify.fix_explanation.mc-121903": "Добавляет NBT тег LastExecuted к командным блокам для сохранения и загрузки их последнего выполненного свойства.",
"debugify.fix_explanation.mc-124117": "Отправляет пакеты игроков для обновления всех их эффектов, опыта и способностей при перемещении между мирами.",
"debugify.fix_explanation.mc-132878": "Создает частицы разрушения при нанесении урона стойке для брони.",
"debugify.fix_explanation.mc-135971": "Изменяет поведение CTRL+Q в слоте крафта для повторения CTRL+Q до тех пор, пока в слоте для крафта не останется предметов.",
"debugify.fix_explanation.mc-155509": "Проверяет, жив ли иглобрюх, прежде чем кольнуть игрока.",
"debugify.fix_explanation.mc-160095": "Если кактусы сталкиваются с головкой поршня, то вместо поршня рассматривается блок, который перемещается поршнем.",
"debugify.fix_explanation.mc-179072": "Проверяет, является ли существо, которое видит крипер, врагом, прежде чем начать взрываться.",
"debugify.fix_explanation.mc-183990": "Когда моб тикает, он проверяет, мертва ли его цель, и удаляет её, если это так. Это исправление также применимо к большому списку сущностей, которые имеют групповые атаки, а не только к чешуйнице.",
"debugify.fix_explanation.mc-193343": "Убирает скорость души, если игрок является зрителем.",
"debugify.fix_explanation.mc-199467": "Изменяет входные данные для функций sin и cos, которые преобразуют входные данные из 0 в 2pi. Это предотвращает переполнение целых чисел. Хотя, как сообщается, эта проблема связана с клиентом, основная причина находится в обеих средах, следовательно, она находится здесь.",
"debugify.fix_explanation.mc-200418": "Сбрасывает детенышей деревенских жителей с куриц при лечении.",
"debugify.fix_explanation.mc-206922": "Предметы, возраст которых менее 9 тиков, не удаляются после ударов молнии.",
"debugify.fix_explanation.mc-215530": "Сбрасывает заморозку, когда игрок переключается в режим наблюдателя.",
"debugify.fix_explanation.mc-224729": "Всегда сохраняет ProtoChunks, даже если не выполняется условие сохранения чанка.",
"modmenu.summaryTranslation.debugify": "Исправление багов Майнкрафта с баг-трекера",
"modmenu.descriptionTranslation.debugify": "Исправление багов Майнкрафта с баг-трекера\n\nЛицензии:\nj-Tai's TieFix - Использованный код под лицензией LGPLv3\nFlashyReese's Sodium Extra - Использованный код под лицензией LGPLv3\nAmpflower's 2x2 Surronded Saplings Fix - Использованный код под лицензией Zlib"
}
================================================
FILE: src/main/resources/assets/debugify/lang/tr_tr.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Temel Düzeltmeler",
"debugify.gameplay": "Oynanış Düzeltmeleri",
"debugify.gameplay.warning": "UYARI: Bu kategori, haksız bir avantaj olabilecek düzeltmeler içeriyor!",
"debugify.gameplay.enable_in_multiplayer": "Çok Oyunculuda Etkinleştir",
"debugify.misc": "Diğer",
"debugify.misc.default_disabled": "Varsayılan Olarak Devre Dışı",
"debugify.misc.default_disabled.description": "Varsayılan: Etkinleştirmek yerine devre dışı bırakılacak yeni hata düzeltmeleri.",
"debugify.env.client": "İstemci",
"debugify.env.server": "Sunucu"
}
================================================
FILE: src/main/resources/assets/debugify/lang/uk_ua.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Основні виправлення",
"debugify.gameplay": "Виправлення ігроладу",
"debugify.gameplay.warning": "УВАГА: Ця категорія містить виправлення, які можуть бути нечесною перевагою!",
"debugify.gameplay.enable_in_multiplayer": "Увімкнути в мережевій грі",
"debugify.fix.enabled": "Виправлено",
"debugify.fix.disabled": "Не виправлено",
"debugify.fix.unavailable": "Недоступно",
"debugify.error.os": "%s стосується лише %s",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Різне",
"debugify.misc.default_disabled": "За замовчуванням вимкнено",
"debugify.misc.default_disabled.description": "Нові виправлення помилок за замовчуванням мають бути вимкнені, а не ввімкнені.",
"debugify.env.client": "Клієнт",
"debugify.env.server": "Сервер",
"debugify.no_yacl.title": "YetAnotherConfigLib не встановлено!",
"debugify.no_yacl.description": "Щоб налаштувати Debugify за допомогою інтерфейсу, ви повинні встановити %s. Це бібліотека, яка використовується для надання цієї функції. В іншому разі ви можете налаштувати за допомогою файлу JSON, який зберігається в '%s'."
}
================================================
FILE: src/main/resources/assets/debugify/lang/vi_vn.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "Sửa lỗi cơ bản",
"debugify.gameplay": "Sửa lỗi trò chơi",
"debugify.gameplay.warning": "CẢNH BÁO: Danh mục này chứa các bản sửa lỗi có thể là một lợi thế không công bằng!",
"debugify.gameplay.enable_in_multiplayer": "Kích hoạt trong nhiều người chơi",
"debugify.fix.enabled": "Đã sửa",
"debugify.fix.disabled": "Chưa sửa",
"debugify.fix.unavailable": "Không có sẵn",
"debugify.error.conflict": "Bản sửa lỗi %s không tương thích với mod '%s'",
"debugify.error.os": "%s chỉ áp dụng cho %s",
"debugify.error.mixin_error": "Không tải được %s, hãy kiểm tra nhật ký để biết thêm thông tin.",
"debugify.error.mixin_error.text": "Bị lỗi",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "Khác",
"debugify.misc.default_disabled": "Mặc định là Vô hiệu hóa",
"debugify.misc.default_disabled.description": "Các bản sửa lỗi mới mặc định bị vô hiệu hóa thay vì được bật.",
"debugify.env.client": "Máy khách",
"debugify.env.client.desc": "Các bản sửa lỗi chỉ áp dụng trên máy khách.",
"debugify.env.server": "Chính",
"debugify.env.server.desc": "Các bản sửa lỗi áp dụng cho cả máy khách và máy chủ cũng như mã chung giữa chúng.",
"debugify.no_yacl.title": "YetAnotherConfigLib chưa được cài đặt!",
"debugify.no_yacl.description": "Để định cấu hình Debugify bằng GUI, bạn phải cài đặt %s, đây là thư viện được sử dụng để cung cấp chức năng này. Nếu không, bạn có thể định cấu hình bằng cách sử dụng tệp JSON được lưu trữ tại '%s'.",
"debugify.mc_237493.header": "Đo từ xa bị vô hiệu hóa bởi Debugify",
"debugify.mc_237493.line": "Bạn đã chọn '%s' trên tùy chọn đo từ xa, vì vậy Debugify đang ngăn mọi kết nối với các dịch vụ đo từ xa từ Mojang. Điều này được cung cấp bởi Debugify để sửa lỗi MC-237493.",
"debugify.mc_237493.tooltip.off": "'%s' vô hiệu hóa hoàn toàn mọi kết nối với các dịch vụ đo từ xa của Mojang. (Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "'%s' chỉ bao gồm thông tin mà Mojang cho là cần thiết.",
"debugify.mc_237493.tooltip.all": "'%s' bao gồm tất cả phép đo từ xa tối thiểu và tùy chọn.",
"debugify.fix_explanation.mc-55347": "Xóa tiêu đề khi ngắt kết nối.",
"debugify.fix_explanation.mc-79545": "Kẹp mức kinh nghiệm vào giới hạn số nguyên chỉ khi kết xuất.",
"debugify.fix_explanation.mc-93384": "Thêm chiều cao mắt vào vị trí xuất hiện hạt.",
"debugify.fix_explanation.mc-108948": "Vấn đề là máy khách không chạy các tính toán giống như máy chủ. Khi không có ai điều khiển thuyền, máy khách không chạy vật lý trên thuyền, khiến máy khách không đồng bộ hóa. Bản sửa lỗi này chỉ yêu cầu máy khách chạy một số tính toán vật lý trên thuyền.",
"debugify.fix_explanation.mc-111516": "Sửa đổi phép tính acos toán học để đảm bảo kết quả không lớn hơn 1.0",
"debugify.fix_explanation.mc-112730": "Ngăn không cho đèn hiệu và các thực thể khối khác được thêm vào danh sách trình kết xuất thực thể khối cục bộ nếu chúng đã được thêm vào danh sách chung.",
"debugify.fix_explanation.mc-122477": "Ngăn chặn hai cuộc thăm dò bàn phím đầu tiên sau khi hộp chỉnh sửa được khởi tạo, ví dụ: hộp trò chuyện.",
"debugify.fix_explanation.mc-123739": "Sắp xếp các mục trong sách công thức theo số nhận dạng của chúng.",
"debugify.fix_explanation.mc-143474": "Sao chép vị trí vật phẩm đã chọn khi tạo người chơi cục bộ mới sau khi hồi sinh.",
"debugify.fix_explanation.mc-159163": "Loại bỏ dữ liệu tư thế khỏi việc xử lý gói dữ liệu thực thể.",
"debugify.fix_effect.mc-159163": "Điều này sẽ ngăn máy khách đồng bộ hóa dữ liệu tư thế với máy chủ và hoàn toàn sử dụng máy khách để quyết định tư thế.",
"debugify.fix_explanation.mc-162253": "Dừng cập nhật ánh sáng máy khách khi vào một đoạn khúc.",
"debugify.fix_explanation.mc-165381": "Hủy hủy khối khi máy khách đánh rơi vật phẩm",
"debugify.fix_explanation.mc_176559": "Không xem xét độ bền của vật phẩm khi so sánh sự thay đổi trong vật phẩm khi kiểm tra xem có nên đặt lại việc phá vỡ khối hay không.",
"debugify.fix_explanation.mc-197260": "Ghi đè mức ánh sáng được truyền cho trình kết xuất giá đỡ áo giáp với tối đa: khối bên dưới giá đỡ áo giáp, đáy giá đỡ áo giáp, đỉnh giá đỡ áo giáp và khối bên trên giá đỡ áo giáp.",
"debugify.fix_explanation.mc-237493": "Thêm một tùy chọn trong menu đo từ xa để tắt hoàn toàn phép đo từ xa. Đo từ xa bị vô hiệu hóa bằng cách ghi đè tất cả các sự kiện đo từ xa gửi đi thành một sự kiện đo từ xa trống, không được gửi.",
"debugify.fix_explanation.mc-2025": "Do sự không chính xác của dấu phẩy động, đôi khi hộp sát thương của các thực thể cuối cùng nhỏ hơn một chút so với mong muốn. Sau đó, nếu điều này xảy ra trước khi các thực thể bị đẩy vào nhau, chúng sẽ giao nhau với bức tường. Sau đó, khi AABB được tính toán lại trên đoạn tải, chúng sẽ được xác định là bên trong tường, nơi chúng được đẩy. Bản sửa lỗi này chỉ cần ghi thẻ 'AABB' vào dữ liệu NBT của thực thể với kích thước hộp đánh chính xác kép, sau đó được tải lại.",
"debugify.fix_effect.mc-2025": "Khắc phục sự cố này có nghĩa là tải Debugify lần đầu tiên sẽ không khắc phục được sự cố cho đến khi các khối được lưu và tải bằng Debugify.",
"debugify.fix_explanation.mc-7569": "Nối thêm một dòng mới vào cuối mỗi thông báo hệ thống.",
"debugify.fix_explanation.mc-30391": "Thêm kiểm tra trường hợp cạnh cho gà, blaze và wither để sát thương rơi sinh ra các hạt để không sinh ra chúng.",
"debugify.fix_explanation.mc-69216": "Loại bỏ thực thể móc câu khi đổi thành khán giả.",
"debugify.fix_explanation.mc-72151": "Sói có một chức năng tùy chỉnh để sửa đổi lượng sát thương mà chúng nhận, giúp chuyển đổi sát thương đầu vào từ 0 thành 0,5, bản sửa lỗi này kiểm tra xem sát thương có phải là 0,5 hay không và thay đổi về 0.",
"debugify.fix_explanation.mc-88371": "Đặt vị trí hạ cánh Y của rồng ender thành 65 nếu trung tâm đã bị phá hủy.",
"debugify.fix_explanation.mc-89146": "Cung cấp thứ tự lưu nghiêm ngặt của các thực thể khối xếp, để khớp với thứ tự cập nhật, sau đó cho phép cập nhật ban đầu các thực thể khối xếp theo đúng thứ tự.",
"debugify.fix_explanation.mc-93018": "Chỉ bắt đầu sinh sản nếu sói đã được thuần hóa.",
"debugify.fix_explanation.mc-100991": "Thông báo cho bộ theo dõi sát thương về một lưỡi câu bị ném ra gây sát thương cho thực thể bằng 0 sát thương, giống như quả cầu tuyết.",
"debugify.fix_explanation.mc-119417": "Ngăn người chơi ngủ khi họ chuyển sang chế độ khán giả.",
"debugify.fix_explanation.mc-119754": "Nói với các thực thể pháo hoa rằng người chơi không bay elytra nếu ở trong chế độ khán giả",
"debugify.fix_explanation.mc-121706": "Các thực thể có mục tiêu tấn công bằng cung tầm xa buộc phải nhìn vào mục tiêu của chúng.",
"debugify.fix_explanation.mc-121903": "Thêm thẻ NBT 'LastExecuted' vào các khối lệnh để lưu và tải thuộc tính được thực thi cuối cùng của chúng.",
"debugify.fix_explanation.mc-124117": "Gửi cho người chơi các gói để cập nhật tất cả các hiệu ứng, kinh nghiệm và khả năng của họ sau khi dịch chuyển tức thời qua chiều không gian khác.",
"debugify.fix_explanation.mc-132878": "Sinh ra các hạt vỡ khi giá đỡ áo giáp bị tổn thương.",
"debugify.fix_explanation.mc-135971": "Ghi đè hành vi CTRL+Q trong ô chế tạo thành CTRL+Q liên tục cho đến khi không còn vật phẩm nào trong ô chế tạo.",
"debugify.fix_explanation.mc-155509": "Kiểm tra xem cá nóc còn sống hay không trước khi cố gắng chích người chơi.",
"debugify.fix_explanation.mc-160095": "Nếu xương rồng gặp đầu pít-tông, khối đang được chuyển động bởi pít-tông được xem xét thay vì chính pít-tông.",
"debugify.fix_explanation.mc-179072": "Kiểm tra xem thực thể mà creeper nhìn thấy có phải là kẻ thù hay không trước khi phát nổ.",
"debugify.fix_explanation.mc-183990": "Khi một mob được đánh dấu, nó sẽ kiểm tra xem mục tiêu của nó đã chết chưa và loại bỏ nó nếu có. Bản sửa lỗi này cũng áp dụng cho một danh sách dài các thực thể có các cuộc tấn công theo nhóm, không chỉ cá bạc.",
"debugify.fix_explanation.mc-193343": "Loại bỏ Tốc độ linh hồn nếu người chơi đang ở chế độ khán giả.",
"debugify.fix_explanation.mc-199467": "Sửa đổi đầu vào thành các hàm sin và cos, bao hàm đầu vào từ 0 đến 2pi. Điều này ngăn chặn bất kỳ sự cố tràn số nguyên nào xảy ra. Mặc dù sự cố này được báo cáo là sự cố của máy khách, nhưng nguyên nhân cốt lõi nằm ở cả hai môi trường, do đó, nó nằm trong tệp main.",
"debugify.fix_explanation.mc-200418": "Tháo rời dân làng con khỏi gà khi chuyển đổi.",
"debugify.fix_explanation.mc-206922": "Các vật phẩm có tuổi đời dưới 9 tick không bị loại bỏ khỏi sét đánh.",
"debugify.fix_explanation.mc-215530": "Đặt lại thời gian đóng băng khi người chơi thay đổi thành chế độ khán giả.",
"debugify.fix_explanation.mc-224729": "Luôn lưu ProtoChunks ngay cả khi vị từ lưu đoạn mã trả về sai."
================================================
FILE: src/main/resources/assets/debugify/lang/zh_cn.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "基础修复",
"debugify.gameplay": "游戏修复",
"debugify.gameplay.warning": "警告:此类别包含可能对其他人来说不公平的修复!",
"debugify.gameplay.enable_in_multiplayer": "在多人游戏中启用",
"debugify.fix.enabled": "已修复",
"debugify.fix.disabled": "未修复",
"debugify.fix.unavailable": "不可用",
"debugify.error.conflict": "‘%s’修复与模组‘%s’不兼容",
"debugify.error.os": "%s仅适用于%s",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "杂项",
"debugify.misc.default_disabled": "默认为禁用",
"debugify.misc.default_disabled.description": "默认禁用新的错误修复,而不是启用。",
"debugify.env.client": "客户端",
"debugify.env.client.desc": "只适用于客户端的修复。",
"debugify.env.server": "主要",
"debugify.env.server.desc": "适用于客户端和服务器的修复,以及它们之间的共同代码。",
"debugify.no_yacl.title": "未安装 YetAnotherConfigLib!",
"debugify.no_yacl.description": "要使用 GUI 配置 Debugify,你必须安装%s,这是用来实现这一功能的前置库。否则,你可以使用存储在「%s」的JSON文件进行配置。",
"debugify.mc_237493.header": "遥测已由 Debugify 关闭",
"debugify.mc_237493.line": "你在遥测选项上选择了「%s」,所以 Debugify 正在阻止与 Mojang 的遥测服务的任何连接。这是由 Debugify 提供的MC-237493修复。",
"debugify.mc_237493.tooltip.off": "「%s」完全禁用了与 Mojang 遥测服务的任何连接。(Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "「%s」只包括 Mojang 认为需要的信息。",
"debugify.mc_237493.tooltip.all": "「%s」包括所有的最少和可选遥测。"
}
================================================
FILE: src/main/resources/assets/debugify/lang/zh_tw.json
================================================
{
"debugify.name": "Debugify",
"debugify.basic": "基礎修復",
"debugify.gameplay": "遊玩修復",
"debugify.gameplay.warning": "警告:這個類別中的修復可能導致遊戲不公平性!",
"debugify.gameplay.enable_in_multiplayer": "在多人遊戲中啟用",
"debugify.fix.enabled": "已修復",
"debugify.fix.disabled": "未修復",
"debugify.fix.unavailable": "不可用",
"debugify.error.conflict": "%s 修復與「%s」模組不相容",
"debugify.error.os": "%s 僅適用於 %s",
"debugify.error.mixin_error": "%s 載入失敗,檢查記錄檔以取得更多資訊。",
"debugify.error.mixin_error.text": "錯誤",
"debugify.os.windows": "Windows",
"debugify.os.macos": "macOS",
"debugify.os.linux": "Linux",
"debugify.os.solaris": "Solaris",
"debugify.misc": "雜項",
"debugify.misc.default_disabled": "預設停用",
"debugify.misc.default_disabled.description": "新的錯誤修復將會預設停用。",
"debugify.env.client": "用戶端",
"debugify.env.client.desc": "修復僅套用於用戶端。",
"debugify.env.server": "主要",
"debugify.env.server.desc": "修復於用戶端與伺服器端兩者套用,以及它們的通用程式碼。",
"debugify.no_yacl.title": "YetAnotherConfigLib 尚未安裝!",
"debugify.no_yacl.description": "要透過介面來設定 Debugify,你必須安裝 %s,此函式庫將讓本功能可用。不然你也可以透過編輯儲存在 '%s' 中的 JSON 檔案來設定。",
"debugify.mc_237493.header": "Debugify 已停用遙測資料",
"debugify.mc_237493.line": "你在遙測資料選項中選擇「%s」,所以 Debugify 將會防止任何來自 Mojang 的遙測資料服務連線。這是由 Debugify 修復的 MC-237493。",
"debugify.mc_237493.tooltip.off": "「%s」完全停用任何來自 Mojang 遙測資料服務的連線。(Debugify MC-237493)",
"debugify.mc_237493.tooltip.minimal": "「%s」僅包含了 Mojang 認為需要的資訊。",
"debugify.mc_237493.tooltip.all": "「%s」包括了所有最小和遙測資料選項。",
"debugify.fix_explanation.mc-55347": "在中斷連線時清除遺留字幕。",
"debugify.fix_explanation.mc-79545": "在繪製時,將經驗等級限制為整數範圍內。",
"debugify.fix_explanation.mc-93384": "將粒子效果生成於眼睛所看的到的高度。",
"debugify.fix_explanation.mc-108948": "這個問題在於用戶端未與伺服器執行相同的計算。當沒有任何人在控制船時,用戶端不會對船進行物理計算,因而導致用戶端與伺服器端的非同步情況。這個修復簡單地告訴用戶端,對船執行一些物理計算。",
"debugify.fix_explanation.mc-111516": "修改反餘弦數學計算,來確保結果不會大於 1.0。",
"debugify.fix_explanation.mc-112730": "如果烽火台和其他方塊已被加入全域清單中,則防止它們被新增到本機方塊實體繪製清單中。",
"debugify.fix_explanation.mc-122477": "在初始化編輯區時,防止前兩次的鍵盤輸入。(例如聊天室)",
"debugify.fix_explanation.mc-123739": "按照配方的識別碼來排序配方手冊。",
"debugify.fix_explanation.mc-143474": "在重生時,複製重生前所在的物品欄位位置。",
"debugify.fix_explanation.mc-159163": "從資料封包處理中移除姿勢資料。",
"debugify.fix_effect.mc-159163": "這將防止用戶端與伺服器同步姿勢資料,僅讓用戶端決定姿勢。",
"debugify.fix_explanation.mc-162253": "在進入另一個區塊時停止用戶端進行照明更新。",
"debugify.fix_explanation.mc-165381": "當用戶端丟出物品時,取消破壞方塊。",
"debugify.fix_explanation.mc-176559": "在檢查是否重設方塊破壞進度時,不對耐久度的變化進行判斷。",
"debugify.fix_explanation.mc-197260": "覆寫繪製光源通過盔甲座的最大值:在盔甲座下方的方塊、盔甲座底部和盔甲座頂部和更上方的方塊。",
"debugify.fix_explanation.mc-237493": "在遙測資料收集選單中新增一個選項,能夠完整關閉遙測資料收集。透過覆寫所有傳送的遙測事件為空來停用遙測,這也等於沒有傳送任何東西。",
"debugify.fix_explanation.mc-2025": "因為浮點數的不準確性,有的時候實體的碰撞箱會稍微小於預期大小。然後,如果這發生在實體互相推擠彼此時,它們可能會與牆壁交集。然後當 AABB 生物重新在區塊載入時進行計算,它們將會被判斷為在牆壁中,然後被推擠出去。這個修復只是將帶有雙精度浮點數的碰撞箱大小的標籤帶入到 AABB 實體的 NBT 資料中,然後再次被載入回來。",
"debugify.fix_effect.mc-2025": "這個修復代表第一次載入 Debugify 將不會修復這個問題,直到區塊被 Debugify 儲存並重新載入。",
"debugify.fix_explanation.mc-7569": "對系統的每條訊息結尾附加換行。",
"debugify.fix_explanation.mc-30391": "新增對於雞、烈焰使者和凋零的邊緣案例,讓摔落傷害粒子效果不再生成。",
"debugify.fix_explanation.mc-69216": "在切換成觀察者模式時捨棄釣竿的魚鉤。",
"debugify.fix_explanation.mc-72151": "狼會有自訂函數來編輯修改所受到的傷害,將輸入傷害從 0 轉換為 0.5,這將修復檢查如果傷害為 0.5 時變更為 0。",
"debugify.fix_explanation.mc-88371": "若中心的停留點已被摧毀,將把龍的降落點固定在 Y 65。",
"debugify.fix_explanation.mc-89146": "提供一種更嚴格的儲存方塊實體的方式,來符合更新順序,這將允許初始化更新方塊實體時有正確的順序。",
"debugify.fix_explanation.mc-93018": "只有在狼是已馴服狀態下開始繁殖過程。",
"debugify.fix_explanation.mc-100991": "告知傷害追蹤器,拋出釣竿時對實體造成了 0 傷害,就像是雪球一樣。",
"debugify.fix_explanation.mc-119417": "防止玩家在睡覺時切換成觀察者模式。",
"debugify.fix_explanation.mc-119754": "告訴煙火實體,玩家並不是在觀察者模式中用鞘翅飛行。",
"debugify.fix_explanation.mc-121706": "使用遠程弓箭的實體在攻擊時將強制看著目標。",
"debugify.fix_explanation.mc-121903": "在指令方塊中新增「LastExecuted」NBT 標籤,以儲存與載入它們最後的執行屬性。",
"debugify.fix_explanation.mc-124117": "在跨維度傳送後,向玩家發送封包以更新它們所有的效果、經驗值和能力。",
"debugify.fix_explanation.mc-132878": "當盔甲座受到傷害時,正確生成破壞粒子效果。",
"debugify.fix_explanation.mc-135971": "覆寫在合成欄中按下 Crtl+Q 的行為,使其重複按 Crtl+Q 直到合成欄沒有剩餘物品。",
"debugify.fix_explanation.mc-155509": "在嘗試刺玩家前檢查河豚是否活著。",
"debugify.fix_explanation.mc-160095": "如果仙人掌遇到活塞頭,則將考慮被推動的方塊,而不是活塞本身。",
"debugify.fix_explanation.mc-179072": "在點燃自己之前檢查實體對於苦力怕來說是否還是敵人。",
"debugify.fix_explanation.mc-183990": "當生物被運算時,它將會檢查目標是否死亡,如果是則將其從目標移除。這個修復還套用在一長串群攻的實體,不僅僅是蠹魚。",
"debugify.fix_explanation.mc-193343": "當玩家切換至觀察者模式,移除靈魂疾走的移動速度加成。",
"debugify.fix_explanation.mc-199467": "修改正弦函數和餘弦函數的輸入函數,使輸入從 0 到 2pi 循環。這可以防止發生任何整數溢出。雖然這個問題被回報於用戶端發生,但根源是兩個環境都有,因此被放在主要部分中。",
"debugify.fix_explanation.mc-200418": "讓騎乘在雞上的幼年殭屍村民,在被治療後讓牠取消乘坐。",
"debugify.fix_explanation.mc-206922": "存在時間低於 9 刻的物品,不會被雷擊移除掉。",
"debugify.fix_explanation.mc-215530": "當玩家切換成觀察者模式時重設冰凍時間。",
"debugify.fix_explanation.mc-224729": "無論區塊儲存條件返回是否是 false,始終儲存 ProtoChunks。"
}
================================================
FILE: src/main/resources/debugify.mixins.json
================================================
{
"required": true,
"package": "dev.isxander.debugify.mixins",
"compatibilityLevel": "JAVA_25",
"injectors": {
"defaultRequire": 1
},
"plugin": "dev.isxander.debugify.mixinplugin.MixinPlugin",
"mixinextras": {
"minVersion": "0.5.3"
},
"mixins": [
"basic.mc100991.FishingHookMixin",
"basic.mc119754.FireworkRocketEntityMixin",
"basic.mc121706.RangedBowAttackGoalMixin",
"basic.mc121903.MinecraftCommandBlockMixin",
"basic.mc123450.ItemFrameMixin",
"basic.mc129909.ServerPlayerMixin",
"basic.mc131562.ServerGamePacketListenerImplMixin",
"basic.mc132878.ArmorStandMixin",
"basic.mc133218.ServerPlayerMixin",
"basic.mc134110.ChestBlockMixin",
"gameplay.mc136249.LivingEntityMixin",
"basic.mc139041.FishingRodItemMixin",
"basic.mc147659.CatSpawnerMixin",
"basic.mc153010.FoxMixin",
"basic.mc155509.PufferfishMixin",
"basic.mc158900.PlayerListMixin",
"basic.mc159283.DensityFunctionsMixin",
"basic.mc160095.CactusBlockMixin",
"basic.mc168573.BlocksAttacksMixin",
"basic.mc170462.MobEffectsMixin",
"basic.mc176806.RespawnAnchorBlockMixin",
"basic.mc177381.LocateCommandMixin",
"basic.mc179072.SwellGoalMixin",
"basic.mc183990.MobMixin",
"basic.mc187100.EnderDragonMixin",
"basic.mc200418.ZombieVillagerMixin",
"basic.mc201374.CampfireBlockMixin",
"basic.mc202637.FoodPropertiesMixin",
"basic.mc206922.EntityMixin",
"basic.mc206922.ItemEntityMixin",
"basic.mc215530.ServerPlayerMixin",
"basic.mc221257.ShulkerBulletMixin",
"basic.mc223153.BlocksMixin",
"basic.mc224729.ChunkMapMixin",
"basic.mc226961.ExperienceOrbMixin",
"basic.mc227008.EnderManMixin",
"basic.mc227337.ShulkerBulletMixin",
"basic.mc231743.FlowerPotBlockMixin",
"basic.mc232869.StriderMixin",
"basic.mc245394.RaidMixin",
"basic.mc263999.BreakDoorGoalMixin",
"basic.mc264285.CreeperMixin",
"basic.mc264979.SettingsMixin",
"basic.mc267125.PlayerListMixin",
"basic.mc268617.FileUtilMixin",
"basic.mc271899.StructureTemplateMixin",
"basic.mc272431.EnderDragonMixin",
"basic.mc297837.WaypointTransmitterMixin",
"basic.mc298066.LivingEntityMixin",
"basic.mc30391.LivingEntityMixin",
"basic.mc44654.EntityMixin",
"basic.mc7569.RconConsoleSourceMixin",
"basic.mc82263.EnderDragonMixin",
"basic.mc84661.MobEffectsMixin",
"basic.mc88371.DragonLandingPhaseMixin",
"basic.mc89146.ChunkAccessMixin",
"basic.mc93018.AnimalMixin",
"basic.mc94054.WallClimberNavigationMixin",
"errorhandler.CrashReportMixin",
"gameplay.mc8187.TreeFeatureMixin"
]
}
================================================
FILE: src/main/templates/fabric.mod.json
================================================
{
"schemaVersion": 1,
"id": "${mod_id}",
"version": "${mod_version}",
"name": "${mod_name}",
"description": "${mod_description}\n\nCredits:\n${mod_credits}",
"authors": [
"isXander"
],
"contact": {
"homepage": "https://isxander.dev",
"issues": "https://github.com/isXander/Debugify/issues",
"sources": "https://github.com/isXander/Debugify"
},
"license": "LGPLv3",
"environment": "*",
"icon": "debugify.png",
"entrypoints": {
"main": [
"dev.isxander.debugify.Debugify::onInitialize"
],
"client": [
"dev.isxander.debugify.client.DebugifyClient::onInitializeClient"
],
"modmenu": [
"dev.isxander.debugify.client.integrations.ModMenuIntegration"
]
},
"depends": {
"fabricloader": ">=0.18.6",
"minecraft": "~26.1",
"java": ">=25",
"fabric-resource-loader-v0": "*"
},
"recommends": {
"yet_another_config_lib_v3": "*",
"modmenu": "*"
},
"custom": {
"modmenu": {
"links": {
"Patched Bugs": "https://github.com/isXander/Debugify/blob/main/PATCHED.md#unpatched-in-vanilla"
}
}
}
}