diff --git a/src/main/java/net/moonleay/gimbal/mixin/NoClipCameraFixMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NoClipCameraFixMixin.java
deleted file mode 100644
index 55a8882..0000000
--- a/src/main/java/net/moonleay/gimbal/mixin/NoClipCameraFixMixin.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Gimbal
- * Copyright (C) 2024 moonleay
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package net.moonleay.gimbal.mixin;
-
-import net.minecraft.client.MinecraftClient;
-import net.minecraft.client.render.Camera;
-import net.moonleay.gimbal.client.editor.ClientEditor;
-import net.moonleay.gimbal.editor.state.mode.Capability;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Inject;
-import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
-
-@Mixin(Camera.class)
-public class NoClipCameraFixMixin {
-
- @Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true)
- private void fixCameraInNoClip(double desiredCameraDistance, CallbackInfoReturnable cir) {
- if (!ClientEditor.INSTANCE.shouldClient(Capability.NO_CLIP) || (!(MinecraftClient.getInstance().player != null && MinecraftClient.getInstance().player.isCreative()))) {
- return;
- }
- cir.setReturnValue(desiredCameraDistance);
- cir.cancel();
- }
-}
diff --git a/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java b/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java
index fafab39..8e9a80a 100644
--- a/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java
+++ b/src/main/java/net/moonleay/gimbal/mixin/NoClipMixin.java
@@ -19,12 +19,15 @@
package net.moonleay.gimbal.mixin;
import com.mojang.authlib.GameProfile;
+import net.minecraft.client.MinecraftClient;
+import net.minecraft.client.render.Camera;
import net.minecraft.entity.EntityPose;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.world.World;
+import net.moonleay.gimbal.client.editor.ClientEditor;
import net.moonleay.gimbal.editor.ServerEditorManager;
import net.moonleay.gimbal.editor.state.mode.Capability;
import org.spongepowered.asm.mixin.Mixin;
@@ -32,51 +35,72 @@ 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;
import java.util.UUID;
-@Mixin(PlayerEntity.class)
-public abstract class NoClipMixin extends LivingEntity {
- @Shadow public abstract GameProfile getGameProfile();
+public abstract class NoClipMixin {
- @Shadow public abstract PlayerAbilities getAbilities();
-
- @Shadow
- public abstract boolean isCreative();
-
- protected NoClipMixin(EntityType extends LivingEntity> entityType, World world) {
- super(entityType, world);
- } // Server side
-
-
- @Inject(method = "tick", at = @At(value = "FIELD",
- target = "Lnet/minecraft/entity/player/PlayerEntity;noClip:Z", shift = At.Shift.AFTER)
- ) private void enoClip(CallbackInfo ci) {
- if (!this.isCreative())
- return;
- UUID uuid = this.getGameProfile().getId();
-
- if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP)) {
- return; // NoClip is not enabled
+ @Mixin(PlayerEntity.class) // Serverside, allows clipping
+ public static abstract class PlayerEntityMixin extends LivingEntity {
+ protected PlayerEntityMixin(EntityType extends LivingEntity> entityType, World world) {
+ super(entityType, world);
}
- if (!this.getAbilities().flying) {
- return;
+
+ @Shadow
+ public abstract GameProfile getGameProfile();
+
+ @Shadow
+ public abstract PlayerAbilities getAbilities();
+
+ @Shadow
+ public abstract boolean isCreative();
+
+ @Inject(method = "tick", at = @At(value = "FIELD",
+ target = "Lnet/minecraft/entity/player/PlayerEntity;noClip:Z", shift = At.Shift.AFTER)
+ )
+ private void enoClip(CallbackInfo ci) {
+ if (!this.isCreative())
+ return;
+ UUID uuid = this.getGameProfile().getId();
+
+ if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP)) {
+ return; // NoClip is not enabled
+ }
+ if (!this.getAbilities().flying) {
+ return;
+ }
+ // Enable NoClip
+ this.noClip = true;
+ }
+
+ @Inject(method = "updatePose", at = @At("HEAD"))
+ private void onUpdatePose(CallbackInfo ci) {
+ UUID uuid = this.getGameProfile().getId();
+
+ if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP))
+ return; // NoClip is not enabled
+ if (!this.getAbilities().flying)
+ return;
+
+ // Force standing pose in NoClip mode
+
+ this.setPose(EntityPose.STANDING);
}
- // Enable NoClip
- this.noClip = true;
}
- @Inject(method = "updatePose", at = @At("HEAD"))
- private void onUpdatePose(CallbackInfo ci) {
- UUID uuid = this.getGameProfile().getId();
- if (!ServerEditorManager.INSTANCE.shouldPlayer(uuid, Capability.NO_CLIP))
- return; // NoClip is not enabled
- if (!this.getAbilities().flying)
- return;
+ @Mixin(Camera.class) // Clientside, fixes camera
+ public static abstract class CameraMixin {
- // Force standing pose in NoClip mode
-
- this.setPose(EntityPose.STANDING);
+ @Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true)
+ private void fixCameraInNoClip(double desiredCameraDistance, CallbackInfoReturnable cir) {
+ if (!ClientEditor.INSTANCE.shouldClient(Capability.NO_CLIP) || (!(MinecraftClient.getInstance().player != null && MinecraftClient.getInstance().player.isCreative()))) {
+ return;
+ }
+ cir.setReturnValue(desiredCameraDistance);
+ cir.cancel();
+ }
}
+
}
diff --git a/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java
index 8e2a4fa..8a28216 100644
--- a/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java
+++ b/src/main/java/net/moonleay/gimbal/mixin/ReplaceModeMixin.java
@@ -18,50 +18,87 @@
package net.moonleay.gimbal.mixin;
+import net.minecraft.block.BlockState;
import net.minecraft.entity.player.PlayerEntity;
-import net.minecraft.item.ItemPlacementContext;
-import net.minecraft.item.ItemStack;
-import net.minecraft.item.ItemUsageContext;
+import net.minecraft.item.*;
+import net.minecraft.state.property.Property;
import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.moonleay.gimbal.editor.ServerEditorManager;
import net.moonleay.gimbal.editor.state.mode.Capability;
-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 org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
+import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.UUID;
-@Mixin(ItemPlacementContext.class)
-public abstract class ReplaceModeMixin extends ItemUsageContext {
+public abstract class ReplaceModeMixin {
- @Shadow
- protected boolean canReplaceExisting;
+ @Mixin(ItemPlacementContext.class)
+ public static abstract class ItemPlacementContextMixin extends ItemUsageContext {
+ @Shadow
+ protected boolean canReplaceExisting;
- @Mutable
- @Shadow
- @Final
- private BlockPos placementPos;
+ @Mutable
+ @Shadow
+ @Final
+ private BlockPos placementPos;
- public ReplaceModeMixin(PlayerEntity player, Hand hand, BlockHitResult hit) {
- super(player, hand, hit);
+ public ItemPlacementContextMixin(PlayerEntity player, Hand hand, BlockHitResult hit) {
+ super(player, hand, hit);
+ }
+
+ @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/hit/BlockHitResult;)V", at = @At(value = "RETURN"))
+ private void func(World world, PlayerEntity playerEntity, Hand hand, ItemStack itemStack, BlockHitResult blockHitResult, CallbackInfo ci) {
+ if (playerEntity == null)
+ return;
+ UUID id = playerEntity.getGameProfile().getId();
+ if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE))
+ return;
+
+ this.canReplaceExisting = true;
+ this.placementPos = blockHitResult.getBlockPos();
+ }
}
- @Inject(method = "(Lnet/minecraft/world/World;Lnet/minecraft/entity/player/PlayerEntity;Lnet/minecraft/util/Hand;Lnet/minecraft/item/ItemStack;Lnet/minecraft/util/hit/BlockHitResult;)V", at = @At(value = "RETURN"))
- private void func(World world, PlayerEntity playerEntity, Hand hand, ItemStack itemStack, BlockHitResult blockHitResult, CallbackInfo ci) {
- if (playerEntity == null)
- return;
- UUID id = playerEntity.getGameProfile().getId();
- if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE))
- return;
+ @Mixin(BlockItem.class)
+ public static abstract class BlockItemMixin extends Item {
- this.canReplaceExisting = true;
- this.placementPos = blockHitResult.getBlockPos();
+ public BlockItemMixin(Settings settings) {
+ super(settings);
+ }
+
+ @Shadow
+ protected abstract boolean place(ItemPlacementContext context, BlockState state);
+
+ @Redirect(method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BlockItem;place(Lnet/minecraft/item/ItemPlacementContext;Lnet/minecraft/block/BlockState;)Z"))
+ private boolean func(BlockItem instance, ItemPlacementContext context, BlockState state) {
+ if (context.getPlayer() == null)
+ return this.place(context, state);
+ UUID id = context.getPlayer().getGameProfile().getId();
+ if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE))
+ return this.place(context, state);
+ BlockState oldState = context.getWorld().getBlockState(context.getBlockPos());
+ return this.place(context, getTargetBlockState(oldState, instance.getBlock().getDefaultState()));
+ }
+
+ @Unique
+ public BlockState getTargetBlockState(BlockState oldState, BlockState newBlock) {
+ var oldManager = oldState.getBlock().getStateManager();
+ var newManager = newBlock.getBlock().getStateManager();
+ for (var prop : oldManager.getProperties()) {
+ var matchingProp = newManager.getProperty(prop.getName());
+ if (matchingProp != null) {
+ //noinspection rawtypes,unchecked
+ newBlock = newBlock.with((Property) matchingProp, oldState.get(matchingProp));
+ }
+ }
+ return newBlock;
+ }
}
+
}
diff --git a/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java b/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java
deleted file mode 100644
index 255604a..0000000
--- a/src/main/java/net/moonleay/gimbal/mixin/ReplaceStateUpdaterMixin.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Gimbal
- * Copyright (C) 2024 moonleay
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-package net.moonleay.gimbal.mixin;
-
-import net.minecraft.block.BlockState;
-import net.minecraft.item.BlockItem;
-import net.minecraft.item.Item;
-import net.minecraft.item.ItemPlacementContext;
-import net.minecraft.state.property.Property;
-import net.moonleay.gimbal.editor.ServerEditorManager;
-import net.moonleay.gimbal.editor.state.mode.Capability;
-import org.spongepowered.asm.mixin.Mixin;
-import org.spongepowered.asm.mixin.Shadow;
-import org.spongepowered.asm.mixin.Unique;
-import org.spongepowered.asm.mixin.injection.At;
-import org.spongepowered.asm.mixin.injection.Redirect;
-
-import java.util.UUID;
-
-@Mixin(BlockItem.class)
-public abstract class ReplaceStateUpdaterMixin extends Item {
-
- public ReplaceStateUpdaterMixin(Settings settings) {
- super(settings);
- }
-
- @Shadow
- protected abstract boolean place(ItemPlacementContext context, BlockState state);
-
- @Redirect(method = "place(Lnet/minecraft/item/ItemPlacementContext;)Lnet/minecraft/util/ActionResult;", at = @At(value = "INVOKE", target = "Lnet/minecraft/item/BlockItem;place(Lnet/minecraft/item/ItemPlacementContext;Lnet/minecraft/block/BlockState;)Z"))
- private boolean func(BlockItem instance, ItemPlacementContext context, BlockState state) {
- if (context.getPlayer() == null)
- return this.place(context, state);
- UUID id = context.getPlayer().getGameProfile().getId();
- if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE))
- return this.place(context, state);
- BlockState oldState = context.getWorld().getBlockState(context.getBlockPos());
- return this.place(context, getTargetBlockState(oldState, instance.getBlock().getDefaultState()));
- }
-
- @Unique
- public BlockState getTargetBlockState(BlockState oldState, BlockState newBlock) {
- var oldManager = oldState.getBlock().getStateManager();
- var newManager = newBlock.getBlock().getStateManager();
- for (var prop : oldManager.getProperties()) {
- var matchingProp = newManager.getProperty(prop.getName());
- if (matchingProp != null) {
- //noinspection rawtypes,unchecked
- newBlock = newBlock.with((Property) matchingProp, oldState.get(matchingProp));
- }
- }
- return newBlock;
- }
-}
diff --git a/src/main/resources/gimbal.mixins.json b/src/main/resources/gimbal.mixins.json
index b383149..0babedd 100644
--- a/src/main/resources/gimbal.mixins.json
+++ b/src/main/resources/gimbal.mixins.json
@@ -6,15 +6,15 @@
"mixins": [
"ForcePlaceMixin",
"NoBlockUpdatesMixin",
- "NoClipMixin",
- "ReplaceModeMixin",
- "ReplaceStateUpdaterMixin"
+ "NoClipMixin$PlayerEntityMixin",
+ "ReplaceModeMixin$BlockItemMixin",
+ "ReplaceModeMixin$ItemPlacementContextMixin"
],
"client": [
"BulldozerMixin$ClientPlayerInteractionManagerMixin",
"BulldozerMixin$MinecraftClientMixin",
"HudMixin",
- "NoClipCameraFixMixin",
+ "NoClipMixin$CameraMixin",
"NormalModeMixin",
"YouInjectButtonMixin$GameMenuScreenMixin",
"YouInjectButtonMixin$TitleScreenMixin"