mirror of
https://codeberg.org/moonleay/Gimble.git
synced 2024-11-24 15:52:11 +00:00
refactor: combined NoClip and ReplaceMode mixins into one mixin each
Signed-off-by: moonleay <contact@moonleay.net>
This commit is contained in:
parent
4c8404d306
commit
6a89e5683f
5 changed files with 127 additions and 177 deletions
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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<Double> cir) {
|
|
||||||
if (!ClientEditor.INSTANCE.shouldClient(Capability.NO_CLIP) || (!(MinecraftClient.getInstance().player != null && MinecraftClient.getInstance().player.isCreative()))) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
cir.setReturnValue(desiredCameraDistance);
|
|
||||||
cir.cancel();
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,12 +19,15 @@
|
||||||
package net.moonleay.gimbal.mixin;
|
package net.moonleay.gimbal.mixin;
|
||||||
|
|
||||||
import com.mojang.authlib.GameProfile;
|
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.EntityPose;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerAbilities;
|
import net.minecraft.entity.player.PlayerAbilities;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
import net.moonleay.gimbal.client.editor.ClientEditor;
|
||||||
import net.moonleay.gimbal.editor.ServerEditorManager;
|
import net.moonleay.gimbal.editor.ServerEditorManager;
|
||||||
import net.moonleay.gimbal.editor.state.mode.Capability;
|
import net.moonleay.gimbal.editor.state.mode.Capability;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
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.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Mixin(PlayerEntity.class)
|
public abstract class NoClipMixin {
|
||||||
public abstract class NoClipMixin extends LivingEntity {
|
|
||||||
@Shadow public abstract GameProfile getGameProfile();
|
|
||||||
|
|
||||||
@Shadow public abstract PlayerAbilities getAbilities();
|
@Mixin(PlayerEntity.class) // Serverside, allows clipping
|
||||||
|
public static abstract class PlayerEntityMixin extends LivingEntity {
|
||||||
@Shadow
|
protected PlayerEntityMixin(EntityType<? extends LivingEntity> entityType, World world) {
|
||||||
public abstract boolean isCreative();
|
super(entityType, world);
|
||||||
|
|
||||||
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
|
|
||||||
}
|
}
|
||||||
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))
|
@Mixin(Camera.class) // Clientside, fixes camera
|
||||||
return; // NoClip is not enabled
|
public static abstract class CameraMixin {
|
||||||
if (!this.getAbilities().flying)
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Force standing pose in NoClip mode
|
@Inject(method = "clipToSpace", at = @At("HEAD"), cancellable = true)
|
||||||
|
private void fixCameraInNoClip(double desiredCameraDistance, CallbackInfoReturnable<Double> cir) {
|
||||||
this.setPose(EntityPose.STANDING);
|
if (!ClientEditor.INSTANCE.shouldClient(Capability.NO_CLIP) || (!(MinecraftClient.getInstance().player != null && MinecraftClient.getInstance().player.isCreative()))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cir.setReturnValue(desiredCameraDistance);
|
||||||
|
cir.cancel();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,50 +18,87 @@
|
||||||
|
|
||||||
package net.moonleay.gimbal.mixin;
|
package net.moonleay.gimbal.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemPlacementContext;
|
import net.minecraft.item.*;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.state.property.Property;
|
||||||
import net.minecraft.item.ItemUsageContext;
|
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.hit.BlockHitResult;
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.moonleay.gimbal.editor.ServerEditorManager;
|
import net.moonleay.gimbal.editor.ServerEditorManager;
|
||||||
import net.moonleay.gimbal.editor.state.mode.Capability;
|
import net.moonleay.gimbal.editor.state.mode.Capability;
|
||||||
import org.spongepowered.asm.mixin.Final;
|
import org.spongepowered.asm.mixin.*;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
|
||||||
import org.spongepowered.asm.mixin.Shadow;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
@Mixin(ItemPlacementContext.class)
|
public abstract class ReplaceModeMixin {
|
||||||
public abstract class ReplaceModeMixin extends ItemUsageContext {
|
|
||||||
|
|
||||||
@Shadow
|
@Mixin(ItemPlacementContext.class)
|
||||||
protected boolean canReplaceExisting;
|
public static abstract class ItemPlacementContextMixin extends ItemUsageContext {
|
||||||
|
@Shadow
|
||||||
|
protected boolean canReplaceExisting;
|
||||||
|
|
||||||
@Mutable
|
@Mutable
|
||||||
@Shadow
|
@Shadow
|
||||||
@Final
|
@Final
|
||||||
private BlockPos placementPos;
|
private BlockPos placementPos;
|
||||||
|
|
||||||
public ReplaceModeMixin(PlayerEntity player, Hand hand, BlockHitResult hit) {
|
public ItemPlacementContextMixin(PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||||
super(player, hand, hit);
|
super(player, hand, hit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Inject(method = "<init>(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 = "<init>(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"))
|
@Mixin(BlockItem.class)
|
||||||
private void func(World world, PlayerEntity playerEntity, Hand hand, ItemStack itemStack, BlockHitResult blockHitResult, CallbackInfo ci) {
|
public static abstract class BlockItemMixin extends Item {
|
||||||
if (playerEntity == null)
|
|
||||||
return;
|
|
||||||
UUID id = playerEntity.getGameProfile().getId();
|
|
||||||
if (!ServerEditorManager.INSTANCE.shouldPlayer(id, Capability.REPLACE))
|
|
||||||
return;
|
|
||||||
|
|
||||||
this.canReplaceExisting = true;
|
public BlockItemMixin(Settings settings) {
|
||||||
this.placementPos = blockHitResult.getBlockPos();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,15 +6,15 @@
|
||||||
"mixins": [
|
"mixins": [
|
||||||
"ForcePlaceMixin",
|
"ForcePlaceMixin",
|
||||||
"NoBlockUpdatesMixin",
|
"NoBlockUpdatesMixin",
|
||||||
"NoClipMixin",
|
"NoClipMixin$PlayerEntityMixin",
|
||||||
"ReplaceModeMixin",
|
"ReplaceModeMixin$BlockItemMixin",
|
||||||
"ReplaceStateUpdaterMixin"
|
"ReplaceModeMixin$ItemPlacementContextMixin"
|
||||||
],
|
],
|
||||||
"client": [
|
"client": [
|
||||||
"BulldozerMixin$ClientPlayerInteractionManagerMixin",
|
"BulldozerMixin$ClientPlayerInteractionManagerMixin",
|
||||||
"BulldozerMixin$MinecraftClientMixin",
|
"BulldozerMixin$MinecraftClientMixin",
|
||||||
"HudMixin",
|
"HudMixin",
|
||||||
"NoClipCameraFixMixin",
|
"NoClipMixin$CameraMixin",
|
||||||
"NormalModeMixin",
|
"NormalModeMixin",
|
||||||
"YouInjectButtonMixin$GameMenuScreenMixin",
|
"YouInjectButtonMixin$GameMenuScreenMixin",
|
||||||
"YouInjectButtonMixin$TitleScreenMixin"
|
"YouInjectButtonMixin$TitleScreenMixin"
|
||||||
|
|
Loading…
Reference in a new issue