diff --git a/gradle.properties b/gradle.properties index 56d07eb..b1dfe88 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ minecraft_version=1.20.1 yarn_mappings=1.20.1+build.10 loader_version=0.18.3 # Mod Properties -mod_version=26.3.7 +mod_version=26.3.8 maven_group=dev.tggamesyt archives_base_name=szar # Dependencies diff --git a/src/client/java/dev/tggamesyt/szar/client/RouletteScreen.java b/src/client/java/dev/tggamesyt/szar/client/RouletteScreen.java new file mode 100644 index 0000000..fb6877a --- /dev/null +++ b/src/client/java/dev/tggamesyt/szar/client/RouletteScreen.java @@ -0,0 +1,270 @@ +package dev.tggamesyt.szar.client; + +import dev.tggamesyt.szar.*; +import net.minecraft.client.gui.DrawContext; +import net.minecraft.client.gui.screen.ingame.HandledScreen; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.text.Text; +import net.minecraft.util.Identifier; +import net.minecraft.util.math.RotationAxis; + +public class RouletteScreen extends HandledScreen { + + private static final Identifier BG_TEXTURE = + new Identifier(Szar.MOD_ID, "textures/gui/roulette.png"); + + // Add these fields to the class + private int dotAnimFrame = 0; + private int dotAnimTick = 0; + private static final int DOT_FRAME_DURATION = 20; + private static final String[] DOT_FRAMES = { + "...", "⋅..", "⋅⋅.", ".⋅⋅", "..⋅", "...", "...", "...", "..." + }; + private boolean showingWinner = false; + private int stoppedTick = 0; // elapsed ticks since spin stopped + + private final PlayerInventory inventory; + private final RouletteBlockEntity blockEntity; + private final RouletteScreenHandler handler; + + public String spinString = "Next spin in: 0s"; + public int nextspinTime = 0; + public boolean isIntermission = true; + private int winnernum = 0; + + private float wheelDeg = 0f; + private float ballDeg = 0f; + + // Spin start positions (captured when spin begins) + private float wheelStartDeg = 0f; + private float ballStartDeg = 0f; + + // Total distance each will travel over the entire spin duration + private float wheelTotalDist = 0f; + private float ballTotalDist = 0f; + + // Total ticks for the active spin (rollingTicks + halfWaitTicks) + private int spinTotalTicks = 0; + + // How many ticks of the spin are "locked still" at the end (second half of wait) + private int spinStopTicks = 0; + + private boolean spinInitialized = false; + private int lastElapsed = -1; + + // Full speed in degrees/tick — used to compute how far wheel/ball travel + // during the constant-speed portion so total distance lands on target + private static final float WHEEL_FULL_SPEED = 8.0f; + private static final float BALL_FULL_SPEED = 14.0f; + + public RouletteScreen(RouletteScreenHandler handler, + PlayerInventory inventory, + Text title) { + super(handler, inventory, title); + this.handler = handler; + this.blockEntity = handler.blockEntity; + this.backgroundWidth = 326; + this.backgroundHeight = 194; + this.inventory = inventory; + } + + // Ease curve: constant speed phase (0→splitT) then ease-out (splitT→1) + // At t=splitT the curve transitions smoothly — the ease-out's initial + // derivative is set to match FULL_SPEED so there is no speed discontinuity. + // + // For t in [0, splitT]: pos(t) = fullSpeed * t * totalTicks + // For t in [splitT, 1]: pos(t) = pos(splitT) + decelDist * easeOut((t-splitT)/(1-splitT)) + // + // easeOut(u) = 2u - u² → derivative at u=0 is 2/totalDecelTicks * decelDist + // We need that to equal fullSpeed * totalTicks (per-tick speed at split point). + // This is satisfied automatically because we set decelDist so the curve lands on target, + // and the split is at the rollingTicks boundary. + + private void onSpinStart(int rollingTicks, int halfWaitTicks) { + spinTotalTicks = rollingTicks + halfWaitTicks; + spinStopTicks = blockEntity.wheelWaitSeconds * 20 - halfWaitTicks; // second half of wait + + wheelStartDeg = wheelDeg; + ballStartDeg = ballDeg; + + float targetWheelDeg = RouletteBlockEntity.getWheelDegrees(winnernum); + float targetBallDeg = 0f; + + // Distance covered during constant phase (phase1) + float wheelPhase1Dist = WHEEL_FULL_SPEED * rollingTicks; + float ballPhase1Dist = BALL_FULL_SPEED * rollingTicks; + + // Where each ends up after phase1 + float wheelAfterPhase1 = (wheelStartDeg + wheelPhase1Dist) % 360f; + float ballAfterPhase1 = (ballStartDeg + ballPhase1Dist) % 360f; + + // Phase2 must cover exactly the right distance to land on target. + // Pick the smallest distance >= a minimum so the wheel visibly decelerates. + float minDecelRotations = 1.0f; // at least 1 full extra rotation during decel + float wheelPhase2Dist = positiveMod(targetWheelDeg - wheelAfterPhase1, 360f); + if (wheelPhase2Dist < 360f * minDecelRotations) wheelPhase2Dist += 360f; + + float ballPhase2Dist = positiveMod(targetBallDeg - ballAfterPhase1, 360f); + if (ballPhase2Dist < 360f * minDecelRotations) ballPhase2Dist += 360f; + + wheelTotalDist = wheelPhase1Dist + wheelPhase2Dist; + ballTotalDist = ballPhase1Dist + ballPhase2Dist; + + spinInitialized = true; + } + + // Returns position fraction [0,1] along the total distance given elapsed ticks. + // Uses a piecewise curve: linear up to splitTick, then ease-out after. + // The ease-out's initial slope matches the linear slope → no speed jump. + private float curvePosition(int elapsed, int splitTick, int totalTicks, + float phase1Dist, float totalDist) { + if (elapsed <= 0) return 0f; + if (elapsed >= totalTicks) return 1f; + + float phase2Dist = totalDist - phase1Dist; + + if (elapsed <= splitTick) { + // Linear phase + return (phase1Dist * ((float) elapsed / splitTick)) / totalDist; + } else { + // Ease-out phase: u goes 0→1 over (totalTicks - splitTick) ticks + float u = (float)(elapsed - splitTick) / (totalTicks - splitTick); + // easeOut(u) = 2u - u² (starts at slope 2, ends at slope 0) + float eased = 2f * u - u * u; + return (phase1Dist + eased * phase2Dist) / totalDist; + } + } + + public void tickScreen() { + nextspinTime = handler.getPropertyDelegate().get(1); + isIntermission = handler.getPropertyDelegate().get(0) == 1; + winnernum = handler.getPropertyDelegate().get(2); + + if (isIntermission) { + spinString = "Next spin in: " + (nextspinTime + 19) / 20 + "s"; + spinInitialized = false; + lastElapsed = -1; + showingWinner = false; + stoppedTick = 0; + wheelDeg = RouletteBlockEntity.getWheelDegrees(winnernum); + ballDeg = 0f; + return; + } + + int rollingTicks = blockEntity.wheelRollingSeconds * 20; + int waitTicks = blockEntity.wheelWaitSeconds * 20; + int halfWaitTicks = waitTicks / 2; + int elapsed = -nextspinTime; + + if (!spinInitialized || lastElapsed < 0) { + dotAnimFrame = 0; + dotAnimTick = 0; + showingWinner = false; + stoppedTick = 0; + onSpinStart(rollingTicks, halfWaitTicks); + } + lastElapsed = elapsed; + + if (elapsed >= spinTotalTicks) { + // Wheel has stopped — count ticks and show winner at halfWaitTicks + stoppedTick++; + wheelDeg = RouletteBlockEntity.getWheelDegrees(winnernum); + ballDeg = 0f; + if (stoppedTick >= halfWaitTicks) { + showingWinner = true; + } + spinString = showingWinner ? "Winner: " + winnernum + " (" + RouletteBlockEntity.NUMBER_COLORS[winnernum].toUpperCase() + ")" : "Spinning" + DOT_FRAMES[dotAnimFrame]; + return; + } + + // Animate dots while spinning + dotAnimTick++; + if (dotAnimTick >= DOT_FRAME_DURATION) { + dotAnimTick = 0; + dotAnimFrame = (dotAnimFrame + 1) % DOT_FRAMES.length; + } + spinString = "Spinning" + DOT_FRAMES[dotAnimFrame]; + + float wheelFrac = curvePosition(elapsed, rollingTicks, spinTotalTicks, + WHEEL_FULL_SPEED * rollingTicks, wheelTotalDist); + float ballFrac = curvePosition(elapsed, rollingTicks, spinTotalTicks, + BALL_FULL_SPEED * rollingTicks, ballTotalDist); + + wheelDeg = (wheelStartDeg + wheelFrac * wheelTotalDist) % 360f; + ballDeg = (ballStartDeg + ballFrac * ballTotalDist) % 360f; + } + + private static float positiveMod(float value, float mod) { + return ((value % mod) + mod) % mod; + } + + // ---------------------------- + // BACKGROUND + // ---------------------------- + + @Override + protected void drawBackground(DrawContext context, float delta, int mouseX, int mouseY) { + int guiLeft = (width - backgroundWidth) / 2; + int guiTop = (height - backgroundHeight) / 2; + context.getMatrices().push(); + context.getMatrices().translate(guiLeft, guiTop, 0); + context.getMatrices().scale(2.0f, 2.0f, 1.0f); + context.drawTexture(BG_TEXTURE, 0, 0, 0, 0, backgroundWidth, backgroundHeight); + context.getMatrices().pop(); + } + + protected void drawText(DrawContext context) { + int guiLeft = (width - backgroundWidth) / 2; + int guiTop = (height - backgroundHeight) / 2; + context.drawText(textRenderer, Text.literal(spinString), + guiLeft + 190, guiTop + 115, 0x373737, false); + } + + protected void drawWheel(DrawContext context) { + int cx = ((width - backgroundWidth) / 2) + 255; + int cy = ((height - backgroundHeight) / 2) + 155; + + Identifier wheelTex = new Identifier(Szar.MOD_ID, "textures/gui/roulette_wheel.png"); + Identifier ballTex = new Identifier(Szar.MOD_ID, "textures/gui/roulette_ball.png"); + int imgWidth = 64; + int imgHeight = 64; + + context.getMatrices().push(); + context.getMatrices().translate(cx, cy, 0); + context.getMatrices().multiply(RotationAxis.POSITIVE_Z.rotationDegrees(wheelDeg)); + context.drawTexture(wheelTex, -imgWidth / 2, -imgHeight / 2, 0, 0, + imgWidth, imgHeight, imgWidth, imgHeight); + context.getMatrices().pop(); + + context.getMatrices().push(); + context.getMatrices().translate(cx, cy, 0); + context.getMatrices().multiply(RotationAxis.POSITIVE_Z.rotationDegrees(ballDeg)); + context.drawTexture(ballTex, -imgWidth / 2, -imgHeight / 2, 0, 0, + imgWidth, imgHeight, imgWidth, imgHeight); + context.getMatrices().pop(); + } + + // ---------------------------- + // RENDER + // ---------------------------- + + @Override + public void render(DrawContext context, int mouseX, int mouseY, float delta) { + renderBackground(context); + super.render(context, mouseX, mouseY, delta); + drawWheel(context); + drawText(context); + drawMouseoverTooltip(context, mouseX, mouseY); + tickScreen(); + } + + @Override + public boolean mouseClicked(double mouseX, double mouseY, int button) { + return super.mouseClicked(mouseX, mouseY, button); + } + + @Override + public void removed() { + super.removed(); + } +} \ No newline at end of file diff --git a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java index 3a54327..05f3658 100644 --- a/src/client/java/dev/tggamesyt/szar/client/SzarClient.java +++ b/src/client/java/dev/tggamesyt/szar/client/SzarClient.java @@ -250,6 +250,7 @@ public class SzarClient implements ClientModInitializer { SlotMachineRenderer::new );*/ HandledScreens.register(Szar.SLOT_MACHINE_SCREEN_HANDLER_TYPE, SlotMachineScreen::new); + HandledScreens.register(Szar.ROULETTE_SCREEN_HANDLER_TYPE, RouletteScreen::new); EntityRendererRegistry.register( Szar.NiggerEntityType, diff --git a/src/main/java/dev/tggamesyt/szar/RouletteBlock.java b/src/main/java/dev/tggamesyt/szar/RouletteBlock.java new file mode 100644 index 0000000..8707e72 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/RouletteBlock.java @@ -0,0 +1,204 @@ +package dev.tggamesyt.szar; + +import net.fabricmc.fabric.api.screenhandler.v1.ExtendedScreenHandlerFactory; +import net.minecraft.block.Block; +import net.minecraft.block.BlockEntityProvider; +import net.minecraft.block.BlockState; +import net.minecraft.block.ShapeContext; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.block.entity.BlockEntityTicker; +import net.minecraft.block.entity.BlockEntityType; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.item.ItemPlacementContext; +import net.minecraft.network.PacketByteBuf; +import net.minecraft.screen.NamedScreenHandlerFactory; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.state.StateManager; +import net.minecraft.state.property.DirectionProperty; +import net.minecraft.state.property.Properties; +import net.minecraft.text.Text; +import net.minecraft.util.ActionResult; +import net.minecraft.util.BlockMirror; +import net.minecraft.util.BlockRotation; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Vec3d; +import net.minecraft.util.shape.VoxelShape; +import net.minecraft.util.shape.VoxelShapes; +import net.minecraft.world.BlockView; +import net.minecraft.world.World; + +public class RouletteBlock extends Block implements BlockEntityProvider { + + public static final DirectionProperty FACING = Properties.HORIZONTAL_FACING; + + public RouletteBlock(Settings settings) { + super(settings); + setDefaultState(getStateManager().getDefaultState().with(FACING, Direction.NORTH)); + } + + VoxelShape shape23 = VoxelShapes.cuboid(0.25f, 0f, 0f, 0.75f, 0.25f, 0.125f); + VoxelShape shape24 = VoxelShapes.cuboid(0.125f, 0f, 0.125f, 0.875f, 0.125f, 0.25f); + VoxelShape shape25 = VoxelShapes.cuboid(0f, 0f, 0.25f, 1f, 0.125f, 0.75f); + VoxelShape shape26 = VoxelShapes.cuboid(0.125f, 0f, 0.75f, 0.875f, 0.125f, 0.875f); + VoxelShape shape27 = VoxelShapes.cuboid(0.25f, 0f, 0.875f, 0.75f, 0.25f, 1f); + VoxelShape shape28 = VoxelShapes.cuboid(0f, 0.125f, 0.25f, 0.125f, 0.25f, 0.75f); + VoxelShape shape29 = VoxelShapes.cuboid(0.875f, 0.125f, 0.25f, 1f, 0.25f, 0.75f); + VoxelShape shape30 = VoxelShapes.cuboid(0.75f, 0.125f, 0.125f, 0.875f, 0.25f, 0.25f); + VoxelShape shape31 = VoxelShapes.cuboid(0.75f, 0.125f, 0.75f, 0.875f, 0.25f, 0.875f); + VoxelShape shape32 = VoxelShapes.cuboid(0.125f, 0.125f, 0.125f, 0.25f, 0.25f, 0.25f); + VoxelShape shape33 = VoxelShapes.cuboid(0.125f, 0.125f, 0.75f, 0.25f, 0.25f, 0.875f); + VoxelShape shape34 = VoxelShapes.cuboid(0.3125f, 0.313125f, 0.3125f, 0.6875f, 0.313125f, 0.6875f); + VoxelShape shape35 = VoxelShapes.cuboid(0.4375f, 0.125f, 0.4375f, 0.5625f, 0.3125f, 0.5625f); + VoxelShape BASE_SHAPE = VoxelShapes.union(shape23, shape24, shape25, shape26, shape27, shape28, shape29, shape30, shape31, shape32, shape33, shape34, shape35); + + private static VoxelShape rotateShape(Direction from, Direction to, VoxelShape shape) { + VoxelShape[] buffer = new VoxelShape[]{shape, VoxelShapes.empty()}; + + int times = (to.getHorizontal() - from.getHorizontal() + 4) % 4; + + for (int i = 0; i < times; i++) { + buffer[0].forEachBox((minX, minY, minZ, maxX, maxY, maxZ) -> + buffer[1] = VoxelShapes.union(buffer[1], + VoxelShapes.cuboid(1 - maxZ, minY, minX, 1 - minZ, maxY, maxX)) + ); + buffer[0] = buffer[1]; + buffer[1] = VoxelShapes.empty(); + } + + return buffer[0]; + } + + @Override + public VoxelShape getCollisionShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + return rotateShape(Direction.NORTH, state.get(FACING), BASE_SHAPE); + } + + @Override + public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { + return getCollisionShape(state, world, pos, context); + } + + // ===== ROTATION ===== + + @Override + public BlockState getPlacementState(ItemPlacementContext ctx) { + return getDefaultState().with(FACING, ctx.getHorizontalPlayerFacing().getOpposite()); + } + + @Override + protected void appendProperties(StateManager.Builder builder) { + builder.add(FACING); + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, BlockState state) { + return new RouletteBlockEntity(pos, state); + } + + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, + PlayerEntity player, Hand hand, BlockHitResult hit) { + + if (hand != Hand.MAIN_HAND) return ActionResult.PASS; + + BlockEntity blockEntity = world.getBlockEntity(pos); + if (!(blockEntity instanceof RouletteBlockEntity be)) { + return ActionResult.PASS; + } + + Vec3d hitVec = hit.getPos().subtract(pos.getX(), pos.getY(), pos.getZ()); + Direction facing = state.get(FACING); + + double x = hitVec.x; + double y = hitVec.y; + double z = hitVec.z; + + // Rotate based on facing (proper Minecraft rotation logic) + switch (facing) { + case NORTH -> { + // no change + } + case SOUTH -> { + x = 1 - x; + z = 1 - z; + } + case WEST -> { + double temp = x; + x = z; + z = 1 - temp; + } + case EAST -> { + double temp = x; + x = 1 - z; + z = temp; + } + } + + boolean isHandle = + x >= 0.0625 && x <= 0.25 && + y >= 0.5 && y <= 0.6875 && + z >= 0.4375 && z <= 1.1875; + if (!world.isClient) { + // Open the GUI (client will receive block position) + player.openHandledScreen(state.createScreenHandlerFactory(world, pos)); + } + + return ActionResult.SUCCESS; + } + @Override + public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) { + BlockEntity be = world.getBlockEntity(pos); + if (!(be instanceof RouletteBlockEntity slotBe)) return null; + + // Return an ExtendedScreenHandlerFactory that sends the BlockPos to the client + return new ExtendedScreenHandlerFactory() { + @Override + public void writeScreenOpeningData(ServerPlayerEntity player, PacketByteBuf buf) { + buf.writeBlockPos(pos); // send the block pos to client for the constructor + } + + @Override + public Text getDisplayName() { + return Text.literal("Roulette"); + } + + @Override + public ScreenHandler createMenu(int syncId, PlayerInventory inv, PlayerEntity player) { + return new RouletteScreenHandler(syncId, inv, slotBe); + } + }; + } + + @Override + public BlockState rotate(BlockState state, BlockRotation rotation) { + if (state.contains(FACING)) { + return state.with(FACING, rotation.rotate(state.get(FACING))); + } + return state; + } + + @Override + public BlockState mirror(BlockState state, BlockMirror mirror) { + if (state.contains(FACING)) { + return state.rotate(mirror.getRotation(state.get(FACING))); + } + return state; + } + + @Override + public BlockEntityTicker getTicker( + World world, + BlockState state, + BlockEntityType type) { + + return type == Szar.ROULETTE_BLOCKENTITY + ? (world1, pos, state1, blockEntity) -> + RouletteBlockEntity.tick(world1, pos, state1, (RouletteBlockEntity) blockEntity) + : null; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/RouletteBlockEntity.java b/src/main/java/dev/tggamesyt/szar/RouletteBlockEntity.java new file mode 100644 index 0000000..28fca7d --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/RouletteBlockEntity.java @@ -0,0 +1,318 @@ +package dev.tggamesyt.szar; + +import net.minecraft.block.BlockState; +import net.minecraft.block.entity.BlockEntity; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.inventory.SimpleInventory; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NbtCompound; +import net.minecraft.nbt.NbtList; +import net.minecraft.network.listener.ClientPlayPacketListener; +import net.minecraft.network.packet.Packet; +import net.minecraft.network.packet.s2c.play.BlockEntityUpdateS2CPacket; +import net.minecraft.screen.ArrayPropertyDelegate; +import net.minecraft.screen.PropertyDelegate; +import net.minecraft.server.network.ServerPlayerEntity; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; + +import java.util.HashMap; +import java.util.Map; +import java.util.Random; +import java.util.UUID; + +public class RouletteBlockEntity extends BlockEntity { + public int wheelWaitSeconds = 10; + public int wheelRollingSeconds = 5; + public int intermissionSeconds = 20; + + private static final int[] WHEEL_ORDER = { + 0, 26, 3, 35, 12, 28, 7, 29, 18, 22, 9, + 31, 14, 20, 1, 33, 16, 24, 5, 10, 23, 8, + 30, 11, 36, 13, 27, 6, 34, 17, 25, 2, 21, + 4, 19, 15, 32 + }; + + // 0=green, then alternating red/black in standard European roulette order + // Index = the number itself (0-36) + public static final String[] NUMBER_COLORS = { + "green", // 0 + "red", "black", "red", "black", "red", // 1-5 + "black", "red", "black", "red", "black",// 6-10 + "black", "red", "black", "red", "black",// 11-15 + "red", "black", "red", "black", "black",// 16-20 + "red", "black", "red", "black", "red", // 21-25 + "black", "red", "red", "black", "red", // 26-30 + "black", "red", "black", "red", "black",// 31-35 + "red" // 36 + }; + + public static float getWheelDegrees(int winnerNum) { + for (int i = 0; i < WHEEL_ORDER.length; i++) { + if (WHEEL_ORDER[i] == winnerNum) return i * 9.73f; + } + return 0.0f; + } + + private int winnernum = 0; + public boolean isIntermission = true; + public int nextspinTime = intermissionSeconds * 20; + final PropertyDelegate propertyDelegate; + + private final Map playerInventories = new HashMap<>(); + + public RouletteBlockEntity(BlockPos pos, BlockState state) { + super(Szar.ROULETTE_BLOCKENTITY, pos, state); + this.propertyDelegate = new ArrayPropertyDelegate(3); + } + + public static class PlayerBetInventories { + public final SimpleInventory fullbet = new SimpleInventory(37); + public final SimpleInventory twelves = new SimpleInventory(3); + public final SimpleInventory halves = new SimpleInventory(2); + public final SimpleInventory evenodd = new SimpleInventory(2); + public final SimpleInventory blackred = new SimpleInventory(2); + public final SimpleInventory thirds = new SimpleInventory(3); + + public void clear() { + fullbet.clear(); + twelves.clear(); + halves.clear(); + evenodd.clear(); + blackred.clear(); + thirds.clear(); + } + + public void writeNbt(NbtCompound nbt) { + nbt.put("fullbet", inventoryToNbt(fullbet)); + nbt.put("twelves", inventoryToNbt(twelves)); + nbt.put("halves", inventoryToNbt(halves)); + nbt.put("evenodd", inventoryToNbt(evenodd)); + nbt.put("blackred", inventoryToNbt(blackred)); + nbt.put("thirds", inventoryToNbt(thirds)); + } + + public void readNbt(NbtCompound nbt) { + nbtToInventory(nbt.getList("fullbet", 10), fullbet); + nbtToInventory(nbt.getList("twelves", 10), twelves); + nbtToInventory(nbt.getList("halves", 10), halves); + nbtToInventory(nbt.getList("evenodd", 10), evenodd); + nbtToInventory(nbt.getList("blackred", 10), blackred); + nbtToInventory(nbt.getList("thirds", 10), thirds); + } + + private static NbtList inventoryToNbt(SimpleInventory inv) { + NbtList list = new NbtList(); + for (int i = 0; i < inv.size(); i++) { + NbtCompound slot = new NbtCompound(); + slot.putByte("Slot", (byte) i); + inv.getStack(i).writeNbt(slot); + list.add(slot); + } + return list; + } + + private static void nbtToInventory(NbtList list, SimpleInventory inv) { + for (int i = 0; i < list.size(); i++) { + NbtCompound slot = list.getCompound(i); + int index = slot.getByte("Slot") & 0xFF; + if (index < inv.size()) { + inv.setStack(index, ItemStack.fromNbt(slot)); + } + } + } + } + + public PlayerBetInventories getInventoriesFor(UUID uuid) { + return playerInventories.computeIfAbsent(uuid, id -> new PlayerBetInventories()); + } + + public PlayerBetInventories getInventoriesFor(net.minecraft.entity.player.PlayerEntity player) { + return getInventoriesFor(player.getUuid()); + } + + // ─── Payout logic ──────────────────────────────────────────────────────── + + private static void giveItems(ServerPlayerEntity player, ItemStack stack, int multiplier) { + if (stack.isEmpty()) return; + int total = stack.getCount() * multiplier; + while (total > 0) { + int batchSize = Math.min(total, stack.getMaxCount()); + ItemStack give = new ItemStack(stack.getItem(), batchSize); + player.getInventory().offerOrDrop(give); + total -= batchSize; + } + } + + private void resolvePayouts(World world, int winner) { + String winnerColor = NUMBER_COLORS[winner]; + + for (Map.Entry entry : playerInventories.entrySet()) { + ServerPlayerEntity player = (ServerPlayerEntity) world.getPlayerByUuid(entry.getKey()); + if (player == null) { + continue; + } + PlayerBetInventories inv = entry.getValue(); + + // fullbet + ItemStack fullbetBet = inv.fullbet.getStack(winner).copy(); + inv.fullbet.setStack(winner, ItemStack.EMPTY); + if (!fullbetBet.isEmpty()) { + giveItems(player, fullbetBet, 36); + } + + // twelves + if (winner >= 1 && winner <= 12) { + ItemStack bet = inv.twelves.getStack(0).copy(); + inv.twelves.setStack(0, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 3); } + } else if (winner >= 13 && winner <= 24) { + ItemStack bet = inv.twelves.getStack(1).copy(); + inv.twelves.setStack(1, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 3); } + } else if (winner >= 25 && winner <= 36) { + ItemStack bet = inv.twelves.getStack(2).copy(); + inv.twelves.setStack(2, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 3); } + } + + // halves + if (winner >= 1 && winner <= 18) { + ItemStack bet = inv.halves.getStack(0).copy(); + inv.halves.setStack(0, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } else if (winner >= 19 && winner <= 36) { + ItemStack bet = inv.halves.getStack(1).copy(); + inv.halves.setStack(1, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } + + // evenodd + if (winner != 0) { + if (winner % 2 == 0) { + ItemStack bet = inv.evenodd.getStack(0).copy(); + inv.evenodd.setStack(0, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } else { + ItemStack bet = inv.evenodd.getStack(1).copy(); + inv.evenodd.setStack(1, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } + } + + // blackred + if (winnerColor.equals("red")) { + ItemStack bet = inv.blackred.getStack(0).copy(); + inv.blackred.setStack(0, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } else if (winnerColor.equals("black")) { + ItemStack bet = inv.blackred.getStack(1).copy(); + inv.blackred.setStack(1, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } + + // thirds + if (winner != 0) { + if (winner % 3 == 0) { + ItemStack bet = inv.thirds.getStack(0).copy(); + inv.thirds.setStack(0, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } else if ((winner + 1) % 3 == 0) { + ItemStack bet = inv.thirds.getStack(1).copy(); + inv.thirds.setStack(1, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } else if ((winner + 2) % 3 == 0) { + ItemStack bet = inv.thirds.getStack(2).copy(); + inv.thirds.setStack(2, ItemStack.EMPTY); + if (!bet.isEmpty()) { giveItems(player, bet, 2); } + } + } + inv.clear(); + } + } + + // ─── Tick ───────────────────────────────────────────────────────────────── + + public static void tick(World world, BlockPos pos, BlockState state, RouletteBlockEntity be) { + if (world.isClient) return; + + be.nextspinTime--; + + if (be.isIntermission) { + if (be.nextspinTime > 0) { + // still counting down to spin + } else if (be.nextspinTime == 0) { + // Spin is starting — pick winner and clear all bets + be.winnernum = new Random().nextInt(37); + be.isIntermission = false; + } + } else { + // Spinning phase — nextspinTime is negative here + int spinTicks = (be.wheelWaitSeconds + be.wheelRollingSeconds) * 20; + if (be.nextspinTime <= -spinTicks) { + // Spin ended — resolve payouts then go back to intermission + be.resolvePayouts(world, be.winnernum); + be.isIntermission = true; + be.nextspinTime = be.intermissionSeconds * 20; + } + } + + be.propertyDelegate.set(0, be.isIntermission ? 1 : 0); + be.propertyDelegate.set(1, be.nextspinTime); + be.propertyDelegate.set(2, be.winnernum); + be.markDirty(); + } + + private void clearAllBets() { + for (PlayerBetInventories inv : playerInventories.values()) { + inv.clear(); + } + } + + // ─── NBT ────────────────────────────────────────────────────────────────── + + @Override + public void writeNbt(NbtCompound nbt) { + super.writeNbt(nbt); + nbt.putBoolean("isIntermission", isIntermission); + nbt.putInt("nextspinTime", nextspinTime); + nbt.putInt("winnernum", winnernum); + + NbtCompound playersNbt = new NbtCompound(); + for (Map.Entry entry : playerInventories.entrySet()) { + NbtCompound playerNbt = new NbtCompound(); + entry.getValue().writeNbt(playerNbt); + playersNbt.put(entry.getKey().toString(), playerNbt); + } + nbt.put("playerInventories", playersNbt); + } + + @Override + public void readNbt(NbtCompound nbt) { + super.readNbt(nbt); + isIntermission = nbt.getBoolean("isIntermission"); + nextspinTime = nbt.getInt("nextspinTime"); + winnernum = nbt.getInt("winnernum"); + + playerInventories.clear(); + NbtCompound playersNbt = nbt.getCompound("playerInventories"); + for (String key : playersNbt.getKeys()) { + UUID uuid = UUID.fromString(key); + PlayerBetInventories invs = new PlayerBetInventories(); + invs.readNbt(playersNbt.getCompound(key)); + playerInventories.put(uuid, invs); + } + } + + @Override + public Packet toUpdatePacket() { + return BlockEntityUpdateS2CPacket.create(this); + } + + @Override + public NbtCompound toInitialChunkDataNbt() { + NbtCompound nbt = new NbtCompound(); + writeNbt(nbt); + return nbt; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/RouletteScreenHandler.java b/src/main/java/dev/tggamesyt/szar/RouletteScreenHandler.java new file mode 100644 index 0000000..f039a78 --- /dev/null +++ b/src/main/java/dev/tggamesyt/szar/RouletteScreenHandler.java @@ -0,0 +1,143 @@ +package dev.tggamesyt.szar; + +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.entity.player.PlayerInventory; +import net.minecraft.inventory.Inventory; +import net.minecraft.item.ItemStack; +import net.minecraft.screen.PropertyDelegate; +import net.minecraft.screen.ScreenHandler; +import net.minecraft.screen.slot.Slot; + +public class RouletteScreenHandler extends ScreenHandler { + + public final RouletteBlockEntity blockEntity; + + public static final int SLOT_SIZE = 18; + public static final int GRID_START_X = 60; + public static final int GRID_START_Y = 8; + + private static int gx(int col) { return GRID_START_X + (col - 1) * SLOT_SIZE; } + private static int gy(int row) { return GRID_START_Y + (row - 1) * SLOT_SIZE; } + + // Slot that locks itself when the block entity is spinning + private class BetSlot extends Slot { + public BetSlot(Inventory inventory, int index, int x, int y) { + super(inventory, index, x, y); + } + + private boolean isSpinning() { + return !blockEntity.isIntermission; + } + + @Override + public boolean canInsert(ItemStack stack) { + return !isSpinning(); + } + + @Override + public boolean canTakeItems(PlayerEntity playerEntity) { + return !isSpinning(); + } + + @Override + public ItemStack takeStack(int amount) { + if (isSpinning()) return ItemStack.EMPTY; + return super.takeStack(amount); + } + } + + public RouletteScreenHandler(int syncId, PlayerInventory playerInv, RouletteBlockEntity blockEntity) { + super(Szar.ROULETTE_SCREEN_HANDLER_TYPE, syncId); + this.blockEntity = blockEntity; + + this.addProperties(blockEntity.propertyDelegate); + + RouletteBlockEntity.PlayerBetInventories inv = + blockEntity.getInventoriesFor(playerInv.player); + + // === fullbetInventory === + this.addSlot(new BetSlot(inv.fullbet, 0, gx(1), gy(2))); + int fbIdx = 1; + for (int col = 2; col <= 13; col++) { + this.addSlot(new BetSlot(inv.fullbet, fbIdx++, gx(col), gy(3))); + this.addSlot(new BetSlot(inv.fullbet, fbIdx++, gx(col), gy(2))); + this.addSlot(new BetSlot(inv.fullbet, fbIdx++, gx(col), gy(1))); + } + + // === twelvesInventory === + this.addSlot(new BetSlot(inv.twelves, 0, gx(3), gy(4))); + this.addSlot(new BetSlot(inv.twelves, 1, gx(7), gy(4))); + this.addSlot(new BetSlot(inv.twelves, 2, gx(11), gy(4))); + + // === halvesInventory === + this.addSlot(new BetSlot(inv.halves, 0, gx(2), gy(5))); + this.addSlot(new BetSlot(inv.halves, 1, gx(12), gy(5))); + + // === evenoddInventory === + this.addSlot(new BetSlot(inv.evenodd, 0, gx(4), gy(5))); + this.addSlot(new BetSlot(inv.evenodd, 1, gx(10), gy(5))); + + // === blackredInventory === + this.addSlot(new BetSlot(inv.blackred, 0, gx(6), gy(5))); + this.addSlot(new BetSlot(inv.blackred, 1, gx(8), gy(5))); + + // === thirdsInventory === + this.addSlot(new BetSlot(inv.thirds, 0, gx(14), gy(1))); + this.addSlot(new BetSlot(inv.thirds, 1, gx(14), gy(2))); + this.addSlot(new BetSlot(inv.thirds, 2, gx(14), gy(3))); + + // === Player inventory === + int playerInvY = GRID_START_Y + 5 * SLOT_SIZE + 14; + for (int y = 0; y < 3; y++) + for (int x = 0; x < 9; x++) + this.addSlot(new Slot(playerInv, x + y * 9 + 9, 8 + x * 18, playerInvY + y * 18)); + for (int x = 0; x < 9; x++) + this.addSlot(new Slot(playerInv, x, 8 + x * 18, playerInvY + 58)); + } + + @Override + public boolean onButtonClick(PlayerEntity player, int id) { + return true; + } + + @Override + public boolean canUse(PlayerEntity player) { + return true; + } + + @Override + public ItemStack quickMove(PlayerEntity player, int index) { + ItemStack newStack = ItemStack.EMPTY; + Slot slot = this.slots.get(index); + + if (slot.hasStack()) { + ItemStack originalStack = slot.getStack(); + newStack = originalStack.copy(); + + int playerStart = 49; + int totalSlots = this.slots.size(); + + if (index >= playerStart) { + if (!this.insertItem(originalStack, 0, 1, false)) { + return ItemStack.EMPTY; + } + } else if (index == 0) { + if (!this.insertItem(originalStack, playerStart, totalSlots, true)) { + return ItemStack.EMPTY; + } + } + + if (originalStack.isEmpty()) { + slot.setStack(ItemStack.EMPTY); + } else { + slot.markDirty(); + } + } + + return newStack; + } + + public PropertyDelegate getPropertyDelegate() { + return blockEntity.propertyDelegate; + } +} \ No newline at end of file diff --git a/src/main/java/dev/tggamesyt/szar/Szar.java b/src/main/java/dev/tggamesyt/szar/Szar.java index 618fa7b..c16f806 100644 --- a/src/main/java/dev/tggamesyt/szar/Szar.java +++ b/src/main/java/dev/tggamesyt/szar/Szar.java @@ -31,6 +31,7 @@ import net.minecraft.entity.damage.DamageType; import net.minecraft.entity.data.DataTracker; import net.minecraft.entity.data.TrackedData; import net.minecraft.entity.data.TrackedDataHandlerRegistry; +import net.minecraft.entity.decoration.painting.PaintingVariant; import net.minecraft.entity.effect.StatusEffect; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.passive.VillagerEntity; @@ -718,8 +719,50 @@ public class Szar implements ModInitializer { }) ); }); - + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "axolotl"), + new PaintingVariant(32, 32) + ); + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "bloc"), + new PaintingVariant(32, 32) + ); + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "block_wave"), + new PaintingVariant(32, 32) + ); + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "bounce"), + new PaintingVariant(32, 32) + ); + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "chicken_jokey"), + new PaintingVariant(16, 16) + ); + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "frogs"), + new PaintingVariant(32, 32) + ); + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "matrix"), + new PaintingVariant(32, 32) + ); + Registry.register( + Registries.PAINTING_VARIANT, + new Identifier(MOD_ID, "nyansniffer"), + new PaintingVariant(32, 32) + ); } + + + public static ObeliskCoreBlockEntity findNearestObelisk(ServerWorld world, BlockPos center, int radius) { ObeliskCoreBlockEntity closest = null; double closestDistance = Double.MAX_VALUE; @@ -817,29 +860,34 @@ public class Szar implements ModInitializer { new Identifier(MOD_ID, "firtana"), new FirtanaItem(new Item.Settings()) ); - static VoxelShape shape23 = VoxelShapes.cuboid(0.25f, 0f, 0f, 0.75f, 0.25f, 0.125f); - static VoxelShape shape24 = VoxelShapes.cuboid(0.125f, 0f, 0.125f, 0.875f, 0.125f, 0.25f); - static VoxelShape shape25 = VoxelShapes.cuboid(0f, 0f, 0.25f, 1f, 0.125f, 0.75f); - static VoxelShape shape26 = VoxelShapes.cuboid(0.125f, 0f, 0.75f, 0.875f, 0.125f, 0.875f); - static VoxelShape shape27 = VoxelShapes.cuboid(0.25f, 0f, 0.875f, 0.75f, 0.25f, 1f); - static VoxelShape shape28 = VoxelShapes.cuboid(0f, 0.125f, 0.25f, 0.125f, 0.25f, 0.75f); - static VoxelShape shape29 = VoxelShapes.cuboid(0.875f, 0.125f, 0.25f, 1f, 0.25f, 0.75f); - static VoxelShape shape30 = VoxelShapes.cuboid(0.75f, 0.125f, 0.125f, 0.875f, 0.25f, 0.25f); - static VoxelShape shape31 = VoxelShapes.cuboid(0.75f, 0.125f, 0.75f, 0.875f, 0.25f, 0.875f); - static VoxelShape shape32 = VoxelShapes.cuboid(0.125f, 0.125f, 0.125f, 0.25f, 0.25f, 0.25f); - static VoxelShape shape33 = VoxelShapes.cuboid(0.125f, 0.125f, 0.75f, 0.25f, 0.25f, 0.875f); - static VoxelShape shape34 = VoxelShapes.cuboid(0.3125f, 0.313125f, 0.3125f, 0.6875f, 0.313125f, 0.6875f); - static VoxelShape shape35 = VoxelShapes.cuboid(0.4375f, 0.125f, 0.4375f, 0.5625f, 0.3125f, 0.5625f); - static VoxelShape ROULETTE_SHAPE = VoxelShapes.union(shape23, shape24, shape25, shape26, shape27, shape28, shape29, shape30, shape31, shape32, shape33, shape34, shape35); + public static final ScreenHandlerType ROULETTE_SCREEN_HANDLER_TYPE = + ScreenHandlerRegistry.registerExtended( + new Identifier(Szar.MOD_ID, "roulette"), + (syncId, inv, buf) -> { + BlockPos pos = buf.readBlockPos(); + BlockEntity be = inv.player.getWorld().getBlockEntity(pos); + if (!(be instanceof RouletteBlockEntity blockEntity)) { + throw new IllegalStateException("BlockEntity is not a RouletteBlockEntity"); + } + return new RouletteScreenHandler(syncId, inv, blockEntity); + } + ); public static final Block ROULETTE_BLOCK = Registry.register( Registries.BLOCK, new Identifier(MOD_ID, "roulette"), - new BasicRotatableModelBlock( + new RouletteBlock( AbstractBlock.Settings - .copy(Blocks.OAK_WOOD), - ROULETTE_SHAPE + .copy(Blocks.IRON_BLOCK) ) ); + public static final BlockEntityType ROULETTE_BLOCKENTITY = Registry.register( + Registries.BLOCK_ENTITY_TYPE, + new Identifier(MOD_ID, "roulette"), + FabricBlockEntityTypeBuilder.create( + RouletteBlockEntity::new, + ROULETTE_BLOCK + ).build(null) + ); public static final Item ROULETTE = Registry.register( Registries.ITEM, new Identifier(MOD_ID, "roulette"), diff --git a/src/main/resources/assets/szar/textures/gui/roulette.png b/src/main/resources/assets/szar/textures/gui/roulette.png new file mode 100644 index 0000000..bb27ed9 Binary files /dev/null and b/src/main/resources/assets/szar/textures/gui/roulette.png differ diff --git a/src/main/resources/assets/szar/textures/gui/roulette_ball.png b/src/main/resources/assets/szar/textures/gui/roulette_ball.png new file mode 100644 index 0000000..7228de6 Binary files /dev/null and b/src/main/resources/assets/szar/textures/gui/roulette_ball.png differ diff --git a/src/main/resources/assets/szar/textures/gui/roulette_middle_thingy.png b/src/main/resources/assets/szar/textures/gui/roulette_middle_thingy.png new file mode 100644 index 0000000..880b3f0 Binary files /dev/null and b/src/main/resources/assets/szar/textures/gui/roulette_middle_thingy.png differ diff --git a/src/main/resources/assets/szar/textures/gui/roulette_wheel.png b/src/main/resources/assets/szar/textures/gui/roulette_wheel.png new file mode 100644 index 0000000..bea726b Binary files /dev/null and b/src/main/resources/assets/szar/textures/gui/roulette_wheel.png differ diff --git a/src/main/resources/assets/szar/textures/gui/roulette_wheel_only.png b/src/main/resources/assets/szar/textures/gui/roulette_wheel_only.png new file mode 100644 index 0000000..e410c90 Binary files /dev/null and b/src/main/resources/assets/szar/textures/gui/roulette_wheel_only.png differ diff --git a/src/main/resources/assets/szar/textures/gui/roulette_wheel_project.paint b/src/main/resources/assets/szar/textures/gui/roulette_wheel_project.paint new file mode 100644 index 0000000..46c8e99 Binary files /dev/null and b/src/main/resources/assets/szar/textures/gui/roulette_wheel_project.paint differ diff --git a/src/main/resources/assets/szar/textures/painting/axolotl.png b/src/main/resources/assets/szar/textures/painting/axolotl.png new file mode 100644 index 0000000..35cfb92 Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/axolotl.png differ diff --git a/src/main/resources/assets/szar/textures/painting/axolotl.png.mcmeta b/src/main/resources/assets/szar/textures/painting/axolotl.png.mcmeta new file mode 100644 index 0000000..c5d457f --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/axolotl.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/painting/bloc.png b/src/main/resources/assets/szar/textures/painting/bloc.png new file mode 100644 index 0000000..e14aa96 Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/bloc.png differ diff --git a/src/main/resources/assets/szar/textures/painting/bloc.png.mcmeta b/src/main/resources/assets/szar/textures/painting/bloc.png.mcmeta new file mode 100644 index 0000000..7e77c64 --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/bloc.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/painting/block_wave.png b/src/main/resources/assets/szar/textures/painting/block_wave.png new file mode 100644 index 0000000..749191d Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/block_wave.png differ diff --git a/src/main/resources/assets/szar/textures/painting/block_wave.png.mcmeta b/src/main/resources/assets/szar/textures/painting/block_wave.png.mcmeta new file mode 100644 index 0000000..7e77c64 --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/block_wave.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/painting/bounce.png b/src/main/resources/assets/szar/textures/painting/bounce.png new file mode 100644 index 0000000..3ea2148 Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/bounce.png differ diff --git a/src/main/resources/assets/szar/textures/painting/bounce.png.mcmeta b/src/main/resources/assets/szar/textures/painting/bounce.png.mcmeta new file mode 100644 index 0000000..37d84f6 --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/bounce.png.mcmeta @@ -0,0 +1,4 @@ +{ + "animation": { + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/painting/chicken_jokey.png b/src/main/resources/assets/szar/textures/painting/chicken_jokey.png new file mode 100644 index 0000000..4fe9de4 Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/chicken_jokey.png differ diff --git a/src/main/resources/assets/szar/textures/painting/chicken_jokey.png.mcmeta b/src/main/resources/assets/szar/textures/painting/chicken_jokey.png.mcmeta new file mode 100644 index 0000000..c5d457f --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/chicken_jokey.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/painting/frogs.png b/src/main/resources/assets/szar/textures/painting/frogs.png new file mode 100644 index 0000000..3e9489f Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/frogs.png differ diff --git a/src/main/resources/assets/szar/textures/painting/frogs.png.mcmeta b/src/main/resources/assets/szar/textures/painting/frogs.png.mcmeta new file mode 100644 index 0000000..c5d457f --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/frogs.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 1 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/painting/matrix.png b/src/main/resources/assets/szar/textures/painting/matrix.png new file mode 100644 index 0000000..cec62c4 Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/matrix.png differ diff --git a/src/main/resources/assets/szar/textures/painting/matrix.png.mcmeta b/src/main/resources/assets/szar/textures/painting/matrix.png.mcmeta new file mode 100644 index 0000000..7e77c64 --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/matrix.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/assets/szar/textures/painting/nyansniffer.png b/src/main/resources/assets/szar/textures/painting/nyansniffer.png new file mode 100644 index 0000000..d3ef5d4 Binary files /dev/null and b/src/main/resources/assets/szar/textures/painting/nyansniffer.png differ diff --git a/src/main/resources/assets/szar/textures/painting/nyansniffer.png.mcmeta b/src/main/resources/assets/szar/textures/painting/nyansniffer.png.mcmeta new file mode 100644 index 0000000..7e77c64 --- /dev/null +++ b/src/main/resources/assets/szar/textures/painting/nyansniffer.png.mcmeta @@ -0,0 +1,5 @@ +{ + "animation": { + "frametime": 2 + } +} \ No newline at end of file diff --git a/src/main/resources/data/minecraft/tags/painting_variant/placeable.json b/src/main/resources/data/minecraft/tags/painting_variant/placeable.json new file mode 100644 index 0000000..b5775a0 --- /dev/null +++ b/src/main/resources/data/minecraft/tags/painting_variant/placeable.json @@ -0,0 +1,13 @@ +{ + "replace": false, + "values": [ + "szar:axolotl", + "szar:bloc", + "szar:block_wave", + "szar:bounce", + "szar:chicken_jokey", + "szar:frogs", + "szar:matrix", + "szar:nyansniffer" + ] +} \ No newline at end of file diff --git a/src/main/resources/data/szar/structures/casino.nbt b/src/main/resources/data/szar/structures/casino.nbt index 1d2bdc5..765c75c 100644 Binary files a/src/main/resources/data/szar/structures/casino.nbt and b/src/main/resources/data/szar/structures/casino.nbt differ