#GameLogic

1 messages · Page 1 of 1 (latest)

leaden dew
#

Give me a few to write up as best as I can. Maybe if I explain it and you point out stuff that doesn't make sense it'll help me sort

muted echo
#

okay sure

leaden dew
#

state:

public enum State {
    WAITING, STARTING, IN_PROGRESS, BOSS_FIGHT, PAUSE, ENDING, RESETTING
}

currentLevel: current game instance level. Used to activate many other things.

locations ---> getLocations(int currentLevel):
Uses the current level number to add the locations depending on the level.

Constructor

public DungeonGame(int dungeonGameID, World world) {
        plugin.getServer().getPluginManager().registerEvents(this, plugin);

        state = State.RESETTING; <----------- Sets game state as resetting
        players = new ArrayList<>();
        spectators = new ArrayList<>();

        locations = new Locations(world); <---------- Instance of locations which stores spawn locations as well as start locations etc.
        currentLevel = 1;   <-------- Initializes default level to 1

        mythicMob = null;
        new BukkitRunnable() {
            @Override
            public void run() {
                activateDungeon();
            }
        }.runTaskTimer(plugin, 0, 30);
    }

activateDungeon is the infinite loop that runs and decides the next thing to do in the game

public void activateDungeon() {

        switch (state) {
            case WAITING -> { 
                messagePlayers("&rThe dungeon is waiting for players!");
            }
            case STARTING -> {
                if (players.size() >= 1) {
                    leader = players.get(0);
                    state = State.PAUSE; <-------- Sets the state to pause because players need to get teleported from the "lobby" area to the first level spawn and will wait for the leader to type /start
                    break;
                }
            }
            case IN_PROGRESS -> {
                generateLevel();  <----- This does the spawning for stuff for the current level. method below
            }
            case PAUSE -> {
                generateLevel();  <----- This does the spawning for stuff for the current level. method below
                titlePlayers("&2&l/dm next &rto continue!", "Waiting for &2&lleader &rto resume the dungeon!"); <---- Wait for leader to change gamestate with command
            }
            case ENDING -> {
                messagePlayers("&rThe dungeon is ending!");
                if (players.size() == 0) {
                    state = State.RESETTING;
                    break;
                }
            }
            case RESETTING -> {
                messagePlayers("&rThe dungeon is resetting!");
                currentLevel = 1;
                resetVariables();
                addLocations(currentLevel);
                state = State.WAITING;
            }
        }
    }

This method is used to begin the dungeon the first time only.

    public void start() {
        state = State.STARTING;
    }

This method is used to begin each level in the game.

    public void ready() {
        state = State.IN_PROGRESS;
    }

GenerateLevel()

private void generateLevel() {
        new BukkitRunnable() {
            @Override
            public void run() {
                if (killCount >= Level.getKillGoal(currentLevel)) {
                    spawnBoss();
                    cancel(); <----- level goal reached
                }
                if (spawnedCount > 40)
                    return; <----- Ignore but this is just to prevent overspawn
                for (int i = 0; i < 10; i++) {
                    Location location = locations.getRandomLocation();<--- spawn logic, ignore
                    mythicMob.spawn(BukkitAdapter.adapt(location), 1); <--- spawn logic, ignore
                }

            }
        }.runTaskTimer(plugin, 10, 10);
    }
#

Not saying it's not working or it is but:

What I want to accomplish is that before the first player joins all the firstlevel currentLevel = 1 locations are loaded. The player then gets teleported to the waiting area

Once the player does /start -> He gets teleported to the start location of the first level. Level plays out, etc

After the level finishes:
Player is teleported to the location of level2 which is only added when addLocations() -> Uses the current level is called.

Gamestate is waiting until player types /ready

When he does, generate level starts to create and then repeats itself

#

@fallen vigil @muted echo noti

muted echo
#

ok

leaden dew
#

I hope i explained it correctly, I can provide the full code but I removed all the stuff in the middle to make it as easily readable as possible

muted echo
#

looks like a standard state machine

leaden dew
#

Ok so it makes sense to you? right?

muted echo
#

so is teh goal that any player can start at any time

leaden dew
#

Start or ready?

muted echo
#

or do you just want the dungeon to start the game regardless of how many people are in it

#

like whats the user experience gonna be

leaden dew
#

It can be played as 1 or more than one so yes. Start when the player wants

muted echo
#

okay

leaden dew
#

If they want to have teammates they can. first player to join is set as the leader. that's all working

muted echo
#

so for each group of players there is a dungeon

leaden dew
#

Yes

muted echo
#

and each dungeon is this statemachine

leaden dew
#

Correct

#

Currently just having 1 dungeon up

leaden dew
#

Each dungeongame can only have 1 group of players

muted echo
#

yes thats what I said

#

its a 1 to 1 relation

leaden dew
#

Yes yes perfect

#

Now

#

When no players have joined

#

Is working perfectly

muted echo
#

seems to work fine

leaden dew
#

And here were the issues begin

muted echo
#

rip server xD

leaden dew
#

lmao

#

Let me put some messages on the console to explain

muted echo
#

so the issue is that it goes to pause when the game starts?

leaden dew
#

Nono the issue is that when /start is used. It should teleport you to the locationof the level and you need to type /ready to begin the level

#

first red dot is the command which calls this

    public void start() {
        state = State.STARTING;
    }
#

Second and third (ignore third )

private void generateLevel() {
        new BukkitRunnable() {
            @Override
            public void run() {
                if (killCount >= Level.getKillGoal(currentLevel)) {
                    spawnBoss();
                    cancel(); <----- level goal reached
                }
                if (spawnedCount > 40)
                    return; <----- Ignore but this is just to prevent overspawn
                for (int i = 0; i < 10; i++) {
                    Location location = locations.getRandomLocation();<--- spawn logic, ignore
                    mythicMob.spawn(BukkitAdapter.adapt(location), 1); <--- spawn logic, ignore
                }

            }
        }.runTaskTimer(plugin, 10, 10);
    }
muted echo
#

when is generate called

leaden dew
#

Here is what I think I did wrong. It's being called both in inprogress and pause

muted echo
#

have you even made a state diagram?

leaden dew
#

Wait I think just talking to you gave me the solution because of the questions you asked

leaden dew
muted echo
#

its a map of all your states with arrows between them for each transition

#

then you can visually see what your state will be and how to get to another state

leaden dew
#

I assume I make that manually like a uml unless intelliJ

muted echo
#

yes its an uml state diagram, but i dont think intellij can make those

#

since its more removed from teh code as it doesnt define the implementation, but just the logic

leaden dew
#

Alright let me think about it

muted echo
#

like something like this, but for your game

#

where each block is a state

leaden dew
#

What tool did you use for that

muted echo
#

google images

leaden dew
#

Oh lmao

muted echo
leaden dew
#

Perfect, will do right away. be bask in a bit

muted echo
#

also there are probably better ways to implement the state machine, especially if it is going to be big

#

but one thing at a time

leaden dew
#

I would like to read or see more stuff about that. would be really useful

#

Yeah for sure let me draw this up

#

Wait do I think of this as what I currently have or what I want?

muted echo
#

what you want

#

I mean if you did it right they should be the same

#

so just design it to how you think the game should work

leaden dew
#

@muted echo

muted echo
#

okay

#

so where would you place starting

leaden dew
#

I think I want that, correct?

muted echo
#

idk what you want xD

leaden dew
#

lmao

muted echo
#

this just means that there is no way to go to waiting, unless you create a new dungeon

#

if that's is what you want then its fine

#

if a state is instant, there might not even be a reason for it

leaden dew
#

Let me change the diagram then 1 serc

muted echo
#

like starting, from what I saw its like a transition between waiting and paused

leaden dew
#

Yes, indeed

#

Wait no this diag is wrong

muted echo
#

well as a general rule of thumb, if a state is instant like that, it probably shouldnt be a state at all

leaden dew
muted echo
#

since it will only occur in the transition between waiting and pause, and its instant

leaden dew
#

Changed it up

#

That's how I want it

#

/start only once and /ready each level

#

You're right tho prob can remove starting and make /start still take you to pause

muted echo
#

yes

leaden dew
#

Alright baby steps here but I'm understanding everything

#
        switch (state) {
            case WAITING -> {
            }
            case PAUSE -> {
            }
            case IN_PROGRESS -> {
            }
            case BOSS_FIGHT -> {
            }
            case RESETTING -> {
            }
        }
``` Alright rewriting the method to start fresh
#

So according to what I'm doing. If i need the locations for the upcoming level I would need to add them after islastlevel since before the first level they are already loaded from the constructor

#
    public void activateDungeon1() {
        //Generate switch logic with no code inside of them
        switch (state) {
            case WAITING -> {
                messagePlayers("&rThe dungeon is waiting for players!");
                setWorldBorder();
            }
            case PAUSE -> {
                setWorldBorder();
                titlePlayers("&2&l/dm ready &rto continue!", "Waiting for &2&lleader &rto resume the dungeon!");
            }
            case IN_PROGRESS -> {
                generateLevel();
                setWorldBorder();
            }
            case BOSS_FIGHT -> {

            }
            case ENDING -> {
                if (players.size() != 0) {
                    getPlayers().forEach(dungeonPlayer -> {
                        dungeonPlayer.getPlayer().setGameMode(GameMode.SURVIVAL);
                        dungeonPlayer.getPlayer().teleport(Bukkit.getWorld("spawn").getSpawnLocation());
                        removePlayer(dungeonPlayer.getPlayer());
                        TitleManager.sendTitleWithPrefix(dungeonPlayer.getPlayer(), "Resetting, You have been teleported to spawn!");
                    });
                }
                if (spectators.size() != 0) {
                    getSpectators().forEach(dungeonSpectator -> {
                        dungeonSpectator.getPlayer().setGameMode(GameMode.SURVIVAL);
                        dungeonSpectator.getPlayer().teleport(Bukkit.getWorld("spawn").getSpawnLocation());
                        TitleManager.sendTitleWithPrefix(dungeonSpectator.getPlayer(), "Resetting, You have been teleported to spawn!");
                        removeSpectator(dungeonSpectator.getPlayer());
                    });
                }
            }
            case RESETTING -> {
                leader = null;
                currentLevel = 1;
                resetVariables();
                addLocations(currentLevel);
                state = State.WAITING;
            }
        }
    }
``` polished that a bunch
muted echo
#

yeah this looks nice

#

and then I assume most state changes are called by like commands or whatever

#

like waiting -> paused by /start

leaden dew
#

Yes

#

It's actually working now

#

Holy shit

#

Thanks steaf!

muted echo
#

np

#

but you did all the work though xD

leaden dew
muted echo
#

true