move slot machine functionality to the blockentity

This commit is contained in:
2026-03-04 08:47:25 +01:00
parent 69428bdca3
commit fef55c6d68
4 changed files with 154 additions and 110 deletions

View File

@@ -157,7 +157,10 @@ public class SlotMachineScreen extends HandledScreen<SlotMachineScreenHandler> {
int guiLeft = (width - backgroundWidth) / 2;
int guiTop = (height - backgroundHeight) / 2;
if (handler.blockEntity.isHandleClicked(inventory.player)) {
handleClicked = true;
handleAnimTicks = 0;
}
// Handle animation
if (handleClicked) {
handleAnimTicks++;

View File

@@ -178,4 +178,16 @@ public class SlotMachineBlock extends Block implements BlockEntityProvider {
}
return state;
}
@Override
public <T extends BlockEntity> BlockEntityTicker<T> getTicker(
World world,
BlockState state,
BlockEntityType<T> type) {
return type == Szar.SLOT_MACHINE_BLOCKENTITY
? (world1, pos, state1, blockEntity) ->
SlotMachineBlockEntity.tick(world1, pos, state1, (SlotMachineBlockEntity) blockEntity)
: null;
}
}

View File

@@ -3,11 +3,14 @@ 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.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.util.ItemScatterer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction;
@@ -17,6 +20,18 @@ import java.util.Random;
public class SlotMachineBlockEntity extends BlockEntity {
// ===== TIMING CONFIG =====
public static final int PREPARE_TIME = 35;
public static final int FAST_SPIN_TIME = 35;
public static final int LOCK_INTERVAL = 8;
private static final int RESULT_VIEW_TIME = 80;
private static final int IDLE_SPEED = 20;
private static final int PREPARE_SPEED = 8;
private static final int FAST_SPEED = 1;
private final Random random = new Random();
public final int[] currentSymbol = new int[3];
public final int[] finalSymbol = new int[3];
public static final int TOTAL_SYMBOLS = 7;
@@ -26,9 +41,15 @@ public class SlotMachineBlockEntity extends BlockEntity {
private ItemStack currentBetStack = ItemStack.EMPTY;
private boolean forceWin = false;
private int winTier = 0; // 0 = fruit, 1 = golden apple small, 2 = golden apple jackpot
private boolean isHandleClicked = false;
private PlayerEntity clickedplayer;
private int handleClickWaittime = 0;
final PropertyDelegate propertyDelegate;
public SlotMachineBlockEntity(BlockPos pos, BlockState state) {
super(Szar.SLOT_MACHINE_BLOCKENTITY, pos, state);
this.propertyDelegate = new ArrayPropertyDelegate(2);
}
public void setSymbols(int s0, int s1, int s2) {
@@ -105,6 +126,8 @@ public class SlotMachineBlockEntity extends BlockEntity {
public boolean getForceWin() {return forceWin;}
public void setwinTier(int winTier) {this.winTier = winTier;}
public int getwinTier() {return winTier;}
public boolean isHandleClicked(PlayerEntity player) {return clickedplayer != player ? isHandleClicked : false;}
public void setHandleClicked(boolean isHandleClicked, PlayerEntity player) {this.isHandleClicked = isHandleClicked; this.clickedplayer = player;}
void finishSpin() {
if (getForceWin()) {
@@ -129,4 +152,112 @@ public class SlotMachineBlockEntity extends BlockEntity {
setcurrentBetAmount(0);
setcurrentBetStack(ItemStack.EMPTY);
}
public static void tick(World world, BlockPos pos, BlockState state, SlotMachineBlockEntity blockEntity) {
if (world.isClient) return;
if (blockEntity.isHandleClicked) {
blockEntity.handleClickWaittime++;
}
if (blockEntity.handleClickWaittime >= 1) {
blockEntity.isHandleClicked = false;
}
// old sendcontentupdates
if (!blockEntity.getSpinning()) {
if (blockEntity.getWorld().getTime() % IDLE_SPEED == 0) {
System.out.println("setting random symbols");
blockEntity.setSymbols(
blockEntity.random.nextInt(7),
blockEntity.random.nextInt(7),
blockEntity.random.nextInt(7)
);
}
return;
}
blockEntity.setspinTimer(blockEntity.getspinTimer() + 1);
int totalSpinDuration =
PREPARE_TIME +
FAST_SPIN_TIME +
LOCK_INTERVAL * 3 +
RESULT_VIEW_TIME;
int speed = switch (blockEntity.getspinTimer() < PREPARE_TIME ? 0 : blockEntity.getspinTimer() < PREPARE_TIME + FAST_SPIN_TIME ? 1 : 2) {
case 0 -> PREPARE_SPEED;
case 1 -> FAST_SPEED;
default -> FAST_SPEED;
};
boolean lock0 = blockEntity.getspinTimer() >= PREPARE_TIME + FAST_SPIN_TIME + LOCK_INTERVAL;
boolean lock1 = blockEntity.getspinTimer() >= PREPARE_TIME + FAST_SPIN_TIME + LOCK_INTERVAL * 2;
boolean lock2 = blockEntity.getspinTimer() >= PREPARE_TIME + FAST_SPIN_TIME + LOCK_INTERVAL * 3;
int reel0 = lock0 ? blockEntity.getFinalSymbol(0) : blockEntity.random.nextInt(7);
int reel1 = lock1 ? blockEntity.getFinalSymbol(1) : blockEntity.random.nextInt(7);
int reel2 = lock2 ? blockEntity.getFinalSymbol(2) : blockEntity.random.nextInt(7);
if (blockEntity.getspinTimer() % speed == 0) {
blockEntity.setSymbols(reel0, reel1, reel2);
}
if (blockEntity.getspinTimer() >= (totalSpinDuration - RESULT_VIEW_TIME + 15)) {
blockEntity.propertyDelegate.set(1, blockEntity.getForceWin() ? 1 : 0);
}
if (blockEntity.getspinTimer() >= totalSpinDuration) {
blockEntity.finishSpin();
blockEntity.setSpinning(false);
blockEntity.propertyDelegate.set(0, 0);
}
}
public boolean onButtonClicked(PlayerEntity player, SlotMachineBlockEntity blockEntity, SimpleInventory betInventory) {
blockEntity.setHandleClicked(true, player);
ItemStack bet = betInventory.getStack(0);
if (bet.isEmpty()) return false;
blockEntity.setcurrentBetAmount(bet.getCount());
blockEntity.setcurrentBetStack(bet.copy());
betInventory.setStack(0, ItemStack.EMPTY);
// === Determine if this spin will definitely win (40%) ===
blockEntity.setForceWin(random.nextFloat() < 0.4f);
if (blockEntity.getForceWin()) {
float tierRoll = random.nextFloat();
if (tierRoll < 0.88f) blockEntity.setwinTier(0); // 88%
else if (tierRoll < 0.98f) blockEntity.setwinTier(1); // 10%
else blockEntity.setwinTier(2); // 2%
} else {
blockEntity.setwinTier(-1);
}
// === Preselect final symbols based on forced win type ===
if (blockEntity.getForceWin()) {
switch (blockEntity.getwinTier()) {
case 0 -> { // fruit
int symbol = SlotSymbol.symbolToInt(SlotSymbol.rollFruit(random));
blockEntity.setFinalSymbols(symbol, symbol, symbol);
}
case 1 -> { // golden apple small
int symbol = SlotSymbol.symbolToInt(SlotSymbol.BELL);
blockEntity.setFinalSymbols(symbol, symbol, symbol);
}
case 2 -> { // jackpot
int symbol = SlotSymbol.symbolToInt(SlotSymbol.SEVEN);
blockEntity.setFinalSymbols(symbol, symbol, symbol);
}
}
} else {
blockEntity.setFinalSymbols(SlotSymbol.symbolToInt(SlotSymbol.roll(random)), SlotSymbol.symbolToInt(SlotSymbol.roll(random)), SlotSymbol.symbolToInt(SlotSymbol.roll(random)));
if (blockEntity.getFinalSymbol(0) == blockEntity.getFinalSymbol(1) && blockEntity.getFinalSymbol(1) == blockEntity.getFinalSymbol(2)) {
blockEntity.setForceWin(true);
blockEntity.setwinTier(SlotSymbol.intToSymbol(blockEntity.getFinalSymbol(0)) == SlotSymbol.BELL ? 1 : SlotSymbol.intToSymbol(blockEntity.getFinalSymbol(0)) == SlotSymbol.SEVEN ? 2 : 0);
}
}
blockEntity.setspinTimer(0);
blockEntity.setSpinning(true);
blockEntity.propertyDelegate.set(0, 1);
return true;
}
}

View File

@@ -16,29 +16,19 @@ import java.util.Random;
public class SlotMachineScreenHandler extends ScreenHandler {
// ===== TIMING CONFIG =====
public static final int PREPARE_TIME = 35;
public static final int FAST_SPIN_TIME = 35;
public static final int LOCK_INTERVAL = 8;
private static final int RESULT_VIEW_TIME = 80;
private static final int IDLE_SPEED = 20;
private static final int PREPARE_SPEED = 8;
private static final int FAST_SPEED = 1;
public final SlotMachineBlockEntity blockEntity;
private final SimpleInventory betInventory = new SimpleInventory(1);
private final PlayerInventory playerInventory;
private final PropertyDelegate propertyDelegate;
private final Random random = new Random();
public SlotMachineScreenHandler(int syncId, PlayerInventory playerInv, SlotMachineBlockEntity blockEntity) {
super(Szar.SLOT_MACHINE_SCREEN_HANDLER_TYPE, syncId);
this.playerInventory = playerInv;
this.blockEntity = blockEntity;
this.propertyDelegate = new ArrayPropertyDelegate(2);
this.addProperties(propertyDelegate);
this.addProperties(blockEntity.propertyDelegate);
// Bet slot
this.addSlot(new Slot(betInventory, 0, 44, 35));
@@ -54,106 +44,14 @@ public class SlotMachineScreenHandler extends ScreenHandler {
@Override
public boolean onButtonClick(PlayerEntity player, int id) {
if (id != 0 || blockEntity.getSpinning()) return false;
ItemStack bet = betInventory.getStack(0);
if (bet.isEmpty()) return false;
blockEntity.setcurrentBetAmount(bet.getCount());
blockEntity.setcurrentBetStack(bet.copy());
betInventory.setStack(0, ItemStack.EMPTY);
// === Determine if this spin will definitely win (40%) ===
blockEntity.setForceWin(random.nextFloat() < 0.4f);
if (blockEntity.getForceWin()) {
float tierRoll = random.nextFloat();
if (tierRoll < 0.88f) blockEntity.setwinTier(0); // 88%
else if (tierRoll < 0.98f) blockEntity.setwinTier(1); // 10%
else blockEntity.setwinTier(2); // 2%
} else {
blockEntity.setwinTier(-1);
}
// === Preselect final symbols based on forced win type ===
if (blockEntity.getForceWin()) {
switch (blockEntity.getwinTier()) {
case 0 -> { // fruit
int symbol = SlotSymbol.symbolToInt(SlotSymbol.rollFruit(random));
blockEntity.setFinalSymbols(symbol, symbol, symbol);
}
case 1 -> { // golden apple small
int symbol = SlotSymbol.symbolToInt(SlotSymbol.BELL);
blockEntity.setFinalSymbols(symbol, symbol, symbol);
}
case 2 -> { // jackpot
int symbol = SlotSymbol.symbolToInt(SlotSymbol.SEVEN);
blockEntity.setFinalSymbols(symbol, symbol, symbol);
}
}
} else {
blockEntity.setFinalSymbols(SlotSymbol.symbolToInt(SlotSymbol.roll(random)), SlotSymbol.symbolToInt(SlotSymbol.roll(random)), SlotSymbol.symbolToInt(SlotSymbol.roll(random)));
if (blockEntity.getFinalSymbol(0) == blockEntity.getFinalSymbol(1) && blockEntity.getFinalSymbol(1) == blockEntity.getFinalSymbol(2)) {
blockEntity.setForceWin(true);
blockEntity.setwinTier(SlotSymbol.intToSymbol(blockEntity.getFinalSymbol(0)) == SlotSymbol.BELL ? 1 : SlotSymbol.intToSymbol(blockEntity.getFinalSymbol(0)) == SlotSymbol.SEVEN ? 2 : 0);
}
}
blockEntity.setspinTimer(0);
blockEntity.setSpinning(true);
propertyDelegate.set(0, 1);
return true;
return blockEntity.onButtonClicked(player, blockEntity, betInventory);
}
/*
@Override
public void sendContentUpdates() {
super.sendContentUpdates();
if (!blockEntity.getSpinning()) {
if (blockEntity.getWorld().getTime() % IDLE_SPEED == 0) {
blockEntity.setSymbols(
random.nextInt(7),
random.nextInt(7),
random.nextInt(7)
);
}
return;
}
blockEntity.setspinTimer(blockEntity.getspinTimer() + 1);
int totalSpinDuration =
PREPARE_TIME +
FAST_SPIN_TIME +
LOCK_INTERVAL * 3 +
RESULT_VIEW_TIME;
int speed = switch (blockEntity.getspinTimer() < PREPARE_TIME ? 0 : blockEntity.getspinTimer() < PREPARE_TIME + FAST_SPIN_TIME ? 1 : 2) {
case 0 -> PREPARE_SPEED;
case 1 -> FAST_SPEED;
default -> FAST_SPEED;
};
boolean lock0 = blockEntity.getspinTimer() >= PREPARE_TIME + FAST_SPIN_TIME + LOCK_INTERVAL;
boolean lock1 = blockEntity.getspinTimer() >= PREPARE_TIME + FAST_SPIN_TIME + LOCK_INTERVAL * 2;
boolean lock2 = blockEntity.getspinTimer() >= PREPARE_TIME + FAST_SPIN_TIME + LOCK_INTERVAL * 3;
int reel0 = lock0 ? blockEntity.getFinalSymbol(0) : random.nextInt(7);
int reel1 = lock1 ? blockEntity.getFinalSymbol(1) : random.nextInt(7);
int reel2 = lock2 ? blockEntity.getFinalSymbol(2) : random.nextInt(7);
if (blockEntity.getspinTimer() % speed == 0) {
blockEntity.setSymbols(reel0, reel1, reel2);
}
if (blockEntity.getspinTimer() >= (totalSpinDuration - RESULT_VIEW_TIME + 15)) {
propertyDelegate.set(1, blockEntity.getForceWin() ? 1 : 0);
}
if (blockEntity.getspinTimer() >= totalSpinDuration) {
blockEntity.finishSpin();
blockEntity.setSpinning(false);
propertyDelegate.set(0, 0);
}
}
}*/
@Override
public boolean canUse(PlayerEntity player) {
@@ -194,6 +92,6 @@ public class SlotMachineScreenHandler extends ScreenHandler {
}
public PropertyDelegate getPropertyDelegate() {
return propertyDelegate;
return blockEntity.propertyDelegate;
}
}