Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local VERSION = '0.8.5 - extended XML export with buildings coordinates'
- os.loadAPI('tracker')
- os.loadAPI('json')
- print("Starting 20.000 Blocks")
- DEBUG_MODE = false
- local monitor = peripheral.wrap("right")
- local ox,oy,oz = commands.getBlockPosition()
- CITY_VERSION = 1 -- this denotes which iteration of the map is current. When the map is full, i.e. all buildzones have been played we replace it with an empty one and increase the city vesrion with 1
- SPAWN_VILLAGER = false
- DO_GRID = true
- GRID_HOLE_CHANCE = 0
- NUMBER_OF_BUILDZONES = 6
- NUMBER_OF_VOCAB = 10
- GAME_LENGTH = 600
- VOCAB_WIDTH = 27
- VOCAB_HEIGHT = 19
- BUILDZONE_WIDTH = 62 -- the actual zone width is 63 blocks, but for some reason due to how minecraft handles relative coordinates this has to be 62
- BUILDZONE_FLOOR_HEIGHT = -1
- SPAWN = {
- x=12110,
- y=57,
- z=-1777,
- a1=90,
- a2=0
- }
- FIRSTZONE= {
- x=11685,
- y=57,
- z=-1869
- }
- WAITZONE = {
- x=12093,
- y=56,
- z=-1779,
- w=5,
- l=5
- }
- VICTORY_HEIGHT = 30
- VICTORY_TOTAL = 50
- VICTORY_SPECIFIC = {name='garden',count=101}
- DEFAULT_REWARD = 'minecraft:emerald 2 0 {display:{Name:"Emerald",Lore:[Trade this to the villager for wool]}}'
- WOOL_PER_EMERALD = 64
- PICKAXE_USES = 40
- BLOCKS = {
- CAMP_FLOOR = {block='minecraft:sandstone',data=0},
- CONSTRUCTION = {block='minecraft:diamond_ore',data=0},
- RING = {block='minecraft:diamond_ore',data=0},
- DETECT = {block='minecraft:red_sandstone',data=0},
- DETECT_DEAD = {block='minecraft:obsidian',data=0},
- VOCAB_DETECT = {block="minecraft:quartz_block",data=0},
- VOCAB_REPLACE = {block="minecraft:coal_block",data=0},
- VICTORY_MARKER = {block="minecraft:emerald_block",data=0},
- PLUG = {block="minecraft:lapis_ore",data=0},
- PHVFLOOR = {block="minecraft:stone_slab",data=3},
- BUILDING_HOUSE = {block="minecraft:wool",data=0},
- BUILDING_GARDEN = {block="minecraft:wool",data=13},
- BUILDING_WATER = {block="minecraft:wool",data=1},
- }
- --contains a list of all posible Buildzones (build a bit later)
- LOCS = {}
- if DEBUG_MODE then
- GAME_LENGTH = 12000
- NUMBER_OF_BUILDZONES = 1
- end
- --creates a grid of absolute references (0,0) (1,0)
- function buildGrid(w,h)
- local grid = {}
- for x=0,w-1 do
- for z=0,h-1 do
- table.insert(grid,{x=x,z=z})
- end
- end
- return grid
- end
- --sets where and how big the PHV area is
- --second number is along the long edge of PHV starting at the spawn side
- --first number is along the short edge of PHV starting from the park side
- if DEBUG_MODE then
- FIRSTZONE= {
- x=5,
- y=57,
- z=-7
- }
- LOCS = buildGrid(1,3)
- else
- LOCS = buildGrid(11,27)
- end
- --call these to return a proper minecraft item string including adventure mode properties
- function houseBlock(quant)
- text = BLOCKS.BUILDING_HOUSE.block..' '..quant..' '..BLOCKS.BUILDING_HOUSE.data..' {display:{Name:"House Construction Block",Lore:[Place this against a Diamond to build a house]},CanPlaceOn:["'..BLOCKS.BUILDING_HOUSE.block..'","'..BLOCKS.PLUG.block..'","'..BLOCKS.DETECT.block..'"]}'
- return text
- end
- function gardenBlock(quant)
- text = BLOCKS.BUILDING_GARDEN.block..' '..quant..' '..BLOCKS.BUILDING_GARDEN.data..' {display:{Name:"Garden Construction Block",Lore:[Place this against a Diamond to build a pond or pool]},CanPlaceOn:["'..BLOCKS.BUILDING_HOUSE.block..'","'..BLOCKS.PLUG.block..'","'..BLOCKS.DETECT.block..'"]}'
- return text
- end
- STARTING_ITEMS = {
- houseBlock(30), gardenBlock(30),
- 'stone_pickaxe 1 '..131-PICKAXE_USES..' {CanDestroy:["'..BLOCKS.BUILDING_HOUSE.block..'"],display:{Name:"Construction Remover",Lore:[Use this to remove up to '..PICKAXE_USES..' pieces of construction material]}}'
- }
- REWARDS = {}
- --Urban singlehouse rewards (costs 4 house, -2+2 activators)
- REWARDS[1] = gardenBlock(4)
- REWARDS[2] = gardenBlock(4)
- REWARDS[3] = gardenBlock(4)
- REWARDS[4] = gardenBlock(4)
- --Urban businesses rewards (costs 6 house, -2+1 activators)
- REWARDS[5] = gardenBlock(7)
- REWARDS[6] = gardenBlock(7)
- REWARDS[7] = gardenBlock(7)
- REWARDS[8] = gardenBlock(7)
- --Urban Tech&Science Spaces bridge rewards (costs 6 house, -3+2 activators)
- REWARDS[9] = gardenBlock(10)
- REWARDS[10] = gardenBlock(10)
- --Green Tech&Science Spaces garden bridge
- REWARDS[11] = gardenBlock(7)
- REWARDS[12] = gardenBlock(7)
- --House extention rewards (costs 4 house, 1 activators)
- REWARDS[13] = houseBlock(6)
- REWARDS[14] = houseBlock(6)
- REWARDS[15] = houseBlock(6)
- REWARDS[16] = houseBlock(6)
- --riser 2 (costs 12 house)
- REWARDS[17] = houseBlock(1)
- --riser 1 (costs 8 house)
- REWARDS[18] = houseBlock(1)
- --plaza city (costs 4 house, -1 activator)
- REWARDS[19] = houseBlock(1)
- --plaza park (costs 4 garden, -1 activator)
- REWARDS[20] = gardenBlock(3)
- --extention-farm (like extension rise) (costs 6 garden, -2 activators)
- REWARDS[21] = houseBlock(3)
- REWARDS[22] = houseBlock(3)
- REWARDS[23] = houseBlock(3)
- REWARDS[24] = houseBlock(3)
- --extension-private garden rewards (costs 3 garden, -1 activators)
- REWARDS[25] = "minecraft:emerald"
- REWARDS[26] = "minecraft:emerald"
- REWARDS[27] = "minecraft:emerald"
- REWARDS[28] = "minecraft:emerald"
- --L-shaped small business agriculture (costs 6 garden, -3+2 activators)
- REWARDS[29] = "minecraft:emerald 2"
- REWARDS[30] = "minecraft:emerald 2"
- REWARDS[31] = "minecraft:emerald 2"
- REWARDS[32] = "minecraft:emerald 2"
- --L-shaped small business urban (costs 6 housing, -3+2 activators)
- REWARDS[33] = gardenBlock(6)
- REWARDS[34] = gardenBlock(6)
- REWARDS[35] = gardenBlock(6)
- REWARDS[36] = gardenBlock(6)
- --green-roof houses (costs 4 garden, -2+2 activators)
- REWARDS[37] = houseBlock(4)
- REWARDS[38] = houseBlock(4)
- REWARDS[39] = houseBlock(4)
- REWARDS[40] = houseBlock(4)
- DEFAULT_NAME = 'default-vocab'
- VOCAB_NAMES = {
- 'freestand-house',
- 'freestand-house',
- 'freestand-house',
- 'freestand-house',
- 'dbl-ext-house',
- 'dbl-ext-house',
- 'dbl-ext-house',
- 'dbl-ext-house',
- 'bridge-house',
- 'bridge-house',
- 'bridge-garden',
- 'bridge-garden',
- 'ext-house',
- 'ext-house',
- 'ext-house',
- 'ext-house',
- 'riser-1',
- 'riser-2',
- 'city-garden',
- 'city-plaza',
- 'dbl-ext-garden',
- 'dbl-ext-garden',
- 'dbl-ext-garden',
- 'dbl-ext-garden',
- 'ext-garden',
- 'ext-garden',
- 'ext-garden',
- 'ext-garden',
- 'corner-garden',
- 'corner-garden',
- 'corner-garden',
- 'corner-garden',
- 'corner-house',
- 'corner-house',
- 'corner-house',
- 'corner-house',
- 'freestand-garden',
- 'freestand-garden',
- 'freestand-garden',
- 'freestand-garden'
- }
- ----------------------------------------------------------------------------------------------------------------
- -- the data structure below represents the catalogue of vocabulary as built in minecraft
- -- id - is unique for each vocab, starting from 1 going to 40 currently
- -- column and row - represent the "physical" location of the vocab model in the catalogue in the minecraft world
- -- nameEN and name DE - are names for english and german. for now names must not have spaces, use dashes (-) instead
- -- typeEN and typeDE - are the type names, also in english and german such as tech&science spaces
- -- height - is how many blocks is this structure tall
- -- slots - is how many potential detector stones is this structure occupying as a building, ex. 2 for houses, 3 for corner extenstions, 0 for plazas
- -- green - is true or false and is used for easier calculation of the GREENEST GOAL
- -- greenSlots - is how many slots are green and is used for easier calculation of the GREENEST GOAL
- VOCABS_DATA = {
- {id=1, column=1, row=1,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false, greenSlots=0},
- {id=2, column=1, row=2,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false, greenSlots=0},
- {id=3, column=1, row=3,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false, greenSlots=0},
- {id=4, column=1, row=4,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false, greenSlots=0},
- --
- {id=5, column=2, row=1,nameEN="Gym",nameDE="Fitnessstudio", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false, greenSlots=0},
- {id=6, column=2, row=2,nameEN="Office-Building",nameDE="Bürogebäude", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false, greenSlots=0},
- {id=7, column=2, row=3,nameEN="Hotel",nameDE="Hotel", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false, greenSlots=0},
- {id=8, column=2, row=4 ,nameEN="Bank",nameDE="Bank", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false, greenSlots=0},
- --
- {id=9, column=3, row=1,nameEN="Library",nameDE="Bibliothek", typeEN="Tech & Science Spaces",typeDE="Wissenschaftsgebäude",height=16, slots=1, green=false, greenSlots=0},
- {id=10, column=3, row=2,nameEN="FabLab",nameDE="Innovationszentrum", typeEN="Tech & Science Spaces",typeDE="Wissenschaftsgebäude",height=16, slots=1, green=false, greenSlots=0},
- {id=11, column=3, row=3,nameEN="Aquaponic-Greenhouse",nameDE="Aquaponik-Gewächshaus", typeEN="Tech & Science Spaces",typeDE="Wissenschaftsgebäude",height=16, slots=1, green=true, greenSlots=1},
- {id=12, column=3, row=4,nameEN="Science-Bridge",nameDE="Wissenschaftsbrücke", typeEN="Tech & Science Spaces",typeDE="Wissenschaftsgebäude",height=16, slots=1, green=true, greenSlots=1},
- --
- {id=13, column=4, row=1,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false, greenSlots=0},
- {id=14, column=4, row=2,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false, greenSlots=0},
- {id=15, column=4, row=3,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false, greenSlots=0},
- {id=16, column=4, row=4,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false, greenSlots=0},
- --
- {id=17, column=5, row=1,nameEN="Double-Floor-Riser",nameDE="Verschiebung-zwei-hoch", typeEN="",typeDE="vertikale Verschiebungen",height=0, slots=0, green=false, greenSlots=0},
- {id=18, column=5, row=2,nameEN="Single-Floor-Riser",nameDE="Verschiebung-einen-hoch", typeEN="",typeDE="vertikale Verschiebungen",height=0, slots=0, green=false, greenSlots=0},
- {id=19, column=5, row=3,nameEN="City-Plaza",nameDE="städtischer Platz", typeEN="Plazas",typeDE="Plätze",height=0, slots=0, green=false, greenSlots=0},
- {id=20, column=5, row=4,nameEN="Park-Plaza",nameDE="grüner Platz", typeEN="Plazas",typeDE="Plätze",height=0, slots=0, green=true, greenSlots=1},
- ---
- {id=21, column=6, row=1,nameEN="Green-Gym",nameDE="grünes Fitnessstudio", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=true, greenSlots=5},
- {id=22, column=6, row=2,nameEN="Green-Office-Building",nameDE="grünes Bürogebäude", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=true, greenSlots=5},
- {id=23, column=6, row=3,nameEN="Green-Hotel",nameDE="grünes Hotel", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=true, greenSlots=5},
- {id=24, column=6, row=4,nameEN="Green-Bank",nameDE="grünes Bank", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=true, greenSlots=5},
- ---
- {id=25, column=7, row=1,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true, greenSlots=1},
- {id=26, column=7, row=2,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true, greenSlots=1},
- {id=27, column=7, row=3,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true, greenSlots=1},
- {id=28, column=7, row=4,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true, greenSlots=1},
- ---
- {id=29, column=8, row=1,nameEN="Open-Аir-Cinema",nameDE="Freiluftkino", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true, greenSlots=3},
- {id=30, column=8, row=2,nameEN="Open-Air-Swimming-Pool",nameDE="Freibad", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true, greenSlots=3},
- {id=31, column=8, row=3,nameEN="Green-Cafe",nameDE="grünes Café", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true, greenSlots=3},
- {id=32, column=8, row=4,nameEN="Palm-Tree-House",nameDE="Palmengarten", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true, greenSlots=3},
- ----
- {id=33, column=9, row=1,nameEN="Cinema",nameDE="Kino", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false, greenSlots=0},
- {id=34, column=9, row=2,nameEN="Conference-Hall",nameDE="Konferenzhalle", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false, greenSlots=0},
- {id=35, column=9, row=3,nameEN="Café",nameDE="Café", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false, greenSlots=0},
- {id=36, column=9, row=4,nameEN="Art-Gallery",nameDE="Kunstgalerie", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false, greenSlots=0},
- ---
- {id=37, column=10, row=1,nameEN="Green-Roof-House",nameDE="grünes Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=true, greenSlots=2},
- {id=38, column=10, row=2,nameEN="Green-Roof-House",nameDE="grünes Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=true, greenSlots=2},
- {id=39, column=10, row=3,nameEN="Green-Roof-House",nameDE="grünes Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=true, greenSlots=2},
- {id=40, column=10, row=4,nameEN="Green-Roof-House",nameDE="grünes Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=true, greenSlots=2},
- }
- --constructor for player object so that data structure is consistant
- function newPlayerData(name,x,y,z)
- local p = {
- name = name,
- x=x,
- y=y,
- z=z
- }
- return p
- end
- --return a list of all players in the game world as player objects
- local function getAllPos(selector)
- local result, message = commands.tp("@a["..selector.."]","~ ~ ~")
- local names = {}
- if result == true then
- for i,result in ipairs(message) do
- local wordpattern = "[^, ]+"
- local numberpattern = "[%-% ]%d+[%.]%d+"
- local words,numbers = {},{}
- for word in string.gmatch(result, wordpattern) do
- table.insert(words,word)
- end
- for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
- local coords = {
- x = math.floor(numbers[1]),
- y = math.floor(numbers[2]),
- z = math.floor(numbers[3])
- }
- local name = words[2]
- table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
- --print("Player Found - getAllPos")
- end
- end
- return names
- end
- --sort table by random
- local function shuffleTable( t )
- local rand = math.random
- assert( t, "shuffleTable() expected a table, got nil" )
- local iterations = #t
- local j
- for i = iterations, 2, -1 do
- j = rand(i)
- t[i], t[j] = t[j], t[i]
- end
- end
- --returns a list of player objects containing all players who are standing on the given block, and who also are in the given selection
- local function getAllOnBlockType(block,selector)
- local result, message = commands.exec("execute @a["..selector.."] ~ ~ ~ detect ~ ~-1 ~ "..block.." -1 tp @p[r=1] ~ ~ ~")
- local names = {}
- if result == true then
- for i,result in ipairs(message) do
- local wordpattern = "[^, ]+"
- local numberpattern = "[%-% ]%d+[%.]%d+"
- local words,numbers = {},{}
- for word in string.gmatch(result, wordpattern) do table.insert(words,word) end
- for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
- if numbers[1] and numbers[2] and numbers[3] then
- local coords = {
- x = math.floor(numbers[1]),
- y = math.floor(numbers[2]),
- z = math.floor(numbers[3])
- }
- local name = words[2]
- table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
- print("Found a player - getOnBlock")
- else
- print("Error: Coordinate Numbers were missing")
- end
- end
- end
- return names
- end
- --gives a player a squid egg with their name on it. Removes all spawn eggs first
- local function giveSquid(name)
- commands.clear(name,'spawn_egg')
- commands.give(name,'spawn_egg 1 94 {CanPlaceOn:["'..BLOCKS.PHVFLOOR.block..'","'..BLOCKS.CAMP_FLOOR.block..'"],display:{Name:"Heimkehrer - '..name..'",Lore:[Use this on the floor to return to spawn]}}')
- end
- --returns a list of squid objects and their names
- local function getSquids()
- local result, message = commands.exec("execute @e[type=Squid] ~ ~ ~ tp @e[r=1] ~ ~ ~")
- local names = {}
- if result == true then
- for i,result in ipairs(message) do
- local wordpattern = "[^, ]+"
- local numberpattern = "[%-% ]%d+[%.]%d+"
- local words,numbers = {},{}
- for word in string.gmatch(result, wordpattern) do table.insert(words,word) print(word) end
- for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
- if numbers[1] and numbers[2] and numbers[3] then
- local coords = {
- x = math.floor(numbers[1]),
- y = math.floor(numbers[2]),
- z = math.floor(numbers[3])
- }
- local name = words[4]
- table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
- print("Found a player - getOnBlock "..name)
- else
- print("Error: Coordinate Numbers were missing")
- end
- end
- end
- return names
- end
- local function removePlayerFromKew(game,playername)
- for _,kew in pairs(game.queues) do
- for index, player in ipairs(kew.playerlist) do
- if player.name == playername then
- table.remove(kew.playerlist,index)
- end
- end
- if #kew.playerlist == 0 and kew.phase == 2 then
- --game can be ended as no players are left
- kew.timer = 0
- end
- end
- end
- local function movePlayerToSpawn(playername)
- respawnPlayer(playername)
- commands.async.tp(playername,SPAWN.x,SPAWN.y,SPAWN.z,SPAWN.a1,SPAWN.a2)
- commands.async.tellraw(playername,'["",{"text":"TELEPORTED: You used your Heimkehrer","color":"blue"}]')
- commands.async.tellraw(playername,'["",{"text":"DE: TELEPORTED: You used your Heimkehrer","color":"gold"}]')
- end
- --takes a list of squids and deals with all those players, moving them back to spawn and removing them from game
- --also gives them a new squid
- local function dealWithSquidders(game,squids)
- for _,squid in pairs(squids) do
- --remove player from current game if in game
- removePlayerFromKew(game,squid.name)
- --teleport them back to spawn
- movePlayerToSpawn(squid.name)
- --give a new squid
- giveSquid(squid.name)
- --particle effects
- --teleport message
- end
- --kill all squids
- if #squids>0 then
- commands.tp("@e[type=Squid]",100000,200,100000)
- commands.kill("@e[type=Squid]")
- os.sleep(#squids*0.2)
- end
- end
- --creates a villager with special items
- local function spawnVillager(x,y,z)
- commands.summon("Villager",x,y,z,'{Invulnerable:1,CustomName:Wool_Seller,Profession:2,Career:1,CareerLevel:6,Offers:{Recipes:[ {buy:{id:emerald,Count:1},sell:{id:wool,Count:'..WOOL_PER_EMERALD..',tag:{CanPlaceOn:["minecraft:diamond_block","minecraft:clay","minecraft:wool","minecraft:stained_hardened_clay"]}}}, {buy:{id:emerald,Count:1},sell:{id:stone_pickaxe,Count:1,Damage:'..131-PICKAXE_USES..',tag:{CanDestroy:["minecraft:wool"]}}} ]}}')
- end
- --displays a subtitle of time to a selection of players
- local function displayTime(selector,minutes,seconds)
- --commands.title("@a["..selector.."]","subtitle",'{text:"Time left: '..minutes..":"..seconds..'",color:red,bold:false,underlined:false,italic:false,strikethrough:false,obfuscated:false}')
- commands.async.xp("-1000000L","@a["..selector.."]")
- local secondstot = (minutes * 60) + seconds
- commands.async.xp(tostring(secondstot).."L","@a["..selector.."]")
- end
- --displays a title to a selection of players
- local function displayTitle(selector,text)
- commands.async.title("@a["..selector.."]","title",'{text:"'..text..'"}')
- end
- --simply runs displayTitle on a list of players
- local function displayTitleToGroup(playerlist,text)
- for i,player in ipairs(playerlist) do
- displayTitle("name="..player.name,text)
- end
- end
- --simply runs displayTime on a list of players
- local function displayTimeToGroup(playerlist,minutes,seconds)
- for i,player in ipairs(playerlist) do
- displayTime("name="..player.name,minutes,seconds)
- end
- end
- --teleports a list of players to an exact place and sends them a message about it
- local function teleportToPoint(x,y,z,playerlist,clear,textEN, textDE)
- for i,player in ipairs(playerlist) do
- player.x = x
- player.y = y
- player.z = z
- commands.async.gamemode(2,player.name)
- if clear then
- commands.async.clear(player.name,"wool")
- commands.async.clear(player.name,"stone_pickaxe")
- end
- commands.tp("@a[name="..player.name.."]",x,y,z)
- commands.async.tellraw(player.name,'["",{"text":"'..textEN..'","color":"blue"}]')
- commands.async.tellraw(player.name,'["",{"text":"'..textDE..'","color":"gold"}]')
- end
- end
- --teleports a list of players to a given buildzone
- local function teleportToZone(buildzone,playerlist,textEN, textDE)
- teleportToPoint(buildzone.x+2+(buildzone.w/2),buildzone.y+5,buildzone.z+2+(buildzone.w/2),playerlist,true,textEN, textDE)
- end
- --gives the same list of items to a list of players
- local function giveItems(playerlist,itemlist)
- local given = 0
- for i,player in ipairs(playerlist) do
- --commands.async.clear(player.name)
- for j,item in ipairs(itemlist) do
- commands.async.give("@a[name="..player.name.."]",item)
- given = given +1
- end
- giveSquid(player.name)
- end
- return given
- end
- --a multi builder which uses the vocab constructor to create sets of vocab
- local function makeVocabZones(quant,w)
- local x,y,z = ox,oy,oz+6
- local result = {}
- local id = 1
- for i=0,quant-1 do
- for k=0,3 do
- local zpos = i-4
- local ypos = k
- --print("vocab at X")
- --print(x-(2*w)-6)
- --print("and Z")
- --print(z+((w+1)*zpos))
- local nextVocab = newVocabZone(
- x-(2*w)-6,y+(ypos*(VOCAB_HEIGHT+3)),
- z+((w+1)*zpos),
- w,
- id,
- REWARDS[id] or DEFAULT_REWARD,
- VOCABS_DATA[id].nameEN or DEFAULT_NAME,
- VOCABS_DATA[id].nameDE or DEFAULT_NAME,
- VOCABS_DATA[id].typeEN,
- VOCABS_DATA[id].typeDE,
- VOCABS_DATA[id].height,
- VOCABS_DATA[id].slots,
- VOCABS_DATA[id].green,
- VOCABS_DATA[id].greenSlots
- )
- table.insert(result,nextVocab)
- id = id +1
- end
- end
- return result
- end
- --finds the next free location(or buildzone) for a new game in a given area.
- --giving force as True will mean it overrides the first location no matter what
- local function findNextLoc(width,zones,force)
- local x,y,z = 0,0,0
- for i,loc in ipairs(LOCS) do
- x,y,z = FIRSTZONE.x+(loc.x*(width+1)),FIRSTZONE.y,FIRSTZONE.z+(-loc.z*(width+1))
- --print("testing for available zone at: "..x..", "..y..", "..z)
- local result,message = commands.testforblock(x,y+BUILDZONE_FLOOR_HEIGHT,z,"minecraft:air")
- --print("testing done")
- if force then result = true end
- local zonefree = true
- for i,zone in ipairs(zones) do
- if zone.x == x and zone.z == z then
- zonefree = false
- end
- end
- --print("next position free is ",loc.x*width,oy,loc.z*width)
- --if result then print("true") else print("false") end
- if result and zonefree then
- --print("using loc: ",loc.x,loc.z)
- return x,y,z
- end
- end
- return nil,nil,nil
- end
- --relocates a buildzone to a new coordinate safely
- --avoids overlapping with other buildzones
- function moveBuildzone(buildzone,zones)
- local x,y,z = findNextLoc(buildzone.w,zones)
- if x and y and z then
- print("moved buildzone from "..buildzone.x..","..buildzone.z.." to "..x..","..y)
- local w = buildzone.w
- buildzone.x,buildzone.y,buildzone.z = x,y+BUILDZONE_FLOOR_HEIGHT,z
- buildzone.selector = "x="..x..",y="..tostring(y-1)..",z="..z..",dx="..w..",dy=256,dz="..w
- buildzone.structures = {} --a list of all vocabularies which have been contructed
- else
- print("buildzone at "..buildzone.x..","..buildzone.z.." stayed where it is")
- end
- end
- --multi builder to create sets of buildzones using the buildzone constructor
- local function makeBuildzones(quant,vocab,width,height)
- local result = {}
- for i=1,quant do
- --print("locating available slot")
- local x,y,z = findNextLoc(width,result)
- if x and y and z then
- --print("made new buildzone at",x,y,z)
- table.insert(result,newBuildZone(x,y+height,z,width,vocab))
- else
- --print("failed to make new buildzone")
- end
- end
- local remaining = NUMBER_OF_BUILDZONES - #result
- --print("doing this remaining thing")
- for i=1, remaining do
- local x,y,z = findNextLoc(width,result,true)
- if x and y and z then
- --print("forced new buildzone at",x,y,z)
- table.insert(result,newBuildZone(x,y+height,z,width,vocab))
- else
- print("failed to force new buildzone")
- end
- end
- return result
- end
- --vocab constructor old version - DELETE IN NEXT COMMIT. Enforces some data structure
- function newVocabZoneOld(x,y,z,w,reward,name)
- local nvz = {}
- nvz.x ,nvz.y ,nvz.z ,nvz.w = x,y,z,w
- nvz.cx = nvz.x - nvz.w - 2
- nvz.cy = nvz.y
- nvz.cz = nvz.z
- nvz.name = name
- nvz.reward = reward
- return nvz
- end
- --vocab constructor. Enforces some data structure
- function newVocabZone(x,y,z,w,id, reward,nameEN, nameDE, typeEN, typeDE, height, slots,green,greenSlots)
- local nvz = {}
- nvz.x ,nvz.y ,nvz.z ,nvz.w = x,y,z,w
- nvz.cx = nvz.x - nvz.w - 2
- nvz.cy = nvz.y
- nvz.cz = nvz.z
- nvz.nameEN = nameEN
- nvz.reward = reward
- --- new stuff
- nvz.id = id
- nvz.nameDE = nameDE
- nvz.typeEN = typeEN
- nvz.typeDE = typeDE
- nvz.height = height
- nvz.slots = slots
- nvz.green = green
- nvz.greenSlots = greenSlots
- return nvz
- end
- --buildzone constructor. Enforces some data structure
- function newBuildZone(x,y,z,w,vocabZones)
- local nbz = {}
- nbz.x ,nbz.y ,nbz.z ,nbz.w = x,y,z,w
- nbz.selector = "x="..x..",y="..(y-5)..",z="..z..",dx="..w..",dy=256,dz="..w
- nbz.structures = {} --a list of all vocabularies names which have been contructed
- nbz.buildings = {} --a list of all vocabularies with full data (x,y,z,id,name) which have been contructed
- nbz.filledSlots = 0 --to count how many slots have been filled with buildings. the matrix is 7x7x20 slots. one slot is 9x9x9 blocks big
- nbz.greenSlots = 0 --to count how many of the slots are green. the matrix is 7x7x20 slots. one slot is 9x9x9 blocks big
- nbz.variety = {} -- this stores how many buildings of each type are there. it is indexed on vocab.id and the value is the number of buildings from type vocab.id
- nbz.waitingForCheck = {}
- nbz.highest = 0
- nbz.vocab = vocabZones
- return nbz
- end
- --kew constructor. Enforces some data structure
- function newQueue(buildzone,maxplayers)
- local q = {}
- q.timer = 1
- q.phase = 1
- q.victory = false
- q.phases = {
- {
- name = "Selecting Players",
- length = 25,
- displaylength = 15
- },
- {
- name = "Game In Progress",
- length = GAME_LENGTH,
- displaylength = 70
- },
- {
- name = "Round Complete",
- length = 35,
- displaylength = 5
- }
- }
- q.playerlist = {}
- q.maxplayers = maxplayers
- q.buildzone = buildzone
- return q
- end
- --creates a ring of blocks using coordinates
- function fillRing(x,y,z,w,block)
- commands.fill(x,y,z,x+w,y,z,block)
- commands.fill(x+w,y,z,x+w,y,z+w,block)
- commands.fill(x,y,z+w,x+w,y,z+w,block)
- commands.fill(x,y,z+w,x,y,z,block)
- end
- function setup()
- print("debug: starting setup function.")
- local game = {}
- game.vocab = {}
- game.builds = {}
- game.queues = {}
- game.waitlist = {}
- game.spawn = SPAWN
- game.lastClock = os.clock()
- game.nowTime = os.clock()
- --kill all villagers
- commands.exec("kill @e[type=Villager]")
- --buildzone and vocabzone creation
- print("debug-setup: making vocab zones.")
- game.vocab = makeVocabZones(NUMBER_OF_VOCAB,VOCAB_WIDTH)
- print("debug-setup: making building zones.")
- game.builds = makeBuildzones(NUMBER_OF_BUILDZONES,game.vocab,BUILDZONE_WIDTH,BUILDZONE_FLOOR_HEIGHT)
- for i,build in ipairs(game.builds) do
- table.insert(game.queues,newQueue(build,4))
- end
- print("debug-setup: testing for properly setup vocabs.")
- for i,vz in ipairs(game.vocab) do
- local x,y,z,w = vz.x,vz.y,vz.z,vz.w
- local cx,cy,cz = vz.cx,vz.cy,vz.cz
- local detector, message1 = commands.testforblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT.block)
- local blocker, message2 = commands.testforblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT_DEAD.block)
- if not (detector or blocker) then
- for nx=0,2 do
- for nz=0,2 do
- commands.setblock(x+(nx*9)+4,y-1,z+(nz*9)+4,BLOCKS.VOCAB_REPLACE.block)
- commands.setblock(cx+(nx*9)+4,cy-1,cz+(nz*9)+4,BLOCKS.VOCAB_DETECT.block)
- end
- end
- commands.setblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT_DEAD.block)
- end
- end
- print("debug-setup: adding scoreboards.")
- for i, name in ipairs(VOCAB_NAMES) do
- commands.scoreboard("objectives","add",name,"dummy")
- end
- commands.gamerule("doDaylightCycle",false)
- commands.gamerule("keepInventory",true)
- commands.gamerule("doTileDrops",false)
- commands.gamerule("logAdminCommands",false)
- commands.gamerule("commandBlockOutput",false)
- commands.time("set",6000)
- commands.scoreboard("objectives","add","highscores","dummy","Best Neighbourhoods")
- commands.scoreboard("objectives","add","VillagerLife","dummy")
- commands.scoreboard("objectives","add","built","dummy", "Structures Built")
- commands.scoreboard("objectives","add","highest","dummy", "Personal Highest")
- commands.scoreboard("objectives","add","played","dummy","Games Played")
- commands.title("@a","times",0,30,30) -- what does this do?
- math.randomseed( os.time() )
- commands.scoreboard("objectives","setdisplay","sidebar","highscores")
- commands.scoreboard("objectives","setdisplay","list","played")
- print("time is: "..os.time())
- print( "time is: "..textutils.formatTime( os.time(), false ) )
- print("day is: "..os.day())
- print("computer clock is: "..os.clock())
- if DEBUG_MODE then
- for i,build in ipairs(game.builds) do
- build.phase = 2
- build.timer = 500
- end
- end
- print("Computer Co-ordinates ",ox,oy,oz)
- print("20.000 Blocks Active!")
- return game
- end
- function checkForSquids(game)
- --execute on all squids
- local squidders = getSquids()
- dealWithSquidders(game,squidders)
- end
- --main game loop
- --runs the game object through each of these update steps in order
- function update(game)
- local elapsed = updateClock(game)
- --update players
- checkPlayers(game)
- doTimerUpdates(game,elapsed)
- doPhaseUpdates(game)
- doPhaseEnds(game)
- checkBoundaries(game)
- checkForSquids(game)
- if #game.waitlist > 0 then allocateWaiters(game) end
- end
- --calculates elapsed time during a game tick
- function updateClock(game)
- game.nowTime = os.clock()
- local elapsed = game.nowTime - game.lastClock
- game.lastClock = game.nowTime
- return elapsed
- end
- --updates all kews in the game object based on elapsed time
- function doTimerUpdates(game,elapsed)
- for i,kew in ipairs(game.queues) do
- kew.timer = kew.timer - elapsed
- end
- end
- --check players are inside their buildzone and move them back if not
- function checkBoundaries(game)
- for i,kew in ipairs(game.queues) do
- if kew.phase ==2 then
- --boundaries
- local x_min = kew.buildzone.x
- local x_max = kew.buildzone.x+kew.buildzone.w
- local z_min = kew.buildzone.z
- local z_max = kew.buildzone.z+kew.buildzone.w
- local toBeCorrected = {}
- for j,player in ipairs(kew.playerlist) do
- local listOfOne = getAllPos('m=2,name='..player.name)
- if listOfOne and listOfOne[1] then
- player.x = listOfOne[1].x
- player.y = listOfOne[1].y
- player.z = listOfOne[1].z
- local changed = false
- if player.x > x_max then
- changed = true
- player.x = x_max-2
- end
- if player.x < x_min then
- changed = true
- player.x = x_min+2
- end
- if player.z > z_max then
- changed = true
- player.z = z_max-2
- end
- if player.z < z_min then
- changed = true
- player.z = z_min+2
- end
- if changed then teleportToPoint(player.x,kew.buildzone.y,player.z,{player},false,"TELEPORTED: Please stay inside the building zone until your game has ended", "DE: TELEPORTED: Please stay inside the building zone until your game has ended") end
- end
- end
- end
- end
- end
- --here you can set the logic which determines if a buildzone was valuable.
- --Return true if it is crap and should be replaced
- function checkIfBuildzoneIsCrap(buildzone)
- if #buildzone.structures < 5 then
- print("Buildzone was crap")
- return true
- end
- print("Buildzone was ok")
- return false
- end
- --Everything that happens after a buildzone was completed
- --due to time limit.
- function cleanAfterVictory(buildzone)
- commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,BLOCKS.VICTORY_MARKER.block)
- fillRing(buildzone.x,buildzone.y,buildzone.z,buildzone.w,"minecraft:air",0,"replace",BLOCKS.CONSTRUCTION.block,BLOCKS.CONSTRUCTION.data)
- for h=0,256-buildzone.y do
- commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.DETECT.block,BLOCKS.DETECT.data)
- commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.PLUG.block,BLOCKS.PLUG.data)
- commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.BUILDING_GARDEN.block,BLOCKS.BUILDING_GARDEN.data)
- commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air 0","replace",BLOCKS.BUILDING_HOUSE.block,BLOCKS.BUILDING_HOUSE.data)
- end
- commands.async.fill(buildzone.x,buildzone.y-1,buildzone.z,buildzone.x+buildzone.w,buildzone.y-1,buildzone.z+buildzone.w,BLOCKS.CAMP_FLOOR.block,BLOCKS.CAMP_FLOOR.data,"replace",BLOCKS.PLUG.block,BLOCKS.PLUG.data)
- commands.async.fill(buildzone.x,buildzone.y,buildzone.z,buildzone.x+buildzone.w,buildzone.y,buildzone.z+buildzone.w,BLOCKS.PHVFLOOR.block,BLOCKS.PHVFLOOR.data,"replace","minecraft:air","0")
- local wasCrap = checkIfBuildzoneIsCrap(buildzone)
- if wasCrap then
- --mark this buildzone for replacement
- commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,"minecraft:air")
- end
- end
- --these happen every tick and require the game object
- --updates are performed on each Queue (kew) and within each
- --of those on each buildzone.
- function doPhaseUpdates(game)
- for i,kew in ipairs(game.queues) do
- local minutes = string.format("%02d",math.floor(kew.timer/60))
- local seconds = string.format("%02d",math.floor(kew.timer - (minutes*60)))
- if kew.timer <= 0 then
- minutes = "00"
- seconds = "00"
- end
- if kew.phase == 1 then
- --waiting phase
- if #kew.playerlist == kew.maxplayers and kew.timer > 5 then kew.timer = 5 end
- if not DEBUG_MODE and #kew.playerlist == 0 then kew.timer = kew.phases[1].length end
- displayTitleToGroup(kew.playerlist,"Game starting!")
- displayTimeToGroup(kew.playerlist,minutes,seconds)
- --show countdown
- elseif kew.phase == 2 then
- --playing phase
- if #kew.playerlist == 0 then timer = 0 end -- finish if all players quit
- -- do vocab logic
- local victory = updatePlayedZone(kew.buildzone) --currently victory updatePlayedZone returns always false
- --
- displayTimeToGroup(kew.playerlist,minutes,seconds)
- elseif kew.phase == 3 then
- --end phase
- displayTitleToGroup(kew.playerlist,"Use Heimkehrer to return")
- displayTimeToGroup(kew.playerlist,minutes,seconds)
- end
- end
- end
- --this runs after a buildzone is completed
- --it should tally structure types and set scoreboard highscores
- --it also rewards all participants with more played score
- function processHighscores(kew)
- local buildzone = kew.buildzone
- --add score to players who finished this game
- for _,player in ipairs(kew.playerlist) do
- commands.async.scoreboard("players","add",player.name,"played",1)
- end
- end
- --function to export a buildzone detail once it is complete
- --requires a kew so it can access the playerlist
- local function exportKewData(kew)
- local buildzone = kew.buildzone
- local saved = {}
- saved.position =
- {
- x=buildzone.x,
- y=buildzone.y,
- z=buildzone.z
- }
- local timestamp = math.floor(os.clock())
- --saved.timeCompleted = timestamp
- saved.players = {}
- for _, player in ipairs(kew.playerlist) do
- table.insert(saved.players,player.name)
- end
- --saved.structures = buildzone.structures
- saved.buildings = buildzone.buildings
- saved.totals = tracker.tallyTable(buildzone.structures)
- --saved.highest = buildzone.highest
- saved.stats = {
- cityVersion = CITY_VERSION,
- height = buildzone.highest,
- densityIndex = math.floor(100*buildzone.filledSlots/49), -- the density index is made from built area (filledSlots) over the ground area (7x7 slots = 49)
- greenIndex = math.floor(100*buildzone.greenSlots/49), --the green index is made from green area (greenSlots) over the ground area (7x7 slots = 49)
- variety = tablelength(buildzone.variety),
- timeCompleted = timestamp,
- gameLength = GAME_LENGTH
- }
- fs.makeDir("/records")
- local file = fs.open("/records/"..timestamp.."at"..buildzone.x.."_"..buildzone.z..".yaml","w")
- file.write(json.encodePretty(saved))
- file.close()
- end
- --this code runs ONCE at the end of each phase
- --what actually happens is specific to which phase the
- --particular kew is in.
- function doPhaseEnds(game)
- for i,kew in ipairs(game.queues) do
- if kew.timer <= 0 then
- if kew.phase == 1 then
- --waiting phase ends goto play phase
- moveBuildzone(kew.buildzone,game.builds)
- teleportToZone(kew.buildzone,kew.playerlist,"TELEPORTED: Your game has started.", "DE: TELEPORTED: Your game has started.")--teleport selected players
- cleanBuildzone(kew.buildzone)
- prepareBuildzone(kew.buildzone)--prepare build zone
- giveItems(kew.playerlist,STARTING_ITEMS) --give starting items
- displayTitle(kew.buildzone.selector,"Build!")
- kew.victory = false
- displayTime(kew.buildzone.selector,0,0)
- kew.phase = 2
- kew.timer = kew.phases[2].length
- elseif kew.phase == 2 then
- --playing phase ends goto end phase
- processHighscores(kew)
- exportKewData(kew)
- cleanAfterVictory(kew.buildzone)
- kew.phase = 3
- displayTime(kew.buildzone.selector,0,0)
- kew.timer = kew.phases[3].length
- elseif kew.phase == 3 then
- --end phase ends goto waiting phase
- removePlayersFromKew(game,kew)
- kew.phase = 1
- displayTime(kew.buildzone.selector,0,0)
- kew.timer = kew.phases[1].length
- end
- end
- end
- end
- --Replaces everything that is needed to start the game. Does not rebuild the floor, or clear anything away.
- --based on the settings it creates a full grid, or a partial grid, or no grid
- --it also places the ring, although this is disabled for now
- function prepareBuildzone(buildzone)
- local bz = buildzone
- local x,y,z,w = bz.x,bz.y,bz.z,bz.w
- --commands.fill(x,y-1,z,x+w,y-1,z+w,BLOCKS.CAMP_FLOOR)
- fillRing(buildzone.x,buildzone.y,buildzone.z,buildzone.w,BLOCKS.CONSTRUCTION.block)
- if DO_GRID then
- for x=0,6 do
- for z=0,6 do
- local rand = math.random()*100
- --local result, text = commands.testforblock(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+4,BLOCKS.CAMP_FLOOR.block)
- if rand > GRID_HOLE_CHANCE then --and result then
- commands.async.setblock(bz.x+(x*9)+4,bz.y,bz.z+(z*9)+4,BLOCKS.DETECT.block,BLOCKS.DETECT.data,"replace","minecraft:air")
- commands.async.fill(bz.x+(x*9)+1,bz.y-1,bz.z+(z*9)+4,bz.x+(x*9)+7,bz.y-1,bz.z+(z*9)+4,BLOCKS.PLUG.block)
- commands.async.fill(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+1,bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+7,BLOCKS.PLUG.block)
- --commands.async.setblock(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+4,BLOCKS.CAMP_FLOOR.block)
- end
- end
- end
- end
- commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,BLOCKS.CONSTRUCTION.block)
- end
- --deletes everything inside the buildzone
- function cleanBuildzone(buildzone)
- print("Cleaning buildzone")
- for h=0,VICTORY_HEIGHT+20 do
- commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air")
- end
- end
- --moves all players assigned to the queue into the waiting area for the provided game.
- --It also changes them to Adventure mode and clears their inventory
- function respawnPlayers(game,kew)
- teleportToPoint(game.spawn.x,game.spawn.y,game.spawn.z,kew.playerlist,true,"TELEPORTED: Your game ended so you have been returned to the Spawn Point", "DE: TELEPORTED: Your game ended so you have been returned to the Spawn Point") --put players back in spawn area
- for i,player in ipairs(kew.playerlist) do
- --table.insert(game.waitlist,player)
- respawnPlayer(player,"")
- end
- kew.playerlist = {}
- end
- function removePlayersFromKew(game,kew)
- for _, player in ipairs(kew.playerlist) do
- commands.tell(player.name,"Your game is over. Use your Heimkehrer to return to spawn")
- end
- kew.playerlist = {}
- end
- function respawnPlayer(playername,message)
- commands.tell(playername,message)
- commands.async.gamemode(2,playername)
- commands.async.clear(playername,"minecraft:wool")
- commands.async.clear(playername,"minecraft:stone_pickaxe")
- end
- function checkForPlayerInBuildzone(player,buildzone)
- local result,message = commands.testfor('@a[name='..player.name..','..buildzone.selector..']')
- return result
- end
- function checkForPlayerInWaitzone(player)
- local selector = "x="..WAITZONE.x..",y="..WAITZONE.y..",z="..WAITZONE.z..",dx="..WAITZONE.w..",dy=256,dz="..WAITZONE.l
- local result,message = commands.testfor('@a[name='..player.name..','..selector..']')
- return result
- end
- function checkPlayers(game)
- local selector = "x="..WAITZONE.x..",y="..WAITZONE.y..",z="..WAITZONE.z..",dx="..WAITZONE.w..",dy=256,dz="..WAITZONE.l
- local loggedIn = getAllPos('m=2,'..selector)
- --refresh waitlist
- game.waitlist = loggedIn
- --check currently playing players
- for l,kew in ipairs(game.queues) do
- for i,builder in ipairs(kew.playerlist) do
- local isPlaying = checkForPlayerInBuildzone(builder,kew.buildzone)
- --remove players who are already in kews from the waitlist
- for j, player in ipairs(loggedIn) do
- if player.name == builder.name then
- table.remove(loggedIn,j)
- end
- end
- --if the game is in progress and the player is not found then remove them from the gamekew
- if not isPlaying and kew.phase == 2 then
- --table.remove(kew.playerlist,i)
- --print("Removed "..builder.name.." from game in progress")
- end
- end
- end
- end
- --adds players who wait in the orange room to slots in waiting buildzones
- function allocateWaiters(game)
- --find free slots
- local freeslots = {}
- for i, kew in ipairs(game.queues) do
- if kew.phase == 1 and #kew.playerlist < kew.maxplayers then
- local slots = kew.maxplayers - #kew.playerlist
- for j=1,slots do
- table.insert(freeslots,kew)
- end
- end
- end
- --RE-ENABLE SECOND SHUFFLETABLE IF YOU WANT RANDOM PLAYER MATCHUPS
- shuffleTable(game.waitlist)
- --shuffleTable(freeslots)
- while #freeslots > 0 and #game.waitlist > 0 do
- local player = table.remove(game.waitlist,1)
- local freeslot = table.remove(freeslots,1).playerlist
- table.insert(freeslot,player)
- end
- end
- --PARTICLE FUNCTIONS
- --particles shown to player while their shape is being checked for match
- function searchParticle(x,y,z)
- commands.async.particle("fireworksSpark",x,y,z,0.01,3,0.01,0.01,100)
- end
- -- particles shown to player on successful vocab match
- function successParticle(x,y,z)
- commands.async.particle("happyVillager",x,y,z,2,2,2,1,1000)
- commands.async.playsound("random.levelup","@a",x,y,z,1,1.2)
- end
- --- particles shown to player on failed vocab match
- function failParticle(x,y,z)
- commands.async.particle("reddust",x,y,z,0.1,0.1,1.5,1,200)
- commands.async.particle("reddust",x,y,z,1.5,0.1,0.1,1,200)
- commands.async.playsound("random.bowhit","@a",x,y,z,1,0.8)
- end
- --makes sure that incoming check requests dont exist already
- function addToChecklist(player,buildzone)
- for _, detector in ipairs(buildzone.waitingForCheck) do
- if detector.x == player.x and detector.y == player.y and detector.z == player.z then
- return false
- end
- end
- table.insert(buildzone.waitingForCheck,player)
- return true
- end
- --removes all barrier blocks from a buildzone which are used to carve space in vocabs
- function cleanBarriers(buildzone)
- for h=0,200 do
- commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air",0,"replace","minecraft:barrier")
- end
- end
- --The main chunk of code which deals with stepping on detector blocks and reading the vocab
- function updatePlayedZone(buildzone)
- local victory = false
- local buildzoneSelector = buildzone.selector
- --get all players on diamond, add them to the list of things to check
- local detectLocations = getAllOnBlockType(BLOCKS.DETECT.block,buildzoneSelector)
- for _, player in ipairs(detectLocations) do
- addToChecklist(player,buildzone)
- end
- --DEAL WITH THE DETECTOR AT THE TOP OF THE LIST IF THERE IS ONE
- if #buildzone.waitingForCheck > 0 then
- --DO PARTICLE EFFECTS IF A DETECTING BLOCK THAT IS DETECTING
- for i,loc in ipairs(buildzone.waitingForCheck) do
- searchParticle(loc.x,loc.y+1,loc.z)
- end
- local totalResult = false
- local checked = table.remove(buildzone.waitingForCheck,1)
- local x,y,z,name = checked.x,checked.y,checked.z,checked.name
- for i,vocab in pairs(buildzone.vocab) do
- local result,message = commands.testforblocks( vocab.x, vocab.y, vocab.z, vocab.x+vocab.w, vocab.y+VOCAB_HEIGHT, vocab.z+vocab.w, x-math.floor(vocab.w/2), y-1, z-math.floor(vocab.w/2),"masked")
- if result then
- --clone in the correct vocab
- local cloneres,clonemes = commands.clone( vocab.cx, vocab.cy, vocab.cz, vocab.cx+vocab.w, vocab.cy+VOCAB_HEIGHT, vocab.cz+vocab.w, x-math.floor(vocab.w/2), y-1, z-math.floor(vocab.w/2),"masked")
- if DEBUG_MODE then
- print(clonemes[1])
- end
- commands.async.give(name,vocab.reward)
- -- announce vocab success in English
- commands.async.tellraw(name,'["",{"text":"You built a '..vocab.nameEN.. ' and received more building materials!!","color":"green"}]')
- -- announce vocab success in German
- commands.async.tellraw(name,'["",{"text":"DE: You built a '..vocab.nameDE.. ' and received more building materials!!","color":"gold"}]')
- --clear out barrier blocks
- cleanBarriers(buildzone)
- --ADD THE NEW STRUCTURE TO THE RECORDS
- table.insert(buildzone.structures,vocab.nameEN) ---CHANGE HERE to make it record the place of the vocab too x, y, z and vocab id
- local building = {id=vocab.id,xpos=x,ypos=y,zpos=z,name=vocab.nameEN,time=os.clock(),player=name}
- table.insert(buildzone.buildings, building)
- --if vocab.green then
- buildzone.greenSlots = buildzone.greenSlots + vocab.greenSlots
- --end
- buildzone.filledSlots = buildzone.filledSlots + vocab.slots
- local newHeight = y + vocab.height - buildzone.y-1 -- the Y coordinate of the highest block above the ground. Our world has its ground at 55 which is in buildzone.y, subtracting 1 to compensate for player height
- if newHeight > buildzone.highest then
- buildzone.highest = newHeight
- end
- -- count variety
- print("adding variety: "..vocab.id)
- local varietyId = vocab.id -- we use a variety id instead of the vocab id because vocab id 1,2,3,4 for example are all houses so it is the same variety
- --we add only one type of house, one type of green house, one type of garden and one type of extension and we skip the two risers
- if vocab.id == 2 or vocab.id == 3 or vocab.id == 4 then varietyId = 1 end-- only one type for the 4 different orientations of the house
- if vocab.id == 14 or vocab.id == 15 or vocab.id == 16 then varietyId = 13 end-- only one type for the 4 different orientations of the house extension
- if vocab.id == 26 or vocab.id == 27 or vocab.id == 28 then varietyId = 25 end-- only one type for the 4 different orientations of the house garden extension
- if vocab.id == 38 or vocab.id == 39 or vocab.id == 40 then varietyId = 37 end-- only one type for the 4 different orientations of the green roof house
- if varietyId ~= 17 and varietyId ~= 18 then --skip the two riser as they ar enot buildings
- if buildzone.variety[varietyId] then
- print("increasing existing item")
- buildzone.variety[varietyId] = buildzone.variety[varietyId] + 1
- else
- print("adding new item")
- buildzone.variety[varietyId] = 1
- end
- end
- --- CHECK FOR PERSONAL RECORDS
- --- check if the new structure is the highest
- --- CHANGE here to live detect the contribution of the new structure to the 4 goals and update them
- local personalbest = tracker.getScore(name,"highest")
- if personalbest.count < newHeight then
- --commands.async.tell(name,"You just topped your personal record for highest structure!")
- commands.async.scoreboard("players","add",name,"highest",1)
- -- announce success in English
- commands.async.tellraw(name,'["",{"text":"You just topped your personal record for highest structure!","color":"green"}]')
- -- announce success in German
- commands.async.tellraw(name,'["",{"text":"DE: You just topped your personal record for highest structure!","color":"gold"}]')
- end
- ---
- ---
- -- CHECK if placing the current structure would result in beating a server-wide record on the 4 goals
- --calculate total slots - FOR GOAL "DENSEST NEIGHBOURHOOD"
- local most = tracker.getScore("Densest_[percent]","highscores")
- local Kint = math.floor(100 * buildzone.filledSlots / 49) -- Kint is the density index made from built area (filledSlots) over ground area (7x7 slots = 49)
- if Kint > most.count then
- commands.async.scoreboard("players","set","Densest_[percent]","highscores",Kint)
- commands.async.say("@a","The record for the Densest Neighbourhood has been topped!")
- end
- -- FOR THE GOAL "MOST DIVERSE NEIGHBOURHOOD"
- -- here we need to count how many varieties of buildings there are
- --local structures = tracker.tallyTable(buildzone.structures) -- this counts the variety of buildings in a game
- local mostDiverse = tracker.getScore("Most-Diverse_[out-of-26]","highscores")
- local typeCount = tablelength(buildzone.variety)
- print("variety count is: "..typeCount)
- if typeCount > mostDiverse.count then
- commands.async.scoreboard("players","set","Most-Diverse_[out-of-26]","highscores", typeCount)
- commands.async.say("@a","The record for the Most Diverse Neighbourhood has been topped!")
- end
- -- FOR THE GOAL "GREENEST NEIGHBOURHOOD"
- -- here we need to count the number of green vocabs
- local greenest = tracker.getScore("Greenest_[percent]","highscores")
- local Gint = math.floor(100*buildzone.greenSlots/49) --Gint is the green index, made from green area (greenSlots) over ground area (7x7 slots = 49)
- if Gint > greenest.count then
- commands.async.scoreboard("players","set","Greenest_[percent]","highscores",Gint)
- -- announce success in English
- commands.async.tellraw("@a",'["",{"text":"Awesome! '..name.. ' just topped the record for GREENEST NEIGHBOURHOOD!","color":"green"}]')
- -- announce success in German
- commands.async.tellraw("@a",'["",{"text":"DE: Awesome! '..name.. ' just topped the record for GREENEST NEIGHBOURHOOD!","color":"gold"}]')
- ---commands.async.say("@a","The record for the Densest Neighbourhood has been topped!")
- end
- --calculate highest placement -- FOR THE GOAL "TALLEST NEIGHBOURHOOD"
- local highest = tracker.getScore("Tallest_[meters]","highscores")
- if buildzone.highest > highest.count then
- commands.async.scoreboard("players","set","Tallest_[meters]","highscores",buildzone.highest)
- commands.async.say("@a","The record for the Tallest Negihbourhood has been topped!")
- end
- --increase the "how many structures did i build" score for the building player
- commands.async.scoreboard("players","add",name,"built",1)
- commands.async.scoreboard("players","add",name,vocab.name,1) -- use maybe vocab ID instead of name
- totalResult = true
- break
- end
- end
- if totalResult then
- --yey win, do a happy time
- successParticle(x,y,z)
- else
- --no vocab found so do a fail particle
- --announce in English
- commands.async.tellraw(name,'["",{"text":"Your structure is not built correctly, try a different shape.","color":"red"}]')
- -- announce in German
- commands.async.tellraw(name,'["",{"text":"DE: Your structure is not built correctly, try a different shape.","color":"gold"}]')
- failParticle(x,y-1,z)
- end
- end
- return victory
- end
- -- returns how many items are in a table/list
- function tablelength(T)
- local count = 0
- for _ in pairs(T) do count = count + 1 end
- return count
- end
- --Display game information on the monitor
- function debugDisplay(game)
- monitor.clear()
- if blink then
- monitor.setCursorPos(1,1)
- monitor.setTextColor(colors.red)
- monitor.write("Running")
- monitor.setTextColor(colors.white)
- redstone.setOutput("top",true)
- blink = false
- else
- redstone.setOutput("top",false)
- blink = true
- end
- local line = 2
- for i,kew in ipairs(game.queues) do
- monitor.setCursorPos(1,line)
- local minutes = string.format("%02d",math.floor(kew.timer/60))
- local seconds = string.format("%02d",math.floor(kew.timer - (minutes*60)))
- monitor.write("Buildzone "..i.." | Phase: "..kew.phase.." | Time: "..minutes..":"..seconds)
- monitor.setCursorPos(1,line+1)
- for i,player in ipairs(kew.playerlist) do
- monitor.write(player.name.." ")
- end
- line = line +2
- end
- monitor.setCursorPos(1,10)
- for i,player in ipairs(game.waitlist) do
- monitor.write(player.name.." ")
- end
- end
- --BEGIN RUNTIME CODE
- local blink = true
- local game = setup()
- while true do
- update(game)
- if monitor then debugDisplay(game) end
- commands.async.weather("clear",10000)
- local resetbutton = redstone.getInput("left")
- if resetbutton then
- print("reset!")
- for i,kew in ipairs(game.queues) do
- if kew.phase == 2 then
- kew.timer = 5
- end
- end
- end
- sleep(2)
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement