diff --git a/src/main/java/dev/doctor4t/wathe/client/WatheClient.java b/src/main/java/dev/doctor4t/wathe/client/WatheClient.java index f93bdb77..07e7a02d 100644 --- a/src/main/java/dev/doctor4t/wathe/client/WatheClient.java +++ b/src/main/java/dev/doctor4t/wathe/client/WatheClient.java @@ -14,6 +14,8 @@ import dev.doctor4t.wathe.client.gui.TimeRenderer; import dev.doctor4t.wathe.client.model.WatheModelLayers; import dev.doctor4t.wathe.client.model.item.KnifeModelLoadingPlugin; +import dev.doctor4t.wathe.client.particle.HandParticle; +import dev.doctor4t.wathe.client.render.WatheRenderLayers; import dev.doctor4t.wathe.client.render.block_entity.PlateBlockEntityRenderer; import dev.doctor4t.wathe.client.render.block_entity.SmallDoorBlockEntityRenderer; import dev.doctor4t.wathe.client.render.block_entity.WheelBlockEntityRenderer; @@ -26,6 +28,7 @@ import dev.doctor4t.wathe.game.GameConstants; import dev.doctor4t.wathe.game.GameFunctions; import dev.doctor4t.wathe.index.*; +import dev.doctor4t.wathe.item.RevolverItem; import dev.doctor4t.wathe.util.*; import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap; import net.fabricmc.api.ClientModInitializer; @@ -35,6 +38,7 @@ import net.fabricmc.fabric.api.client.model.loading.v1.ModelLoadingPlugin; import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; import net.fabricmc.fabric.api.client.rendering.v1.EntityRendererRegistry; +import net.fabricmc.fabric.api.event.player.UseItemCallback; import net.minecraft.block.Block; import net.minecraft.client.MinecraftClient; import net.minecraft.client.network.AbstractClientPlayerEntity; @@ -53,14 +57,20 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.ItemEntity; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; import net.minecraft.registry.Registries; import net.minecraft.sound.SoundCategory; import net.minecraft.util.Identifier; +import net.minecraft.util.TypedActionResult; +import net.minecraft.util.hit.EntityHitResult; +import net.minecraft.util.hit.HitResult; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import org.lwjgl.glfw.GLFW; import java.util.*; +import java.util.function.Supplier; public class WatheClient implements ClientModInitializer { private static float soundLevel = 0f; @@ -72,6 +82,7 @@ public class WatheClient implements ClientModInitializer { public static PlayerMoodComponent moodComponent; public static final Map PLAYER_ENTRIES_CACHE = Maps.newHashMap(); + public static final Map> GUN_PARTICLE_PROVIDERS = Maps.newHashMap(); public static KeyBinding instinctKeybind; public static float prevInstinctLightLevel = -.04f; @@ -291,6 +302,56 @@ public void onInitializeClient() { GLFW.GLFW_KEY_LEFT_ALT, "category." + Wathe.MOD_ID + ".keybinds" )); + + GUN_PARTICLE_PROVIDERS.put(WatheItems.DERRINGER, + () -> new HandParticle() + .setTexture(Wathe.id("textures/particle/gunshot.png")) + .setPos(0.1f, 0.2f, -0.2f) + .setMaxAge(3) + .setSize(0.5f) + .setVelocity(0f, 0f, 0f) + .setLight(15, 15) + .setAlpha(1f, 0.1f) + .setRenderLayer(WatheRenderLayers::additive) + ); + + GUN_PARTICLE_PROVIDERS.put(WatheItems.REVOLVER, + () -> new HandParticle() + .setTexture(Wathe.id("textures/particle/gunshot.png")) + .setPos(0.1f, 0.275f, -0.2f) + .setMaxAge(3) + .setSize(0.5f) + .setVelocity(0f, 0f, 0f) + .setLight(15, 15) + .setAlpha(1f, 0.1f) + .setRenderLayer(WatheRenderLayers::additive) + ); + + UseItemCallback.EVENT.register((user, world, hand) -> { + ItemStack stack = user.getStackInHand(hand); + if (user.isSpectator() || !(stack.getItem() instanceof RevolverItem gun)) { + return TypedActionResult.pass(stack); + } + + boolean used = gun.hasBeenUsed(stack, user); + + if (world.isClient) { + HitResult collision = gun.getGunTarget(user, stack); + if (collision instanceof EntityHitResult entityHitResult) { + Entity target = entityHitResult.getEntity(); + ClientPlayNetworking.send(new GunShootPayload(target.getId())); + } else { + ClientPlayNetworking.send(new GunShootPayload(-1)); + } + if (!used) { + user.setPitch(user.getPitch() - 4); + if (GUN_PARTICLE_PROVIDERS.containsKey(gun)) { + handParticleManager.spawn(GUN_PARTICLE_PROVIDERS.get(gun).get()); + } + } + } + return TypedActionResult.consume(stack); + }); } public static TrainWorldComponent getTrainComponent() { diff --git a/src/main/java/dev/doctor4t/wathe/client/gui/CrosshairRenderer.java b/src/main/java/dev/doctor4t/wathe/client/gui/CrosshairRenderer.java index 32d16c83..34a93e89 100644 --- a/src/main/java/dev/doctor4t/wathe/client/gui/CrosshairRenderer.java +++ b/src/main/java/dev/doctor4t/wathe/client/gui/CrosshairRenderer.java @@ -13,6 +13,7 @@ import net.minecraft.client.render.RenderTickCounter; import net.minecraft.entity.player.ItemCooldownManager; import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.Identifier; import net.minecraft.util.hit.EntityHitResult; @@ -37,9 +38,8 @@ public static void renderCrosshair(@NotNull MinecraftClient client, @NotNull Cli RenderSystem.defaultBlendFunc(); RenderSystem.disableBlend(); ItemStack mainHandStack = player.getMainHandStack(); - if (mainHandStack.isOf(WatheItems.REVOLVER) && !player.getItemCooldownManager().isCoolingDown(mainHandStack.getItem()) && RevolverItem.getGunTarget(player) instanceof EntityHitResult) { - target = true; - } else if (mainHandStack.isOf(WatheItems.DERRINGER) && !player.getItemCooldownManager().isCoolingDown(mainHandStack.getItem()) && DerringerItem.getGunTarget(player) instanceof EntityHitResult) { + Item item = mainHandStack.getItem(); + if (item instanceof RevolverItem gun && !player.getItemCooldownManager().isCoolingDown(gun) && gun.getGunTarget(player, mainHandStack) instanceof EntityHitResult) { target = true; } else if (mainHandStack.isOf(WatheItems.KNIFE)) { ItemCooldownManager manager = player.getItemCooldownManager(); diff --git a/src/main/java/dev/doctor4t/wathe/client/util/WatheItemTooltips.java b/src/main/java/dev/doctor4t/wathe/client/util/WatheItemTooltips.java index a5995400..09d338c4 100644 --- a/src/main/java/dev/doctor4t/wathe/client/util/WatheItemTooltips.java +++ b/src/main/java/dev/doctor4t/wathe/client/util/WatheItemTooltips.java @@ -1,7 +1,9 @@ package dev.doctor4t.wathe.client.util; import dev.doctor4t.ratatouille.util.TextUtils; +import dev.doctor4t.wathe.index.WatheDataComponentTypes; import dev.doctor4t.wathe.index.WatheItems; +import dev.doctor4t.wathe.item.DerringerItem; import net.fabricmc.fabric.api.client.item.v1.ItemTooltipCallback; import net.minecraft.client.MinecraftClient; import net.minecraft.entity.player.ItemCooldownManager; @@ -20,6 +22,13 @@ public class WatheItemTooltips { public static void addTooltips() { ItemTooltipCallback.EVENT.register((itemStack, tooltipContext, tooltipType, tooltipList) -> { + if (itemStack.getItem() instanceof DerringerItem) { + boolean used = itemStack.getOrDefault(WatheDataComponentTypes.USED, false); + if (used) { + tooltipList.add(Text.translatable("tip.derringer.used").withColor(COOLDOWN_COLOR)); + } + } + addCooldownText(WatheItems.KNIFE, tooltipList, itemStack); addCooldownText(WatheItems.REVOLVER, tooltipList, itemStack); addCooldownText(WatheItems.DERRINGER, tooltipList, itemStack); diff --git a/src/main/java/dev/doctor4t/wathe/item/DerringerItem.java b/src/main/java/dev/doctor4t/wathe/item/DerringerItem.java index 38b0478c..8e38b8d7 100644 --- a/src/main/java/dev/doctor4t/wathe/item/DerringerItem.java +++ b/src/main/java/dev/doctor4t/wathe/item/DerringerItem.java @@ -1,79 +1,19 @@ package dev.doctor4t.wathe.item; -import dev.doctor4t.wathe.Wathe; -import dev.doctor4t.wathe.client.WatheClient; -import dev.doctor4t.wathe.client.particle.HandParticle; -import dev.doctor4t.wathe.client.render.WatheRenderLayers; -import dev.doctor4t.wathe.client.util.WatheItemTooltips; -import dev.doctor4t.wathe.game.GameFunctions; import dev.doctor4t.wathe.index.WatheDataComponentTypes; -import dev.doctor4t.wathe.util.GunShootPayload; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; -import net.minecraft.entity.projectile.ProjectileUtil; import net.minecraft.item.ItemStack; -import net.minecraft.item.tooltip.TooltipType; -import net.minecraft.text.Text; -import net.minecraft.util.Hand; -import net.minecraft.util.TypedActionResult; -import net.minecraft.util.hit.EntityHitResult; -import net.minecraft.util.hit.HitResult; -import net.minecraft.world.World; -import org.jetbrains.annotations.NotNull; - -import java.util.List; public class DerringerItem extends RevolverItem { public DerringerItem(Settings settings) { super(settings); } - @Override - public TypedActionResult use(@NotNull World world, @NotNull PlayerEntity user, Hand hand) { - ItemStack stack = user.getStackInHand(hand); - boolean used = stack.getOrDefault(WatheDataComponentTypes.USED, false); - - if (world.isClient) { - HitResult collision = getGunTarget(user); - if (collision instanceof EntityHitResult entityHitResult) { - Entity target = entityHitResult.getEntity(); - ClientPlayNetworking.send(new GunShootPayload(target.getId())); - } else { - ClientPlayNetworking.send(new GunShootPayload(-1)); - } - if (!used) { - user.setPitch(user.getPitch() - 4); - spawnHandParticle(); - } - } - return TypedActionResult.consume(stack); - } - - public static void spawnHandParticle() { - HandParticle handParticle = new HandParticle() - .setTexture(Wathe.id("textures/particle/gunshot.png")) - .setPos(0.1f, 0.2f, -0.2f) - .setMaxAge(3) - .setSize(0.5f) - .setVelocity(0f, 0f, 0f) - .setLight(15, 15) - .setAlpha(1f, 0.1f) - .setRenderLayer(WatheRenderLayers::additive); - WatheClient.handParticleManager.spawn(handParticle); - } - - @Override - public void appendTooltip(ItemStack stack, TooltipContext context, List tooltip, TooltipType type) { - Boolean used = stack.getOrDefault(WatheDataComponentTypes.USED, false); - if (used) { - tooltip.add(Text.translatable("tip.derringer.used").withColor(WatheItemTooltips.COOLDOWN_COLOR)); - } - - super.appendTooltip(stack, context, tooltip, type); + public boolean hasBeenUsed(ItemStack stack, PlayerEntity user) { + return stack.getOrDefault(WatheDataComponentTypes.USED, false); } - public static HitResult getGunTarget(PlayerEntity user) { - return ProjectileUtil.getCollision(user, entity -> entity instanceof PlayerEntity player && GameFunctions.isPlayerAliveAndSurvival(player), 7f); + public float getRange(PlayerEntity user, ItemStack stack) { + return 7f; } } diff --git a/src/main/java/dev/doctor4t/wathe/item/RevolverItem.java b/src/main/java/dev/doctor4t/wathe/item/RevolverItem.java index 02d884d6..fc05d5ef 100644 --- a/src/main/java/dev/doctor4t/wathe/item/RevolverItem.java +++ b/src/main/java/dev/doctor4t/wathe/item/RevolverItem.java @@ -1,20 +1,12 @@ package dev.doctor4t.wathe.item; -import dev.doctor4t.wathe.Wathe; -import dev.doctor4t.wathe.client.WatheClient; -import dev.doctor4t.wathe.client.particle.HandParticle; -import dev.doctor4t.wathe.client.render.WatheRenderLayers; import dev.doctor4t.wathe.game.GameFunctions; -import dev.doctor4t.wathe.util.GunShootPayload; -import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking; -import net.minecraft.entity.Entity; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.projectile.ProjectileUtil; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.Hand; import net.minecraft.util.TypedActionResult; -import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.hit.HitResult; import net.minecraft.world.World; import org.jetbrains.annotations.NotNull; @@ -26,34 +18,23 @@ public RevolverItem(Settings settings) { @Override public TypedActionResult use(@NotNull World world, @NotNull PlayerEntity user, Hand hand) { - if (world.isClient) { - HitResult collision = getGunTarget(user); - if (collision instanceof EntityHitResult entityHitResult) { - Entity target = entityHitResult.getEntity(); - ClientPlayNetworking.send(new GunShootPayload(target.getId())); - } else { - ClientPlayNetworking.send(new GunShootPayload(-1)); - } - user.setPitch(user.getPitch() - 4); - spawnHandParticle(); - } - return TypedActionResult.consume(user.getStackInHand(hand)); + ItemStack stack = user.getStackInHand(hand); + return TypedActionResult.consume(stack); } - public static void spawnHandParticle() { - HandParticle handParticle = new HandParticle() - .setTexture(Wathe.id("textures/particle/gunshot.png")) - .setPos(0.1f, 0.275f, -0.2f) - .setMaxAge(3) - .setSize(0.5f) - .setVelocity(0f, 0f, 0f) - .setLight(15, 15) - .setAlpha(1f, 0.1f) - .setRenderLayer(WatheRenderLayers::additive); - WatheClient.handParticleManager.spawn(handParticle); + public boolean hasBeenUsed(ItemStack stack, PlayerEntity user) { + return false; } - public static HitResult getGunTarget(PlayerEntity user) { - return ProjectileUtil.getCollision(user, entity -> entity instanceof PlayerEntity player && GameFunctions.isPlayerAliveAndSurvival(player), 15f); + public static HitResult getGunTarget(PlayerEntity user, float range) { + return ProjectileUtil.getCollision(user, entity -> entity instanceof PlayerEntity player && GameFunctions.isPlayerAliveAndSurvival(player), range); + } + + public final HitResult getGunTarget(PlayerEntity user, ItemStack stack) { + return getGunTarget(user, this.getRange(user, stack)); + } + + public float getRange(PlayerEntity user, ItemStack stack) { + return 15f; } } \ No newline at end of file diff --git a/src/main/java/dev/doctor4t/wathe/mixin/client/self/NoteItemMixin.java b/src/main/java/dev/doctor4t/wathe/mixin/client/self/NoteItemMixin.java index fc15c4a6..d23a623c 100644 --- a/src/main/java/dev/doctor4t/wathe/mixin/client/self/NoteItemMixin.java +++ b/src/main/java/dev/doctor4t/wathe/mixin/client/self/NoteItemMixin.java @@ -16,6 +16,9 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +/** + * @author SkyNotTheLimit + */ @Environment(EnvType.CLIENT) @Mixin(NoteItem.class) public class NoteItemMixin { diff --git a/src/main/java/dev/doctor4t/wathe/util/GunShootPayload.java b/src/main/java/dev/doctor4t/wathe/util/GunShootPayload.java index 4bec89ed..d4de5c36 100644 --- a/src/main/java/dev/doctor4t/wathe/util/GunShootPayload.java +++ b/src/main/java/dev/doctor4t/wathe/util/GunShootPayload.java @@ -9,6 +9,7 @@ import dev.doctor4t.wathe.index.WatheItems; import dev.doctor4t.wathe.index.WatheSounds; import dev.doctor4t.wathe.index.tag.WatheItemTags; +import dev.doctor4t.wathe.item.RevolverItem; import net.fabricmc.fabric.api.networking.v1.PlayerLookup; import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking; import net.minecraft.entity.ItemEntity; @@ -23,6 +24,8 @@ import net.minecraft.sound.SoundCategory; import org.jetbrains.annotations.NotNull; +import java.util.function.Predicate; + public record GunShootPayload(int target) implements CustomPayload { public static final Id ID = new Id<>(Wathe.id("gunshoot")); public static final PacketCodec CODEC = PacketCodec.tuple(PacketCodecs.INTEGER, GunShootPayload::target, GunShootPayload::new); @@ -56,7 +59,14 @@ public void receive(@NotNull GunShootPayload payload, ServerPlayNetworking.@NotN if (!player.isCreative()) mainHandStack.set(WatheDataComponentTypes.USED, true); } - if (player.getServerWorld().getEntityById(payload.target()) instanceof PlayerEntity target && target.distanceTo(player) < 65.0) { + Predicate distancePredicate; + if (mainHandStack.getItem() instanceof RevolverItem gun) { + distancePredicate = target -> player.distanceTo(target) < gun.getRange(player, mainHandStack) + 1.5; + } else { + distancePredicate = target -> player.distanceTo(target) < 65; + } + + if (player.getServerWorld().getEntityById(payload.target()) instanceof PlayerEntity target && player.canSee(target) && distancePredicate.test(target)) { GameWorldComponent game = GameWorldComponent.KEY.get(player.getWorld()); Item revolver = WatheItems.REVOLVER;