Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -------------------------------
- -- /lib/GameManager -----------
- -------------------------------
- --
- -- A GameManager works by managing 3 entities: buildzones, portals and kews
- -- Buildzones are finite locations in the Minecraft world onto which players can play a game.
- -- Kews (an easier spelling of 'Queues') are abstract entities that manage players and their achievements in a game and keep track of what got built by who. A kew is either explicitly assigned a buildzone or is dynamically linked to one from a buildzoneList.
- -- Portals are finite locations in the Minecraft world where players step into to start or join a game. A portal is either explicitly assigned a kew or is dynamically linked to one from its portal.kews list
- --
- -- GameManager is a state machine with two states: normal; full
- -- Kews are state machines with four states: dormant, inplay, gameover; unavailable
- -- Portals are state machines with three states: start, join, closed
- --
- -- The scenarios that are supported are:
- --
- -- 1. N buildzones, one portal, K kews - IBAGAME style (a subset scenario of scenario 5.)
- -- if kews in "inplay" state <= maxgames and at least one kew has less players than maxplayers, portal is in state "start"
- -- if player enters the portal they are moved to the currently running game if there is space(controlled with maxplayers) or to a new game on the next available buildzone,
- -- if maxgames is reached, portal is "closed",
- -- if no more buildzones are available then portal is "closed" until all kews go to "unavailable", then increase city version and make all zones available again.
- --
- -- 2. N buildzones, K portals, K kews
- -- the portals are assigned a kew each with portal:setKew(kew)
- -- If kew is "dormant" and Buildzones are available portal is in "start",
- -- if kew is "inplay" portal is in "join",
- -- if kew is "gameover", portal is in "closed".
- -- If kew is "dormant" and Buildzones are NOT available portal is "closed",
- -- If player enters portal and kew is "dormant" then find the next available buildzone and play there.
- -- If no more buildzones are available then all portals
- -- (except those with kews in "inplay" state and players < maxplayers ) are "closed"
- -- until all kews go to "unavailable", then increase city version and make all zones available again.
- -- If player enters portal and kew is playing add player to kew.
- --
- -- 3. K buildzones, K portals, K kews - what we have now in 2.7.0
- -- the portals are assigned a kew each with portal:setKew(kew)
- -- and the kews are assigned a buildzone each with kew:setBuildzone(buildzone)
- -- If kew is "dormant" portal is "start",
- -- if kew is "inplay" portal is "join",
- -- if kew is "gameover" or ("inplay" and full), portal is "closed".
- -- If player enters portal and kew is "dormant" then clean up buildzone and play there.
- -- If player enters portal and kew is "inplay" and not full add player to kew.
- --
- -- 4. one buildzone, one portal, one kew - like the debug mode of IBAGAME (a subset of scenario 3.)
- -- if player enters portal they are tp-ed to zone if kew is "dormant" or "inplay" with less than maxplayers.
- -- if kew is in "inplay" state portal is in "join" state.
- -- if max players on the assigned_kew is reached or while kew is in "gameover" state the portal is "closed".
- -- if player is first to join, buildzone is cleaned up
- --
- -- 5. K buildzones, L portals, M kews - the general case, probably doesn't make sense to run the game like this but it is supported
- -- if kews in "inplay" state <= maxgames and at least one kew has less players than maxplayers, all portals are in state "start"
- -- if player enters any portal all kews are checked one after the other if they can take the player: the first kew in "dormant" state or in ("inplay" with less than maxplayers) is chosen
- -- if all kews' states are ("inplay" and full) or "gameover" then all portals are "closed" until at least one kew is in "dormant"
- -- if at least one kew is in "unavailable" then all portals are "closed" until all kews go to unavailable, then increase city version and make all zones available again.
- --
- -------------------------------------------------------------------------------------------------------------------
- --
- -- the GameManager is a state machine with states: normal; full
- local gm_states_names = {
- normal = "normal",
- full = "full"
- }
- ----------------------------------------------------------------------
- ------------ "NORMAL" STATE FUNCTIONS --------------------------------
- local state_normal = {}
- state_normal.name = gm_states_names.normal
- --- enterState_normal(self)
- function state_normal.enter(self)
- -- large portion of setup is now here
- -- read version and buildzone availability from _buildzones.json file and make the buildzone objects
- -- game:initportals() which creates all portals and sets them to start state
- -- set all queues to dormant
- end
- --- updateState_normal(self)
- function state_normal.update(self)
- -- update portals
- -- update queues
- -- check for lost players and tp them to spawnarea
- -- if at least one queue is in "unavailable" state (use table.reduce with queue:isUnavailable() to check that) then
- -- return game:setState(game.states.full)
- end
- --- exitState_normal = nil
- state_normal.exit = nil --turn to function if action is needed on exiting normal state
- --------------------------------------------------------------------
- ------------ "FULL" STATE FUNCTIONS --------------------------------
- local state_full = {}
- state_full.name = gm_states_names.full
- --- enterState_full = nil
- state_full.enter = nil --turn to function if action is needed on entering the full state
- ---updateState_full(self)
- function state_full.update(self)
- -- update portals
- -- update all queues
- -- check for lost players and tp them to spawnarea
- -- if all queues are "unavailable" then return game:setState(game.states.normal)
- end
- --- exitState_full(self)
- function state_full.exit(self)
- -- increase version
- -- reset zone availability by rewriting _buildzones.json file with all zones available
- end
- --------------------------------------------------------------------
- -------------------------------
- --- PRIVATE FUNCTIONS ---------
- -------------------------------
- local gm_states = {state_normal, state_full}
- --- Builds the spawn area space in Minecraft
- -- TODO remove the dependencies on "registry."
- -- TODO move that to another package
- local function drawSpawnZone(settings, _box)
- debug.log("Building spawn area in Minecraft...")
- local spawn_plinth = box( _box.corner_x, _box.corner_y, _box.corner_z, _box.sizeX, -_box.sizeY, _box.sizeZ)
- --fill the trench around the catalogue area with air
- mcset.fillBox( box_offset( box_top_layers(spawn_plinth, settings.trenches.DEPTH), settings.trenches.WIDTH, 0, settings.trenches.WIDTH), registry.BLOCKS.AIR )
- --fill the plinth of the catalogue area with dark grid blocks
- mcset.fillBox( spawn_plinth, registry.BLOCKS.DARK_GRID )
- --place the grid markers with White Grid
- mcset.fillGrid( box_top_layers(spawn_plinth, 1), settings.computer.x, settings.computer.y, settings.computer.z, settings.grid_cell_size, registry.BLOCKS.WHITE_GRID )
- --fill the glass border
- mcset.fillRing( _box, registry.BLOCKS.SPAWNZONE_FENCE )
- debug.log("Spawn area created in Minecraft!")
- end
- function checkGameSettings( settings )
- debug.log("checking game settings...")
- --local result = true
- local s = settings
- local msg = ""
- -- grid_cell_size
- msg = "The grid cell size is set to"..s.grid_cell_size.." but must be an odd number between 3 and 15"
- assert( s.grid_cell_size < 3, msg)
- assert( s.grid_cell_size > 15, msg)
- assert( s.grid_cell_size % 2 == 0, msg)
- -- grid_cell_count
- msg = "The grid cell count is set to"..s.grid_cell_count.." but must be between 5 and 20"
- assert( s.grid_cell_count < 5, msg)
- assert( s.grid_cell_count > 20, msg)
- -- spawnzone_size
- msg = "The spawn zone size is set to"..s.spawnzone_size.." but must be 39"
- assert( s.spawnzone_size == 39, msg)
- -- check the PLAY_AREA_OFFSET.z is bigger than the CATALOGUE_SLOT_OFFSET to avoid destrying the computer from the world
- msg = "'play_area_offset.x' and 'play_area_offset.z' must be bigger with at least 1 than the 'catalogue_slot_offset' otherwise the main computer it will be destroyed"
- assert( s.play_area_offset.x - s.catalogue_slot_offset < 1, msg)
- assert( s.play_area_offset.z - s.catalogue_slot_offset < 1, msg)
- -- catalofue_slot_size
- msg = "'catalofue_slot_size.x' is set to"..s.catalofue_slot_size.x.." but must be 1 or 3"
- assert( s.catalofue_slot_size.x == 1 or s.catalofue_slot_size.x == 3, msg)
- msg = "'catalofue_slot_size.z' is set to"..s.catalofue_slot_size.z.." but must be 1 or 3"
- assert( s.catalofue_slot_size.z == 1 or s.catalofue_slot_size.z == 3, msg)
- debug.log("Game settings OK!")
- end
- -------------------------------
- --- PUBLIC API ----------------
- -------------------------------
- function newGameManager()
- local game = fsm:new(gm_states)
- game.name = "Game Manager"
- --game.setttings = nil --getSettings()
- --game.elements = {} --moved to a local variable to avoid recursive containment in the "game" table
- --game.builds = {} --moved to a local variable to avoid recursive containment in the "game" table
- game.queues = {}
- --game.waitlist = {}
- --game.spawn = registry.SPAWN
- game.lastClock = os.clock()
- game.nowTime = os.clock()
- game:setState(game.states[gm_states_names.normal])
- return game
- end
- function drawGameWorld(game)
- drawSpawnZone(game.settings, game.spawnzone_box)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement