Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local VERSION = '0.8.4 - goals added'
- 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()
- 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 = 10
- 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 waterBlock(quant)
- text = BLOCKS.BUILDING_WATER.block..' '..quant..' '..BLOCKS.BUILDING_WATER.data..' {display:{Name:"Water 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
- 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+1 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 1
- REWARDS[17] = houseBlock(1)
- --riser 2
- REWARDS[18] = houseBlock(1)
- --filler garden
- REWARDS[19] = houseBlock(1)
- --filler house plaza
- 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-garden (like extension row house)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)
- --allotments (costs 4 garden, -2 activators)
- REWARDS[37] = houseBlock(2)
- REWARDS[38] = houseBlock(2)
- REWARDS[39] = houseBlock(2)
- REWARDS[40] = houseBlock(2)
- 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
- -- there are names for english and german. for now names must not have spaces, use dashes (-) instead
- --there 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
- VOCABS_DATA = {
- {id=1, column=1, row=1,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false},
- {id=2, column=1, row=2,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false},
- {id=3, column=1, row=3,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false},
- {id=4, column=1, row=4,nameEN="House",nameDE="Einfamilienhaus", typeEN="Houses",typeDE="Häuser",height=10, slots=2, green=false},
- --
- {id=5, column=2, row=1,nameEN="Gym",nameDE="Fitnessstudio", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false},
- {id=6, column=2, row=2,nameEN="Office-Building",nameDE="Bürogebäude", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false},
- {id=7, column=2, row=3,nameEN="Hotel",nameDE="Hotel", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false},
- {id=8, column=2, row=4 ,nameEN="Bank",nameDE="Bank", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=false},
- --
- {id=9, column=3, row=1,nameEN="Library",nameDE="Bibliothek", typeEN="Tech & Science Spaces",typeDE="Wissenschaftsgebäude",height=16, slots=1, green=false},
- {id=10, column=3, row=2,nameEN="FabLab",nameDE="Innovationszentrum", typeEN="Tech & Science Spaces",typeDE="Wissenschaftsgebäude",height=16, slots=1, green=false},
- {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=false},
- {id=12, column=3, row=4,nameEN="Science-Bridge",nameDE="Wissenschaftsbrücke", typeEN="Tech & Science Spaces",typeDE="Wissenschaftsgebäude",height=16, slots=1, green=false},
- --
- {id=13, column=4, row=1,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false},
- {id=14, column=4, row=2,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false},
- {id=15, column=4, row=3,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false},
- {id=16, column=4, row=4,nameEN="House-Extension",nameDE="Hauserweiterung", typeEN="Extensions",typeDE="Erweiterungen",height=10, slots=1, green=false},
- --
- {id=17, column=5, row=1,nameEN="Double-Floor-Riser",nameDE="Verschiebung-zwei-hoch", typeEN="",typeDE="vertikale Verschiebungen",height=0, slots=0, green=false},
- {id=18, column=5, row=2,nameEN="Single-Floor-Riser",nameDE="Verschiebung-einen-hoch", typeEN="",typeDE="vertikale Verschiebungen",height=0, slots=0, green=false},
- {id=19, column=5, row=3,nameEN="City-Plaza",nameDE="städtischer Platz", typeEN="Plazas",typeDE="Plätze",height=0, slots=0, green=false},
- {id=20, column=5, row=4,nameEN="Park-Plaza",nameDE="grüner Platz", typeEN="Plazas",typeDE="Plätze",height=0, slots=0, green=true},
- ---
- {id=21, column=6, row=1,nameEN="Green-Gym",nameDE="grünes Fitnessstudio", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=true},
- {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},
- {id=23, column=6, row=3,nameEN="Green-Hotel",nameDE="grünes Hotel", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=true},
- {id=24, column=6, row=4,nameEN="Green-Bank",nameDE="grünes Bank", typeEN="Businesses",typeDE="Geschäfte",height=20, slots=5, green=true},
- ---
- {id=25, column=7, row=1,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true},
- {id=26, column=7, row=2,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true},
- {id=27, column=7, row=3,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true},
- {id=28, column=7, row=4,nameEN="House-Garden",nameDE="Privatgarten", typeEN="Extensions",typeDE="Erweiterungen",height=0, slots=0, green=true},
- ---
- {id=29, column=8, row=1,nameEN="Open-Аir-Cinema",nameDE="Freiluftkino", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true},
- {id=30, column=8, row=2,nameEN="Open-Air-Swimming-Pool",nameDE="Freibad", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true},
- {id=31, column=8, row=3,nameEN="Green-Cafe",nameDE="grünes Café", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true},
- {id=32, column=8, row=4,nameEN="Palm-Tree-House",nameDE="Palmengarten", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=true},
- ----
- {id=33, column=9, row=1,nameEN="Cinema",nameDE="Kino", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false},
- {id=34, column=9, row=2,nameEN="Conference-Hall",nameDE="Konferenzhalle", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false},
- {id=35, column=9, row=3,nameEN="Café",nameDE="Café", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false},
- {id=36, column=9, row=4,nameEN="Art-Gallery",nameDE="Kunstgalerie", typeEN="Gathering Spaces",typeDE="Treffpunkte",height=8, slots=3, green=false},
- ---
- {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},
- {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},
- {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},
- {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},
- }
- --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":"orange"}]')
- 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":"orange"}]')
- 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,
- VOCAB_DATA[id].nameEN or DEFAULT_NAME,
- VOCAB_DATA[id].nameDE or DEFAULT_NAME,
- VOCAB_DATA[id].typeEN,
- VOCAB_DATA[id].typeDE,
- VOCAB_DATA[id].height,
- VOCAB_DATA[id].slots,
- VOCAB_DATA[id].green
- )
- 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))
- local result,message = commands.testforblock(x,y+BUILDZONE_FLOOR_HEIGHT,z,"minecraft:air")
- 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
- 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
- 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)
- 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
- 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. one slot is 9x9x9 blocks big
- nbz.greenBuildings = 0 --to count how many of the buildings are green
- nbz.variety = {} -- this stores how many buildgins 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()
- 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
- game.vocab = makeVocabZones(NUMBER_OF_VOCAB,VOCAB_WIDTH)
- 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
- 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
- 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")
- 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,VICTORY_HEIGHT 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
- }
- saved.completed = os.time()
- saved.players = {}
- for _, player in ipairs(kew.playerlist) do
- table.insert(saved.players,player.name)
- end
- saved.structures = buildzone.structures
- saved.totals = tracker.tallyTable(buildzone.structures)
- saved.highest = buildzone.highest - buildzone.y
- fs.makeDir("/records")
- local file = fs.open("/records/"..buildzone.x.."_"..buildzone.z,"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":"orange"}]')
- --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}
- table.insert(buildzone.buildings, building)
- if vocab.green then
- buildzone.greenBuildings = buildzone.greenBuildings + 1
- end
- buildzone.filledSlots = buildzone.filledSlots + vocab.slots
- local newHeight = y + vocab.height - buildzone.y -- the Y coordinate of the highest block above the ground. Our world has its ground at 55 which is in buildzone.y
- if newHeight > buildzone.highest then
- buildzone.highest = newHeight
- end
- -- count variety
- if buildzone.variety[vocab.id] then
- buildzone.variety[vocab.id] = buildzone.variety[vocab.id] + 1
- else
- buildzone.variety[vocab.id] = 1
- 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":"orange"}]')
- 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-40]","highscores")
- if #buildzone.variety > mostDiverse.count then
- commands.async.scoreboard("players","set","Most-Diverse_[out-of-40]","highscores",#buildzone.variety)
- 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.greenBuildings/#buildzone.buildings) --Gint is the green index, made from the number of green buildings over the total number of buildings
- 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":"orange"}]')
- ---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":"orange"}]')
- failParticle(x,y-1,z)
- end
- end
- return victory
- 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