forradalom es szabadsagharc: island structure, update ak47, rework revolver

This commit is contained in:
2026-03-15 17:25:45 +01:00
parent 87e4c03db6
commit 351c41c028
47 changed files with 837 additions and 246 deletions

View File

@@ -0,0 +1,5 @@
package dev.tggamesyt.szar.client;
public class AK47InputState {
public static boolean mouseHeld = false;
}

View File

@@ -0,0 +1,121 @@
package dev.tggamesyt.szar.client;
import dev.tggamesyt.szar.RevolverItem;
import dev.tggamesyt.szar.Szar;
import net.fabricmc.fabric.api.client.rendering.v1.HudRenderCallback;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.item.ItemStack;
public class RevolverHudRenderer {
private static final int RADIUS = 30;
private static final int CX_FROM_RIGHT = 80;
private static final int CY_FROM_BOTTOM = 80;
private static final float SNAP_SPEED = 0.15F;
private static final float SLIDE_SPEED = 0.18F;
// How far off screen to the right the barrel slides when closed
private static final int SLIDE_DISTANCE = 150;
private static float displayAngle = 0F;
private static int lastKnownChamber = 0;
// 0 = fully hidden (off screen right), 1 = fully visible
private static float slideProgress = 0F;
public static void register() {
HudRenderCallback.EVENT.register(RevolverHudRenderer::render);
}
public static void tick(int currentChamber, float tickDelta) {
float degreesPerChamber = 360F / RevolverItem.CHAMBERS;
float targetAngle = -currentChamber * degreesPerChamber;
if (currentChamber != lastKnownChamber) {
lastKnownChamber = currentChamber;
}
float delta = targetAngle - displayAngle;
while (delta > 180F) delta -= 360F;
while (delta < -180F) delta += 360F;
displayAngle += delta * SNAP_SPEED * tickDelta;
// Slide in/out
float targetSlide = RevolverHudState.isOpen ? 1F : 0F;
slideProgress += (targetSlide - slideProgress) * SLIDE_SPEED * tickDelta;
}
public static void render(DrawContext context, float tickDelta) {
MinecraftClient client = MinecraftClient.getInstance();
if (client.player == null) return;
ItemStack stack = client.player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
int current = RevolverItem.getCurrentChamber(stack);
tick(current, tickDelta);
// Don't render at all if fully hidden
if (slideProgress < 0.01F) return;
boolean[] chambers = RevolverItem.getChambers(stack);
int baseCx = context.getScaledWindowWidth() - CX_FROM_RIGHT;
int cy = context.getScaledWindowHeight() - CY_FROM_BOTTOM;
// Slide offset: 0 = off screen right, 1 = in place
int slideOffset = (int)((1F - slideProgress) * SLIDE_DISTANCE);
int cx = baseCx + slideOffset;
// Draw translucent background circle
int circleAlpha = (int)(slideProgress * 120); // max alpha 120 (~47% opacity)
drawCircle(context, cx, cy, RADIUS + 8, circleAlpha);
// Draw chamber dots
for (int i = 0; i < RevolverItem.CHAMBERS; i++) {
float baseAngle = (float)(-Math.PI / 2.0)
+ i * (float)(2.0 * Math.PI / RevolverItem.CHAMBERS)
+ (float)Math.toRadians(displayAngle);
int x = (int)(cx + Math.cos(baseAngle) * RADIUS);
int y = (int)(cy + Math.sin(baseAngle) * RADIUS);
boolean isCurrent = i == current;
int size = isCurrent ? 6 : 4;
int color;
if (isCurrent) {
color = (int)(slideProgress * 255) << 24 | (chambers[i] ? 0x0000FF00 : 0x00FF4444);
} else {
color = (int)(slideProgress * 255) << 24 | (chambers[i] ? 0x00FFFFFF : 0x00555555);
}
context.fill(x - size / 2, y - size / 2, x + size / 2, y + size / 2, color);
}
// Center dot
int dotAlpha = (int)(slideProgress * 255);
context.fill(cx - 2, cy - 2, cx + 2, cy + 2, dotAlpha << 24 | 0x00AAAAAA);
}
private static void drawCircle(DrawContext context, int cx, int cy, int radius, int alpha) {
// Approximate circle with filled quads at each degree
int steps = 64;
int color = alpha << 24 | 0x00222222;
for (int i = 0; i < steps; i++) {
float a1 = (float)(i * 2 * Math.PI / steps);
float a2 = (float)((i + 1) * 2 * Math.PI / steps);
// Draw thin triangle slice as a quad
int x1 = (int)(cx + Math.cos(a1) * radius);
int y1 = (int)(cy + Math.sin(a1) * radius);
int x2 = (int)(cx + Math.cos(a2) * radius);
int y2 = (int)(cy + Math.sin(a2) * radius);
// Fill triangle from center to edge
context.fill(Math.min(x1, x2) - 1, Math.min(y1, y2) - 1,
Math.max(x1, x2) + 1, Math.max(y1, y2) + 1, color);
}
// Fill center solid
context.fill(cx - radius, cy - radius, cx + radius, cy + radius, color);
}
}

View File

@@ -0,0 +1,8 @@
package dev.tggamesyt.szar.client;
public class RevolverHudState {
public static boolean isOpen = false;
public static boolean isSpinning = false;
public static float spinAngle = 0F;
public static float spinVelocity = 0F;
}

View File

@@ -0,0 +1,29 @@
package dev.tggamesyt.szar.client;
import dev.tggamesyt.szar.RevolverItem;
public class RevolverHudTicker {
private static final float DECELERATION = 0.88F;
private static final float STOP_THRESHOLD = 0.2F;
public static void tick() {
if (!RevolverHudState.isSpinning) return;
RevolverHudState.spinAngle += RevolverHudState.spinVelocity;
RevolverHudState.spinVelocity *= DECELERATION;
if (Math.abs(RevolverHudState.spinVelocity) < STOP_THRESHOLD) {
RevolverHudState.isSpinning = false;
RevolverHudState.spinAngle = 0F;
RevolverHudState.spinVelocity = 0F;
}
}
public static void startSpin(int steps) {
// Spin in the positive direction, one full rotation per step minimum
RevolverHudState.spinAngle = 0F;
RevolverHudState.spinVelocity = steps * (360F / RevolverItem.CHAMBERS) * 0.25F;
RevolverHudState.isSpinning = true;
}
}

View File

@@ -1,132 +0,0 @@
package dev.tggamesyt.szar.client;
import dev.tggamesyt.szar.RevolverItem;
import dev.tggamesyt.szar.Szar;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gui.DrawContext;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.widget.ButtonWidget;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.text.Text;
public class RevolverScreen extends Screen {
private final ItemStack revolverStack;
private static final int[][] SLOT_OFFSETS = {
{ 0, -50}, {43, -25}, {43, 25},
{ 0, 50}, {-43, 25}, {-43,-25}
};
public RevolverScreen(ItemStack stack) {
super(Text.literal("Revolver"));
this.revolverStack = stack;
}
@Override
protected void init() {
int cx = this.width / 2;
int cy = this.height / 2;
boolean[] chambers = RevolverItem.getChambers(revolverStack);
for (int i = 0; i < RevolverItem.CHAMBERS; i++) {
final int index = i;
int bx = cx + SLOT_OFFSETS[i][0] - 15;
int by = cy + SLOT_OFFSETS[i][1] - 10;
this.addDrawableChild(ButtonWidget.builder(
getChamberText(index, chambers),
btn -> {
PlayerEntity player = MinecraftClient.getInstance().player;
if (player == null) return;
boolean[] current = RevolverItem.getChambers(revolverStack);
if (current[index]) {
// Optimistically update client visual
current[index] = false;
RevolverItem.setChambers(revolverStack, current);
} else {
// Check if player has bullet before sending — purely for visual feedback
boolean hasBullet = false;
for (int o = 0; o < player.getInventory().size(); o++) {
ItemStack s = player.getInventory().getStack(o);
if (!s.isEmpty() && s.isOf(Szar.BULLET_ITEM)) {
hasBullet = true;
break;
}
}
if (!hasBullet) return; // don't even send packet
current[index] = true;
RevolverItem.setChambers(revolverStack, current);
}
// Send to server — server does the actual inventory changes
PacketByteBuf buf = PacketByteBufs.create();
buf.writeInt(index);
buf.writeBoolean(!current[index]); // wasLoaded = what it WAS before the flip
ClientPlayNetworking.send(Szar.REVOLVER_CHAMBER_CHANGE, buf);
clearChildren();
init();
}
).dimensions(bx, by, 30, 20).build());
}
this.addDrawableChild(ButtonWidget.builder(
Text.literal("Done"),
btn -> this.close()
).dimensions(cx - 40, cy + 75, 80, 20).build());
}
private boolean takeBullet(PlayerEntity player) {
for (int i = 0; i < player.getInventory().size(); i++) {
ItemStack s = player.getInventory().getStack(i);
if (!s.isEmpty() && s.isOf(Szar.BULLET_ITEM)) {
s.decrement(1);
return true;
}
}
return false;
}
private Text getChamberText(int i, boolean[] chambers) {
int current = RevolverItem.getCurrentChamber(revolverStack);
String prefix = (i == current) ? "" : " ";
return Text.literal(prefix + (chambers[i] ? "" : ""));
}
@Override
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
this.renderBackground(context);
context.drawCenteredTextWithShadow(this.textRenderer,
Text.literal("Load Revolver"), this.width / 2, this.height / 2 - 70, 0xFFFFFF);
context.drawCenteredTextWithShadow(this.textRenderer,
Text.literal("► = current chamber"), this.width / 2, this.height / 2 - 58, 0xAAAAAA);
super.render(context, mouseX, mouseY, delta);
}
@Override
public boolean shouldPause() {
return false;
}
private void syncToServer() {
boolean[] chambers = RevolverItem.getChambers(revolverStack);
int current = RevolverItem.getCurrentChamber(revolverStack);
PacketByteBuf buf = PacketByteBufs.create();
for (int i = 0; i < RevolverItem.CHAMBERS; i++) {
buf.writeBoolean(chambers[i]);
}
buf.writeInt(current);
ClientPlayNetworking.send(Szar.REVOLVER_SYNC, buf);
}
}

View File

@@ -3,6 +3,7 @@ package dev.tggamesyt.szar.client;
import com.mojang.blaze3d.systems.RenderSystem;
import dev.tggamesyt.szar.*;
import dev.tggamesyt.szar.ServerCosmetics.NameType;
import dev.tggamesyt.szar.client.mixin.RevolverAttackMixin;
import net.fabricmc.api.ClientModInitializer;
import net.fabricmc.fabric.api.blockrenderlayer.v1.BlockRenderLayerMap;
import net.fabricmc.fabric.api.client.command.v2.ClientCommandRegistrationCallback;
@@ -91,6 +92,20 @@ public class SzarClient implements ClientModInitializer {
);
@Override
public void onInitializeClient() {
ClientTickEvents.START_CLIENT_TICK.register(client -> {
if (!AK47InputState.mouseHeld) return;
if (client.player == null || client.currentScreen != null) {
AK47InputState.mouseHeld = false;
return;
}
ItemStack stack = client.player.getMainHandStack();
if (!stack.isOf(Szar.AK47)) {
AK47InputState.mouseHeld = false;
return;
}
if (!client.player.isUsingItem()) return;
ClientPlayNetworking.send(Szar.AK47_SHOOT, PacketByteBufs.create());
});
BulletDecalRenderer.register();
// In ClientModInitializer:
ClientPlayNetworking.registerGlobalReceiver(Szar.BULLET_IMPACT, (client, handler, buf, sender) -> {
@@ -103,17 +118,58 @@ public class SzarClient implements ClientModInitializer {
BulletDecalStore.add(new Vec3d(x, y, z), face);
});
});
// Then in a ClientTickEvents.END_CLIENT_TICK:
RevolverHudRenderer.register();
ClientTickEvents.END_CLIENT_TICK.register(client -> {
if (SPIN_KEY.wasPressed() && client.player != null) {
ItemStack stack = client.player.getMainHandStack();
if (stack.isOf(Szar.REVOLVER)) {
// Send spin packet to server
ClientPlayNetworking.send(Szar.REVOLVER_SPIN,
PacketByteBufs.create());
RevolverHudTicker.tick();
if (client.player == null) return;
ItemStack stack = client.player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) {
RevolverHudState.isOpen = false;
return;
}
if (SPIN_KEY.wasPressed()) {
if (client.player.isSneaking()) {
// Shift+R: toggle open/close
RevolverHudState.isOpen = !RevolverHudState.isOpen;
} else if (RevolverHudState.isOpen) {
// R while open: load/unload current chamber then advance
boolean[] chambers = RevolverItem.getChambers(stack);
int current = RevolverItem.getCurrentChamber(stack);
PacketByteBuf buf = PacketByteBufs.create();
buf.writeInt(current);
buf.writeBoolean(chambers[current]); // wasLoaded
ClientPlayNetworking.send(Szar.REVOLVER_CHAMBER_CHANGE, buf);
} else {
// R while closed and not sneaking: spin
ClientPlayNetworking.send(Szar.REVOLVER_SPIN, PacketByteBufs.create());
// Animation starts when server responds with REVOLVER_SPIN_RESULT
}
}
});
ClientPlayNetworking.registerGlobalReceiver(Szar.REVOLVER_STATE_SYNC, (client, handler, buf, sender) -> {
boolean[] chambers = new boolean[RevolverItem.CHAMBERS];
for (int i = 0; i < RevolverItem.CHAMBERS; i++) {
chambers[i] = buf.readBoolean();
}
int current = buf.readInt();
client.execute(() -> {
if (client.player == null) return;
ItemStack stack = client.player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
RevolverItem.setChambers(stack, chambers);
RevolverItem.setCurrentChamber(stack, current);
});
});
ClientPlayNetworking.registerGlobalReceiver(Szar.REVOLVER_SPIN_RESULT, (client2, handler, buf, sender) -> {
int steps = buf.readInt();
client2.execute(() -> RevolverHudTicker.startSpin(steps));
});
ClientPlayConnectionEvents.JOIN.register((handler, sender, client) -> {
PacketByteBuf buf = PacketByteBufs.create();

View File

@@ -1,5 +1,6 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.AK47Item;
import dev.tggamesyt.szar.Joint;
import dev.tggamesyt.szar.RevolverItem;
import net.minecraft.client.network.AbstractClientPlayerEntity;
@@ -77,11 +78,46 @@ public abstract class HeldItemRendererMixin {
matrices.push();
// Center in middle of screen regardless of hand
if (!player.isSneaking()) {
matrices.translate(
isMainHand ? -0.18F : 0.18F,
-0.5F,
-0.5F
);
} else {
matrices.translate(
isMainHand ? 1F : -1F,
-0.2F,
-0.5F
);
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(isMainHand ? 100.0F : -100F));
}
matrices.translate(0.0F, equipProgress * -0.6F, 0.0F);
HeldItemRenderer self = (HeldItemRenderer) (Object) this;
self.renderItem(player, item,
isRight ? ModelTransformationMode.FIRST_PERSON_RIGHT_HAND : ModelTransformationMode.FIRST_PERSON_LEFT_HAND,
!isRight, matrices, vertexConsumers, light);
matrices.pop();
ci.cancel();
}
if (item.getItem() instanceof AK47Item
&& player.isUsingItem()
&& player.getActiveHand() == hand) {
boolean isMainHand = hand == Hand.MAIN_HAND;
Arm arm = isMainHand ? player.getMainArm() : player.getMainArm().getOpposite();
boolean isRight = arm == Arm.RIGHT;
matrices.push();
// Center in middle of screen regardless of hand
matrices.translate(
isMainHand ? -0.18F : 0.18F,
0.00F,
-0.5F,
-0.5F
-1.0F
);
matrices.translate(0.0F, equipProgress * -0.6F, 0.0F);

View File

@@ -1,13 +1,15 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.Szar;
import dev.tggamesyt.szar.client.RevolverScreen;
import dev.tggamesyt.szar.client.AK47InputState;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse;
import net.minecraft.item.ItemStack;
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.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -19,20 +21,24 @@ public class RevolverAttackMixin {
private void onMouseButton(long window, int button, int action, int mods, CallbackInfo ci) {
MinecraftClient client = MinecraftClient.getInstance();
if (client.player == null) return;
if (client.currentScreen != null) return; // let screens handle their own clicks
if (button != 0 || action != 1) return; // only left click press
if (client.currentScreen != null) return;
if (button != 0) return;
ItemStack stack = client.player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
ci.cancel(); // cancel vanilla handling entirely
if (stack.isOf(Szar.REVOLVER)) {
if (action != 1) return;
ci.cancel();
if (client.player.isUsingItem()) {
ClientPlayNetworking.send(Szar.REVOLVER_SHOOT, PacketByteBufs.create());
}
return;
}
if (!client.player.isUsingItem()) {
// Not aiming — open loading screen
client.execute(() -> client.setScreen(new RevolverScreen(stack)));
} else {
// Aiming — shoot
ClientPlayNetworking.send(Szar.REVOLVER_SHOOT, PacketByteBufs.create());
if (stack.isOf(Szar.AK47)) {
ci.cancel();
if (action == 1) AK47InputState.mouseHeld = true;
if (action == 0) AK47InputState.mouseHeld = false;
}
}
}

View File

@@ -0,0 +1,35 @@
package dev.tggamesyt.szar.client.mixin;
import dev.tggamesyt.szar.Szar;
import dev.tggamesyt.szar.client.RevolverHudState;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.Mouse;
import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf;
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(Mouse.class)
public class RevolverScrollMixin {
@Inject(method = "onMouseScroll", at = @At("HEAD"), cancellable = true)
private void onScroll(long window, double horizontal, double vertical, CallbackInfo ci) {
MinecraftClient client = MinecraftClient.getInstance();
if (client.player == null || client.currentScreen != null) return;
ItemStack stack = client.player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
if (!RevolverHudState.isOpen) return;
ci.cancel(); // don't scroll hotbar
int direction = vertical > 0 ? 1 : -1;
PacketByteBuf buf = PacketByteBufs.create();
buf.writeInt(direction);
ClientPlayNetworking.send(Szar.REVOLVER_SCROLL, buf);
}
}

View File

@@ -20,6 +20,7 @@
"RadiatedItemRendererMixin",
"RadiationHeartMixin",
"RevolverAttackMixin",
"RevolverScrollMixin",
"ScreenFlipMixin",
"SplashOverlayMixin",
"TGcapeMixin",

View File

@@ -1,11 +1,8 @@
package dev.tggamesyt.szar;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
import net.minecraft.util.Hand;
import net.minecraft.util.TypedActionResult;
import net.minecraft.util.UseAction;
@@ -17,25 +14,7 @@ public class AK47Item extends Item {
super(settings);
}
@Override
public void inventoryTick(ItemStack stack, World world, Entity entity, int slot, boolean selected) {
if (!(entity instanceof PlayerEntity player)) return;
if (!selected) return;
if (!player.isUsingItem()) return;
if (world.isClient) return;
if (player.getItemCooldownManager().isCoolingDown(this)) return;
if (!consumeAmmo(player)) return;
player.getWorld().playSound(null, player.getBlockPos(),
SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.PLAYERS, 0.5f, 1.8f);
BulletEntity bullet = new BulletEntity(world, player);
bullet.setVelocity(player, player.getPitch(), player.getYaw(), 0f, 4.5f, 1.0f);
world.spawnEntity(bullet);
player.getItemCooldownManager().set(this, 2); // fire rate
}
private boolean consumeAmmo(PlayerEntity player) {
public boolean consumeAmmo(PlayerEntity player) {
if (player.getAbilities().creativeMode) return true;
for (int i = 0; i < player.getInventory().size(); i++) {
@@ -50,7 +29,7 @@ public class AK47Item extends Item {
@Override
public UseAction getUseAction(ItemStack stack) {
return UseAction.NONE;
return UseAction.BOW; // raises arm
}
@Override

View File

@@ -3,6 +3,7 @@ package dev.tggamesyt.szar;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.PlayerLookup;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
@@ -13,14 +14,20 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory;
import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.hit.EntityHitResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
public class BulletEntity extends ThrownItemEntity {
private static final float BASE_DAMAGE = 13.0F;
private static final float PIERCE_BREAK_THRESHOLD = 0.4F;
private float pierceValue = 1.0F;
private int stillTicks = 0;
private double lastX, lastY, lastZ;
@@ -47,7 +54,7 @@ public class BulletEntity extends ThrownItemEntity {
if (movedSq < 0.0001) {
stillTicks++;
if (stillTicks >= 3) { // discard after 3 ticks of no movement
if (stillTicks >= 3) {
discard();
return;
}
@@ -79,20 +86,60 @@ public class BulletEntity extends ThrownItemEntity {
this,
livingOwner
);
target.damage(source, 13.0F);
// Damage scaled by remaining pierce value
target.damage(source, BASE_DAMAGE * pierceValue);
}
discard();
// Don't discard — bullet continues through entities
// But reduce pierce value a bit for entity hits
pierceValue -= 0.3F;
if (pierceValue <= 0) {
discard();
}
}
@Override
protected void onBlockHit(net.minecraft.util.hit.BlockHitResult hit) {
super.onBlockHit(hit);
// Use exact hit position + nudge along face normal to sit on surface
protected void onBlockHit(BlockHitResult hit) {
if (getWorld().isClient) return;
BlockPos blockPos = hit.getBlockPos();
BlockState state = getWorld().getBlockState(blockPos);
Vec3d pos = hit.getPos();
Direction face = hit.getSide();
spawnImpact(pos, face);
discard();
float resistance = state.getBlock().getBlastResistance();
if (!state.isAir()) {
pierceValue -= resistance;
}
if (pierceValue <= 0) {
// Bullet stopped — spawn impact and discard
spawnImpact(pos, face);
discard();
return;
}
if (resistance < PIERCE_BREAK_THRESHOLD && !state.isAir()) {
// Break the block
if (getWorld() instanceof ServerWorld serverWorld) {
// Play break sound
getWorld().playSound(
null,
blockPos,
state.getSoundGroup().getBreakSound(),
SoundCategory.BLOCKS,
1.0F,
1.0F
);
serverWorld.breakBlock(blockPos, true, getOwner());
}
// Bullet continues — don't call super, don't discard
} else {
// Block too strong to break — bullet stops here
spawnImpact(pos, face);
discard();
}
}
private void spawnImpact(Vec3d pos, Direction face) {

View File

@@ -3,6 +3,7 @@ package dev.tggamesyt.szar;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.ai.goal.Goal;
import net.minecraft.entity.ai.goal.LookAroundGoal;
import net.minecraft.entity.ai.goal.MeleeAttackGoal;
@@ -13,10 +14,21 @@ import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.mob.PathAwareEntity;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.registry.RegistryKey;
import net.minecraft.registry.RegistryKeys;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.structure.StructureStart;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.World;
import net.minecraft.world.gen.structure.Structure;
import java.util.EnumSet;
import java.util.List;
import java.util.Optional;
public class EpsteinEntity extends PathAwareEntity implements Arrestable {
@@ -24,6 +36,7 @@ public class EpsteinEntity extends PathAwareEntity implements Arrestable {
public EpsteinEntity(EntityType<? extends PathAwareEntity> type, World world) {
super(type, world);
this.setPersistent();
}
@Override

View File

@@ -13,7 +13,10 @@ import net.minecraft.entity.mob.MobEntity;
import net.minecraft.entity.mob.PathAwareEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.item.Items;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.nbt.NbtString;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
@@ -241,6 +244,15 @@ public class IslamTerrorist extends PathAwareEntity implements Arrestable{
}
}
@Override
protected void dropLoot(DamageSource source, boolean causedByPlayer) {
Random r = new Random();
int number = r.nextInt(3) + 1;
ItemStack powder = new ItemStack(Items.GUNPOWDER, number);
this.dropStack(powder);
}
// ================= DAMAGE =================

View File

@@ -0,0 +1,57 @@
package dev.tggamesyt.szar;
import com.mojang.serialization.Codec;
import net.minecraft.structure.StructurePlacementData;
import net.minecraft.util.BlockRotation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.Heightmap;
import net.minecraft.world.gen.structure.Structure;
import net.minecraft.world.gen.structure.StructureType;
import java.util.Optional;
public class IslandStructure extends Structure {
public static final Codec<IslandStructure> CODEC =
Structure.createCodec(IslandStructure::new);
public IslandStructure(Config config) {
super(config);
}
@Override
protected Optional<StructurePosition> getStructurePosition(Context context) {
ChunkPos chunkPos = context.chunkPos();
int x = chunkPos.getCenterX();
int z = chunkPos.getCenterZ();
// Find water surface — scan down from world height to sea level
int seaLevel = context.chunkGenerator().getSeaLevel();
int surfaceY = context.chunkGenerator().getHeightInGround(
x, z,
Heightmap.Type.OCEAN_FLOOR_WG,
context.world(),
context.noiseConfig()
);
// Must be underwater (ocean floor below sea level)
if (surfaceY >= seaLevel - 2) return Optional.empty();
// Place structure at sea level + 1 so it sits on the water surface
BlockPos pos = new BlockPos(x, seaLevel + 1, z);
StructurePlacementData placement = new StructurePlacementData()
.setRotation(BlockRotation.random(context.random()));
return Structure.getStructurePosition(context, Heightmap.Type.WORLD_SURFACE_WG, collector ->
collector.addPiece(new IslandStructurePiece(context, pos, BlockPos.ORIGIN, placement))
);
}
@Override
public StructureType<?> getType() {
return Szar.ISLAND_TYPE;
}
}

View File

@@ -0,0 +1,87 @@
package dev.tggamesyt.szar;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.structure.SimpleStructurePiece;
import net.minecraft.structure.StructureContext;
import net.minecraft.structure.StructurePlacementData;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.math.random.Random;
import net.minecraft.world.ServerWorldAccess;
import net.minecraft.world.StructureWorldAccess;
import net.minecraft.world.gen.StructureAccessor;
import net.minecraft.world.gen.chunk.ChunkGenerator;
import net.minecraft.world.gen.structure.Structure;
public class IslandStructurePiece extends SimpleStructurePiece {
private static final Identifier TEMPLATE_ID =
new Identifier(Szar.MOD_ID, "island");
/* ===== NORMAL CONSTRUCTOR (Worldgen) ===== */
public IslandStructurePiece(
Structure.Context context,
BlockPos pos,
BlockPos origin,
StructurePlacementData placement
) {
super(
Szar.ISLAND_PIECE,
0,
context.structureTemplateManager(),
TEMPLATE_ID,
TEMPLATE_ID.toString(),
placement,
pos
);
}
/* ===== NBT CONSTRUCTOR (Chunk Save/Load) ===== */
public IslandStructurePiece(StructureContext context, NbtCompound nbt) {
super(
Szar.ISLAND_PIECE,
nbt,
context.structureTemplateManager(),
identifier -> new StructurePlacementData()
);
}
/* ===== Metadata Handler (DATA structure blocks) ===== */
@Override
protected void handleMetadata(
String metadata,
BlockPos pos,
ServerWorldAccess world,
Random random,
BlockBox boundingBox
) {
}
@Override
public void generate(StructureWorldAccess world, StructureAccessor structureAccessor,
ChunkGenerator chunkGenerator, Random random,
BlockBox chunkBox, ChunkPos chunkPos, BlockPos pivot) {
// This actually places the structure blocks
super.generate(world, structureAccessor, chunkGenerator, random, chunkBox, chunkPos, pivot);
BlockBox box = this.getBoundingBox();
for (int bx = box.getMinX(); bx <= box.getMaxX(); bx++) {
for (int by = box.getMinY(); by <= box.getMaxY(); by++) {
for (int bz = box.getMinZ(); bz <= box.getMaxZ(); bz++) {
BlockPos pos = new BlockPos(bx, by, bz);
if (world.getBlockEntity(pos) instanceof ChestBlockEntity chest) {
chest.setLootTable(
new Identifier(Szar.MOD_ID, "chests/island"),
random.nextLong()
);
}
}
}
}
}
}

View File

@@ -1,11 +1,13 @@
package dev.tggamesyt.szar;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.entity.LivingEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvents;
@@ -15,6 +17,8 @@ import net.minecraft.util.UseAction;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import static dev.tggamesyt.szar.Szar.REVOLVER_STATE_SYNC;
public class RevolverItem extends Item {
public static final int CHAMBERS = 6;
@@ -75,4 +79,16 @@ public class RevolverItem extends Item {
return 72000; // held indefinitely
}
public static void syncRevolverToClient(ServerPlayerEntity player, ItemStack stack) {
boolean[] chambers = RevolverItem.getChambers(stack);
int current = RevolverItem.getCurrentChamber(stack);
PacketByteBuf buf = PacketByteBufs.create();
for (int i = 0; i < RevolverItem.CHAMBERS; i++) {
buf.writeBoolean(chambers[i]);
}
buf.writeInt(current);
ServerPlayNetworking.send(player, REVOLVER_STATE_SYNC, buf);
}
}

View File

@@ -9,8 +9,10 @@ import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents;
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerTickEvents;
import net.fabricmc.fabric.api.event.player.AttackEntityCallback;
import net.fabricmc.fabric.api.event.player.UseBlockCallback;
import net.fabricmc.fabric.api.item.v1.FabricItemSettings;
import net.fabricmc.fabric.api.itemgroup.v1.FabricItemGroup;
import net.fabricmc.fabric.api.loot.v2.LootTableEvents;
import net.fabricmc.fabric.api.message.v1.ServerMessageDecoratorEvent;
import net.fabricmc.fabric.api.networking.v1.PacketByteBufs;
import net.fabricmc.fabric.api.networking.v1.ServerPlayConnectionEvents;
@@ -26,6 +28,7 @@ import net.minecraft.advancement.Advancement;
import net.minecraft.block.*;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.block.entity.BlockEntityType;
import net.minecraft.block.entity.ChestBlockEntity;
import net.minecraft.entity.*;
import net.minecraft.entity.damage.DamageSource;
import net.minecraft.entity.damage.DamageType;
@@ -38,6 +41,11 @@ import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.*;
import net.minecraft.loot.LootPool;
import net.minecraft.loot.entry.ItemEntry;
import net.minecraft.loot.function.SetCountLootFunction;
import net.minecraft.loot.provider.number.ConstantLootNumberProvider;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.network.PacketByteBuf;
import net.minecraft.registry.*;
import net.minecraft.registry.entry.RegistryEntry;
@@ -79,6 +87,7 @@ import net.minecraft.world.gen.structure.StructureType;
import net.minecraft.world.poi.PointOfInterestType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.jmx.Server;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@@ -93,9 +102,16 @@ public class Szar implements ModInitializer {
public static MinecraftServer SERVER;
public static final Identifier REVOLVER_SHOOT = new Identifier(MOD_ID, "revolver_shoot");
public static final Identifier REVOLVER_SPIN = new Identifier(MOD_ID, "revolver_spin");
public static final Identifier REVOLVER_SYNC = new Identifier(MOD_ID, "revolver_sync");
public static final Identifier REVOLVER_STATE_SYNC = new Identifier(MOD_ID, "revolver_state_sync");
public static final Identifier BULLET_IMPACT = new Identifier(MOD_ID, "bullet_impact");
public static final Identifier REVOLVER_SCROLL = new Identifier(MOD_ID, "revolver_scroll");
public static final Identifier REVOLVER_SPIN_RESULT = new Identifier(MOD_ID, "revolver_spin_result"); // S2C
public static final Identifier AK47_SHOOT = new Identifier(MOD_ID, "ak47_shoot");
public static final Identifier REVOLVER_CHAMBER_CHANGE = new Identifier(MOD_ID, "revolver_chamber_change");
public static final SoundEvent REVOLVER_CLICK1_SOUND = SoundEvent.of(new Identifier(MOD_ID, "revolver_click1"));
public static final SoundEvent REVOLVER_CLICK2_SOUND = SoundEvent.of(new Identifier(MOD_ID, "revolver_click2"));
public static final SoundEvent REVOLVER_CLICK3_SOUND = SoundEvent.of(new Identifier(MOD_ID, "revolver_click3"));
public static final SoundEvent REVOLVER_ROLL_SOUND = SoundEvent.of(new Identifier(MOD_ID, "revolver_roll"));
public static final SoundEvent BESZIV = Registry.register(
Registries.SOUND_EVENT,
new Identifier(MOD_ID, "besziv"),
@@ -239,6 +255,7 @@ public class Szar implements ModInitializer {
.dimensions(EntityDimensions.fixed(0.6F, 1.8F)) // player-sized
.build()
);
public static final EntityType<HitterEntity> HitterEntityType =
Registry.register(
Registries.ENTITY_TYPE,
@@ -373,12 +390,62 @@ public class Szar implements ModInitializer {
private final Map<UUID, BlockPos> sleepingPlayers = new HashMap<>();
@Override
public void onInitialize() {
ServerPlayNetworking.registerGlobalReceiver(AK47_SHOOT, (server, player, handler, buf, responseSender) -> {
server.execute(() -> {
ItemStack stack = player.getMainHandStack();
if (!stack.isOf(Szar.AK47)) return;
if (player.getItemCooldownManager().isCoolingDown(Szar.AK47)) return;
AK47Item ak = (AK47Item) Szar.AK47;
if (!ak.consumeAmmo(player)) return;
player.getWorld().playSound(null, player.getBlockPos(),
SoundEvents.ENTITY_GENERIC_EXPLODE, SoundCategory.PLAYERS, 0.5f, 1.8f);
BulletEntity bullet = new BulletEntity(player.getWorld(), player);
bullet.setVelocity(player, player.getPitch(), player.getYaw(), 0f, 4.5f, 1.0f);
player.getWorld().spawnEntity(bullet);
// Recoil when shooting downward while falling
recoil(player, 0.1);
player.getItemCooldownManager().set(Szar.AK47, 2);
});
});
ServerPlayConnectionEvents.DISCONNECT.register((handler, server) -> {
PoliceSpawnTimerStore.remove(handler.player);
});
ServerPlayNetworking.registerGlobalReceiver(REVOLVER_SCROLL, (server, player, handler, buf, responseSender) -> {
int direction = buf.readInt();
server.execute(() -> {
ItemStack stack = player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
int current = RevolverItem.getCurrentChamber(stack);
int next = (current + direction + RevolverItem.CHAMBERS) % RevolverItem.CHAMBERS;
RevolverItem.setCurrentChamber(stack, next);
playRevolverClick(player);
RevolverItem.syncRevolverToClient(player, stack); // <- here
});
});
ServerPlayNetworking.registerGlobalReceiver(REVOLVER_SPIN, (server, player, handler, buf, responseSender) -> {
server.execute(() -> {
ItemStack stack = player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
int steps = 1 + player.getWorld().getRandom().nextInt(RevolverItem.CHAMBERS);
int current = RevolverItem.getCurrentChamber(stack);
RevolverItem.setCurrentChamber(stack, (current + steps) % RevolverItem.CHAMBERS);
player.getWorld().playSound(null, player.getBlockPos(),
Szar.REVOLVER_ROLL_SOUND, SoundCategory.PLAYERS, 1f, 1f);
// Tell client how many steps for animation
PacketByteBuf replyBuf = PacketByteBufs.create();
replyBuf.writeInt(steps);
ServerPlayNetworking.send(player, REVOLVER_SPIN_RESULT, replyBuf);
RevolverItem.syncRevolverToClient(player, stack);
});
});
ServerPlayNetworking.registerGlobalReceiver(REVOLVER_CHAMBER_CHANGE, (server, player, handler, buf, responseSender) -> {
int index = buf.readInt();
boolean wasLoaded = buf.readBoolean(); // true = unloading, false = loading
boolean wasLoaded = buf.readBoolean();
server.execute(() -> {
ItemStack stack = player.getMainHandStack();
@@ -387,12 +454,10 @@ public class Szar implements ModInitializer {
boolean[] chambers = RevolverItem.getChambers(stack);
if (wasLoaded) {
// Unload — give shell
chambers[index] = false;
RevolverItem.setChambers(stack, chambers);
player.getInventory().insertStack(new ItemStack(Szar.BULLET_ITEM));
} else {
// Load — take bullet from inventory
for (int i = 0; i < player.getInventory().size(); i++) {
ItemStack s = player.getInventory().getStack(i);
if (!s.isEmpty() && s.isOf(Szar.BULLET_ITEM)) {
@@ -403,33 +468,11 @@ public class Szar implements ModInitializer {
}
}
}
});
});
ServerPlayNetworking.registerGlobalReceiver(REVOLVER_SYNC, (server, player, handler, buf, responseSender) -> {
// Read 6 booleans from packet
boolean[] chambers = new boolean[RevolverItem.CHAMBERS];
for (int i = 0; i < RevolverItem.CHAMBERS; i++) {
chambers[i] = buf.readBoolean();
}
int currentChamber = buf.readInt();
server.execute(() -> {
ItemStack stack = player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
RevolverItem.setChambers(stack, chambers);
RevolverItem.setCurrentChamber(stack, currentChamber);
});
});
ServerPlayNetworking.registerGlobalReceiver(REVOLVER_SPIN, (server, player, handler, buf, responseSender) -> {
server.execute(() -> {
ItemStack stack = player.getMainHandStack();
if (!stack.isOf(Szar.REVOLVER)) return;
int steps = 1 + player.getWorld().getRandom().nextInt(RevolverItem.CHAMBERS);
int current = RevolverItem.getCurrentChamber(stack);
RevolverItem.setCurrentChamber(stack, (current + steps) % RevolverItem.CHAMBERS);
// Notify player
player.sendMessage(Text.literal("*click* chamber " +
(RevolverItem.getCurrentChamber(stack) + 1)).formatted(Formatting.GRAY), true);
// Advance to next chamber after loading/unloading
RevolverItem.setCurrentChamber(stack, (index + 1) % RevolverItem.CHAMBERS);
playRevolverClick(player);
RevolverItem.syncRevolverToClient(player, stack);
});
});
ServerPlayNetworking.registerGlobalReceiver(REVOLVER_SHOOT, (server, player, handler, buf, responseSender) -> {
@@ -462,11 +505,15 @@ public class Szar implements ModInitializer {
BulletEntity bullet = new BulletEntity(player.getWorld(), player);
bullet.setVelocity(player, player.getPitch(), player.getYaw(), 0f, 4.5f, 0.0f);
player.getWorld().spawnEntity(bullet);
// Recoil when shooting downward while falling
recoil(player, 0.2);
}
}
// Always advance chamber after trigger pull
RevolverItem.setCurrentChamber(stack, (current + 1) % RevolverItem.CHAMBERS);
playRevolverClick(player);
RevolverItem.syncRevolverToClient(player, stack);
});
});
ServerPlayNetworking.registerGlobalReceiver(CONFIG_SYNC,
@@ -759,12 +806,6 @@ public class Szar implements ModInitializer {
NyanEntityType,
1, 1, 1
);
BiomeModifications.addSpawn(
BiomeSelectors.includeByKey(BiomeKeys.FOREST, BiomeKeys.FLOWER_FOREST),
SpawnGroup.MONSTER,
EpsteinEntityType,
1, 1, 1
);
BiomeModifications.addFeature(
BiomeSelectors.tag(BiomeTags.IS_JUNGLE),
GenerationStep.Feature.VEGETAL_DECORATION,
@@ -912,6 +953,26 @@ public class Szar implements ModInitializer {
new Identifier(MOD_ID, "nyansniffer"),
new PaintingVariant(32, 32)
);
// In Szar.java onInitialize:
UseBlockCallback.EVENT.register((player, world, hand, hitResult) -> {
if (world.isClient) return ActionResult.PASS;
BlockPos pos = hitResult.getBlockPos();
if (!(world.getBlockEntity(pos) instanceof ChestBlockEntity chest)) return ActionResult.PASS;
// Check if this is an island chest by checking if it has our loot table pending
// Once loot generates we can't check anymore, so tag it via NBT during structure gen
NbtCompound nbt = chest.createNbt();
if (!nbt.getString("szar_chest_type").equals("island")) return ActionResult.PASS;
// Set center item if not already set
ItemStack center = chest.getStack(13);
if (center.isEmpty()) {
chest.setStack(13, new ItemStack(Szar.EPSTEIN_FILES));
}
nbt.remove("szar_chest_type");
return ActionResult.PASS;
});
}
// In your ModItems or wherever you register items
@@ -1066,6 +1127,19 @@ public class Szar implements ModInitializer {
new Identifier(MOD_ID, "casino"),
() -> CasinoStructure.CODEC
);
public static final StructurePieceType ISLAND_PIECE =
Registry.register(
Registries.STRUCTURE_PIECE,
new Identifier(MOD_ID, "island_piece"),
IslandStructurePiece::new
);
public static final StructureType<IslandStructure> ISLAND_TYPE =
Registry.register(
Registries.STRUCTURE_TYPE,
new Identifier(MOD_ID, "island"),
() -> IslandStructure.CODEC
);
static VoxelShape shape0 = VoxelShapes.cuboid(0.1875f, 0f, 0.625f, 0.6875f, 0.5f, 1.125f);
static VoxelShape shape1 = VoxelShapes.cuboid(0.1875f, 1.5f, 0.625f, 0.6875f, 2f, 1.125f);
static VoxelShape shape2 = VoxelShapes.cuboid(0.5625f, 0f, 0.25f, 1.0625f, 2f, 0.75f);
@@ -1732,32 +1806,29 @@ public class Szar implements ModInitializer {
}
}
private static void shootBullet(ServerPlayerEntity player) {
World world = player.getWorld();
Vec3d start = player.getEyePos();
Vec3d dir = player.getRotationVec(1.0f);
Vec3d end = start.add(dir.multiply(100)); // 100 block range
net.minecraft.util.hit.HitResult hit = world.raycast(new net.minecraft.world.RaycastContext(
start, end,
net.minecraft.world.RaycastContext.ShapeType.COLLIDER,
net.minecraft.world.RaycastContext.FluidHandling.NONE,
player
));
// Entity hit check
Box box = new Box(start, end).expand(1);
net.minecraft.util.hit.EntityHitResult entityHit =
net.minecraft.entity.projectile.ProjectileUtil.raycast(
player, start, end, box,
e -> !e.isSpectator() && e != player && e.canHit(), 100 * 100
);
if (entityHit != null) {
entityHit.getEntity().damage(
world.getDamageSources().playerAttack(player), 8.0f
);
public static void recoil(ServerPlayerEntity player, double recoil) {
if (player.isCreative()) {
return;
}
double recoilfinal = player.isOnGround() ? recoil / 2 : recoil;
// Opposite of the direction the player is looking
float pitch = (float) Math.toRadians(player.getPitch());
float yaw = (float) Math.toRadians(player.getYaw());
double dx = -(-Math.cos(pitch) * Math.sin(yaw)) * recoilfinal;
double dy = -(- Math.sin(pitch)) * recoilfinal;
double dz = -( Math.cos(pitch) * Math.cos(yaw)) * recoilfinal;
player.addVelocity(dx, dy, dz);
player.velocityModified = true;
player.fallDistance = Math.max(0, player.fallDistance - (float)(dy * 8));
}
private static void playRevolverClick(ServerPlayerEntity player) {
float pitch = 0.9F + player.getWorld().getRandom().nextFloat() * 0.2F; // 0.9 to 1.1
player.getWorld().playSound(null, player.getBlockPos(),
Szar.REVOLVER_CLICK2_SOUND, SoundCategory.PLAYERS, 1f, pitch);
}
}

View File

@@ -162,5 +162,37 @@
"stream": true
}
]
},
"revolver_click1": {
"sounds": [
{
"name": "szar:revolver_click1",
"stream": true
}
]
},
"revolver_click2": {
"sounds": [
{
"name": "szar:revolver_click2",
"stream": true
}
]
},
"revolver_click3": {
"sounds": [
{
"name": "szar:revolver_click3",
"stream": true
}
]
},
"revolver_roll": {
"sounds": [
{
"name": "szar:revolver_roll",
"stream": true
}
]
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 B

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@@ -1,7 +1,8 @@
{
"replace": false,
"values": [
"szar:niggerite_block"
"szar:niggerite_block",
"szar:cigany"
]
}

View File

@@ -0,0 +1,61 @@
{
"type": "minecraft:chest",
"pools": [
{
"rolls": 1,
"entries": [
{
"type": "minecraft:item",
"name": "szar:epstein_files"
}
]
},
{
"rolls": 26,
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:gold_ingot",
"weight": 40,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:binomial",
"n": 1,
"p": 0.2
},
"add": true
}
]
},
{
"type": "minecraft:item",
"name": "minecraft:diamond",
"weight": 30,
"functions": [
{
"function": "minecraft:set_count",
"count": {
"type": "minecraft:binomial",
"n": 1,
"p": 0.2
},
"add": true
}
]
},
{
"type": "minecraft:item",
"name": "minecraft:gold_block",
"weight": 20
},
{
"type": "minecraft:item",
"name": "minecraft:diamond_block",
"weight": 10
}
]
}
]
}

View File

@@ -0,0 +1,17 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"DDD",
"DDD",
"DDD"
],
"key": {
"D": {
"item": "minecraft:debug_stick"
}
},
"result": {
"item": "szar:cigany",
"count": 1
}
}

Binary file not shown.

View File

@@ -0,0 +1,11 @@
{
"values": [
"minecraft:ocean",
"minecraft:deep_ocean",
"minecraft:cold_ocean",
"minecraft:deep_cold_ocean",
"minecraft:lukewarm_ocean",
"minecraft:deep_lukewarm_ocean",
"minecraft:warm_ocean"
]
}

View File

@@ -0,0 +1,8 @@
{
"type": "szar:island",
"biomes": "#szar:island",
"step": "surface_structures",
"terrain_adaptation": "beard_thin",
"spawn_overrides": {},
"config": {}
}

View File

@@ -0,0 +1,14 @@
{
"structures": [
{
"structure": "szar:island",
"weight": 1
}
],
"placement": {
"type": "minecraft:random_spread",
"spacing": 40,
"separation": 20,
"salt": 533693546
}
}