Advertisement
antonsavov

Untitled

Mar 9th, 2017
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 60.19 KB | None | 0 0
  1. local VERSION = '1.0.1 - record breaking message are now green'
  2. os.loadAPI('tracker')
  3. os.loadAPI('json')
  4.  
  5. print("Starting 20.000 Blocks")
  6.  
  7. DEBUG_MODE = false
  8. local monitor = peripheral.wrap("right")
  9. local ox,oy,oz = commands.getBlockPosition()
  10.  
  11. 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
  12. SPAWN_VILLAGER = false
  13. DO_GRID = true
  14. GRID_HOLE_CHANCE = 0
  15. NUMBER_OF_BUILDZONES = 6
  16. NUMBER_OF_VOCAB = 10
  17. GAME_LENGTH = 600
  18. VOCAB_WIDTH = 27
  19. VOCAB_HEIGHT = 19
  20. 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
  21. BUILDZONE_FLOOR_HEIGHT = -1
  22. HOMECOMER_TYPE = "Pig"
  23. HOMECOMER_VALUE = 90 --90 is for pig
  24. SPAWN = {
  25. x=12110,
  26. y=57,
  27. z=-1777,
  28. a1=90,
  29. a2=0
  30. }
  31. FIRSTZONE= {
  32. x=11685,
  33. y=57,
  34. z=-1869
  35. }
  36. WAITZONE = {
  37. x=12093,
  38. y=56,
  39. z=-1779,
  40. w=5,
  41. l=5
  42. }
  43. --this is the block at ~-4 ~ ~-4 from the corner of the shape zone
  44. --i.e., (the one with the grammar shape in it) of the vocab that is closest to zero
  45. FIRSTVOCAB= {
  46. x=0,
  47. y=57,
  48. z=5
  49. }
  50. VICTORY_HEIGHT = 30
  51. VICTORY_TOTAL = 50
  52. VICTORY_SPECIFIC = {name='garden',count=101}
  53.  
  54.  
  55. WOOL_PER_EMERALD = 64
  56.  
  57.  
  58. BLOCKS = {
  59. CAMP_FLOOR = {block='minecraft:sandstone',data=0},
  60. CONSTRUCTION = {block='minecraft:diamond_ore',data=0},
  61. RING = {block='minecraft:diamond_ore',data=0},
  62. DETECT = {block='minecraft:red_sandstone',data=0},
  63. DETECT_DEAD = {block='minecraft:obsidian',data=0},
  64. VOCAB_DETECT = {block="minecraft:quartz_block",data=0},
  65. VOCAB_REPLACE = {block="minecraft:coal_block",data=0},
  66. VICTORY_MARKER = {block="minecraft:emerald_block",data=0},
  67. PLUG = {block="minecraft:lapis_ore",data=0},
  68. PHVFLOOR = {block="minecraft:stone_slab",data=3},
  69. BUILDING_HOUSE = {block="minecraft:wool",data=0},
  70. BUILDING_GARDEN = {block="minecraft:wool",data=13},
  71. BUILDING_WATER = {block="minecraft:wool",data=1},
  72. _matWhiteSmooth ={block="mincreaft:stained_hardened_clay",data=0},
  73. _matWhiteSmooth2 = {block="minecraft:brick_block",data=0},
  74. _matYellowSmooth = {block="minecraft:stained_hardened_clay",data=4},
  75. _matPinkSmooth = {block="minecraft:stained_hardened_clay",data=6},
  76. _matBlueSmooth = {block="minecraft:stained_hardened_clay",data=9},
  77. _matPurpleSmooth = {block="minecraft:stained_hardened_clay",data=10},
  78. _matWhiteTextured = {block="minecraft:planks",data=4},
  79. _matYellowTextured = {block="minecraft:planks",data=1},
  80. _matPinkTextured = {block="minecraft:planks",data=0},
  81. _matBlueTextured = {block="minecraft:planks",data=2},
  82. _matPurpleTextured = {block="minecraft:planks",data=5},
  83. }
  84.  
  85. --contains a list of all posible Buildzones (build a bit later)
  86. LOCS = {}
  87.  
  88. if DEBUG_MODE then
  89. GAME_LENGTH = 12000
  90. NUMBER_OF_BUILDZONES = 1
  91. end
  92.  
  93. -- see if the file exists
  94. function file_exists(file)
  95. local f = fs.open(file, "rb")
  96. if f then f:close() end
  97. return f ~= nil
  98. end
  99.  
  100. --creates a grid of absolute references (0,0) (1,0)
  101. function buildGrid(w,h)
  102. local grid = readGridFromFile()
  103. if grid then
  104. -- grid was read from teh file successfully
  105. else
  106. --generate file from scratch
  107. grid = {}
  108. for z=0,h-1 do
  109. for x=0,w-1 do
  110. table.insert(grid,{x=x,z=z,played=false})
  111. end
  112. end
  113. end
  114. return grid
  115. end
  116.  
  117. function readGridFromFile()
  118. local result = nil
  119. fs.makeDir("/records")
  120. local filename = "/records/_buildzones-list.yaml"
  121.  
  122. if file_exists(filename) then
  123. ---read from file
  124. result = json.decodeFromFile(filename)
  125. end
  126. return result
  127. end
  128.  
  129. function writeGridToFile()
  130. fs.makeDir("/records")
  131. local filename = "/records/_buildzones-list.yaml"
  132.  
  133. local file = fs.open(filename,"w")
  134. file.write(json.encodePretty(LOCS))
  135. file.close()
  136. end
  137.  
  138. --sets where and how big the PHV area is
  139. --second number is along the long edge of PHV starting at the spawn side
  140. --first number is along the short edge of PHV starting from the park side
  141. if DEBUG_MODE then
  142. FIRSTZONE= {
  143. x=5,
  144. y=57,
  145. z=-7
  146. }
  147.  
  148. LOCS = buildGrid(1,3)
  149. else
  150. LOCS = buildGrid(11,27)
  151. end
  152.  
  153. --call these to return a proper minecraft item string including adventure mode properties
  154. function houseBlock(quant)
  155. text = BLOCKS.BUILDING_HOUSE.block..' '..quant..' '..BLOCKS.BUILDING_HOUSE.data..' {display:{Name:"Urban Resource",Lore:[Place this against a Detector to build denser, more urban buildings]},CanPlaceOn:["'..BLOCKS.BUILDING_HOUSE.block..'","'..BLOCKS.PLUG.block..'","'..BLOCKS.DETECT.block..'"]}'
  156. return text
  157. end
  158.  
  159.  
  160. function gardenBlock(quant)
  161. text = BLOCKS.BUILDING_GARDEN.block..' '..quant..' '..BLOCKS.BUILDING_GARDEN.data..' {display:{Name:"Nature Resource",Lore:[Place this against a Detector to build greener, more open buildings]},CanPlaceOn:["'..BLOCKS.BUILDING_HOUSE.block..'","'..BLOCKS.PLUG.block..'","'..BLOCKS.DETECT.block..'"]}'
  162. return text
  163. end
  164.  
  165. PICKAXE_USES = 40
  166. pickaxe = 'stone_pickaxe 1 '..131-PICKAXE_USES..' {CanDestroy:["'..BLOCKS.BUILDING_HOUSE.block..'"],display:{Name:"Resource Remover",Lore:[Use the pickaxe to remove up to '..PICKAXE_USES..' resource blocks]}}'
  167.  
  168.  
  169.  
  170. STARTING_ITEMS = {
  171. houseBlock(30), gardenBlock(30),pickaxe
  172. }
  173.  
  174.  
  175. DEFAULT_NAME = 'BUILDING'
  176. --[[
  177. VOCAB_NAMES = {
  178. 'freestand-house',
  179. 'freestand-house',
  180. 'freestand-house',
  181. 'freestand-house',
  182. 'dbl-ext-house',
  183. 'dbl-ext-house',
  184. 'dbl-ext-house',
  185. 'dbl-ext-house',
  186. 'bridge-house',
  187. 'bridge-house',
  188. 'bridge-garden',
  189. 'bridge-garden',
  190. 'ext-house',
  191. 'ext-house',
  192. 'ext-house',
  193. 'ext-house',
  194. 'riser-1',
  195. 'riser-2',
  196. 'city-garden',
  197. 'city-plaza',
  198. 'dbl-ext-garden',
  199. 'dbl-ext-garden',
  200. 'dbl-ext-garden',
  201. 'dbl-ext-garden',
  202. 'ext-garden',
  203. 'ext-garden',
  204. 'ext-garden',
  205. 'ext-garden',
  206. 'corner-garden',
  207. 'corner-garden',
  208. 'corner-garden',
  209. 'corner-garden',
  210. 'corner-house',
  211. 'corner-house',
  212. 'corner-house',
  213. 'corner-house',
  214. 'freestand-garden',
  215. 'freestand-garden',
  216. 'freestand-garden',
  217. 'freestand-garden'
  218. }
  219. --]]
  220.  
  221.  
  222. ----------------------------------------------------------------------------------------------------------------
  223. -- the data structure below represents the catalogue of vocabularies as built in minecraft
  224. -- id - is unique for each vocab, starting from 1 going to 40 currently
  225. -- column and row - represent the "physical" location of the vocab model in the catalogue in the minecraft world
  226. -- nameEN and name DE - are names for english and german. for now english names must not have spaces, use dashes (-) instead
  227. -- typeEN and typeDE - are the type names, also in english and german such as tech&science spaces
  228. -- height - is how many blocks is this structure tall
  229. -- 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
  230. -- green - is true or false and is used for easier calculation of the GREENEST GOAL - we dont use this field now and can be removed
  231. -- greenSlots - is how many slots are green and is used for easier calculation of the GREENEST GOAL
  232. VOCABS_DATA = {
  233. -- urban houses
  234. {id=1, column=1, row=1,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  235. {id=2, column=1, row=2,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  236. {id=3, column=1, row=3,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  237. {id=4, column=1, row=4,nameEN="SINGLE-FAMILY-HOUSE",nameDE="EINFAMILIENHAUS", typeEN="HOUSES",typeDE="HÄUSER",height=10, slots=2, green=false, greenSlots=0, rewardUrban=false, rewardCount=4},
  238. -- urban businesses
  239. {id=5, column=2, row=1,nameEN="GYM",nameDE="FITNESSSTUDIO", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=false, greenSlots=0, rewardUrban=false, rewardCount=8},
  240. {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, rewardUrban=false, rewardCount=8},
  241. {id=7, column=2, row=3,nameEN="HOTEL",nameDE="HOTEL", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=false, greenSlots=0, rewardUrban=false, rewardCount=8},
  242. {id=8, column=2, row=4 ,nameEN="BANK",nameDE="BANK", typeEN="BUSINESSES",typeDE="GESCHÄFTE",height=20, slots=5, green=false, greenSlots=0, rewardUrban=false, rewardCount=8},
  243. -- urban tech&science spaces
  244. {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, rewardUrban=false, rewardCount=10},
  245. {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, rewardUrban=false, rewardCount=10},
  246. -- green tech&science spaces
  247. {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, rewardUrban=true, rewardCount=10},
  248. {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, rewardUrban=true, rewardCount=10},
  249. -- urban house extensions
  250. {id=13, column=4, row=1,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  251. {id=14, column=4, row=2,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  252. {id=15, column=4, row=3,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  253. {id=16, column=4, row=4,nameEN="HOUSE-EXTENSION",nameDE="HAUSERWEITERUNG", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=10, slots=1, green=false, greenSlots=0, rewardUrban=false, rewardCount=6},
  254. --risers
  255. {id=17, column=5, row=1,nameEN="DOUBLE-FLOOR-RISER",nameDE="VERSCHIEBUNG-ZWEI-HOCH", typeEN="RISERS",typeDE="VERTIKALE VERSCHIEBUNGEN",height=0, slots=0, green=false, greenSlots=0, rewardUrban=true, rewardCount=8},
  256. {id=18, column=5, row=2,nameEN="SINGLE-FLOOR-RISER",nameDE="VERSCHIEBUNG-EINEN-HOCH", typeEN="RISERS",typeDE="VERTIKALE VERSCHIEBUNGEN",height=0, slots=0, green=false, greenSlots=0, rewardUrban=true, rewardCount=6},
  257. --plazas
  258. {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, rewardUrban=false, rewardCount=2},
  259. {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, rewardUrban=true, rewardCount=2},
  260. --green businesses
  261. {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, rewardUrban=true, rewardCount=8},
  262. {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, rewardUrban=true, rewardCount=8},
  263. {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, rewardUrban=true, rewardCount=8},
  264. {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, rewardUrban=true, rewardCount=8},
  265. ---green private garden extensions
  266. {id=25, column=7, row=1,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  267. {id=26, column=7, row=2,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  268. {id=27, column=7, row=3,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  269. {id=28, column=7, row=4,nameEN="HOUSE-GARDEN",nameDE="PRIVATGARTEN", typeEN="EXTENSIONS",typeDE="ERWEITERUNGEN",height=0, slots=0, green=true, greenSlots=1, rewardUrban=true, rewardCount=6},
  270. ---green gathering spaces
  271. {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, rewardUrban=true, rewardCount=9},
  272. {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, rewardUrban=true, rewardCount=9},
  273. {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, rewardUrban=true, rewardCount=9},
  274. {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, rewardUrban=true, rewardCount=9},
  275. ----urban gathering spaces
  276. {id=33, column=9, row=1,nameEN="CINEMA",nameDE="KINO", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  277. {id=34, column=9, row=2,nameEN="CONFERENCE-HALL",nameDE="KONFERENZHALLE", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  278. {id=35, column=9, row=3,nameEN="CAFÉ",nameDE="CAFÉ", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  279. {id=36, column=9, row=4,nameEN="ART-GALLERY",nameDE="KUNSTGALERIE", typeEN="GATHERING SPACES",typeDE="TREFFPUNKTE",height=8, slots=3, green=false, greenSlots=0, rewardUrban=false, rewardCount=9},
  280. ---green-roof houses
  281. {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, rewardUrban=true, rewardCount=4},
  282. {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, rewardUrban=true, rewardCount=4},
  283. {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, rewardUrban=true, rewardCount=4},
  284. {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, rewardUrban=true, rewardCount=4},
  285. }
  286.  
  287.  
  288. DEFAULT_REWARD = houseBlock(4)
  289.  
  290. REWARDS = {}
  291.  
  292.  
  293. --constructor for player object so that data structure is consistant
  294. function newPlayerData(name,x,y,z)
  295. local p = {
  296. name = name,
  297. x=x,
  298. y=y,
  299. z=z
  300. }
  301. return p
  302. end
  303.  
  304. --return a list of all players in the game world as player objects
  305. local function getAllPos(selector)
  306. local result, message = commands.tp("@a["..selector.."]","~ ~ ~")
  307. local names = {}
  308. if result == true then
  309. for i,result in ipairs(message) do
  310. local wordpattern = "[^, ]+"
  311. local numberpattern = "[%-% ]%d+[%.]%d+"
  312. local words,numbers = {},{}
  313.  
  314. for word in string.gmatch(result, wordpattern) do
  315. table.insert(words,word)
  316. end
  317.  
  318. for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
  319.  
  320. local coords = {
  321. x = math.floor(numbers[1]),
  322. y = math.floor(numbers[2]),
  323. z = math.floor(numbers[3])
  324. }
  325. local name = words[2]
  326. table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
  327. --print("Player Found - getAllPos")
  328. end
  329. end
  330. return names
  331. end
  332.  
  333. --sort table by random
  334. local function shuffleTable( t )
  335. local rand = math.random
  336. assert( t, "shuffleTable() expected a table, got nil" )
  337. local iterations = #t
  338. local j
  339.  
  340. for i = iterations, 2, -1 do
  341. j = rand(i)
  342. t[i], t[j] = t[j], t[i]
  343. end
  344. end
  345.  
  346. --returns a list of player objects containing all players who are standing on the given block, and who also are in the given selection
  347. local function getAllOnBlockType(block,selector)
  348. local result, message = commands.exec("execute @a["..selector.."] ~ ~ ~ detect ~ ~-1 ~ "..block.." -1 tp @p[r=1] ~ ~ ~")
  349. local names = {}
  350. if result == true then
  351. for i,result in ipairs(message) do
  352. local wordpattern = "[^, ]+"
  353. local numberpattern = "[%-% ]%d+[%.]%d+"
  354. local words,numbers = {},{}
  355.  
  356. for word in string.gmatch(result, wordpattern) do table.insert(words,word) end
  357. for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
  358.  
  359. if numbers[1] and numbers[2] and numbers[3] then
  360. local coords = {
  361. x = math.floor(numbers[1]),
  362. y = math.floor(numbers[2]),
  363. z = math.floor(numbers[3])
  364. }
  365. local name = words[2]
  366. table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
  367. print("Found a player - getOnBlock")
  368. else
  369. print("Error: Coordinate Numbers were missing")
  370. end
  371. end
  372. end
  373. return names
  374. end
  375.  
  376. --gives a player a HOMECOMER egg with their name on it. Removes all spawn eggs first
  377. local function giveHomecomer(name)
  378. commands.clear(name,'spawn_egg')
  379.  
  380. commands.give(name,'spawn_egg 1 '..HOMECOMER_VALUE..' {CanPlaceOn:["'..BLOCKS.PHVFLOOR.block..'","'..BLOCKS.CAMP_FLOOR.block..'","'..BLOCKS._matWhiteSmooth.block..'","'..BLOCKS._matWhiteSmooth2.block..'","'..BLOCKS._matYellowSmooth.block..'","'..BLOCKS._matPinkSmooth.block..'","'..BLOCKS._matBlueSmooth.block..'","'..BLOCKS._matPurpleSmooth.block..'","'..BLOCKS._matWhiteTextured.block..'","'..BLOCKS._matYellowTextured.block..'","'..BLOCKS._matPinkTextured.block..'","'..BLOCKS._matBlueTextured.block..'","'..BLOCKS._matPurpleTextured.block..'"],display:{Name:"HOMECOMER - '..name..'",Lore:[Use this on the floor to return to spawn]}}')
  381. end
  382.  
  383. --returns a list of HOMECOMER entities and their names
  384. local function getHomecomers()
  385. local result, message = commands.exec("execute @e[type="..HOMECOMER_TYPE.."] ~ ~ ~ tp @e[r=1] ~ ~ ~")
  386. local names = {}
  387. if result == true then
  388. for i,result in ipairs(message) do
  389. local wordpattern = "[^, ]+"
  390. local numberpattern = "[%-% ]%d+[%.]%d+"
  391. local words,numbers = {},{}
  392.  
  393. for word in string.gmatch(result, wordpattern) do table.insert(words,word) print(word) end
  394. for number in string.gmatch(result, numberpattern) do table.insert(numbers,number) end
  395.  
  396. if numbers[1] and numbers[2] and numbers[3] then
  397. local coords = {
  398. x = math.floor(numbers[1]),
  399. y = math.floor(numbers[2]),
  400. z = math.floor(numbers[3])
  401. }
  402. local name = words[4]
  403. table.insert(names,newPlayerData(name,coords.x,coords.y,coords.z))
  404. print("Found a player - getOnBlock "..name)
  405. else
  406. print("Error: Coordinate Numbers were missing")
  407. end
  408. end
  409. end
  410. return names
  411. end
  412.  
  413. local function removePlayerFromKew(game,playername)
  414. for _,kew in pairs(game.queues) do
  415. for index, player in ipairs(kew.playerlist) do
  416. if player.name == playername then
  417. table.remove(kew.playerlist,index)
  418. end
  419. end
  420. if #kew.playerlist == 0 and kew.phase == 2 then
  421. --game can be ended as no players are left
  422. kew.timer = 0
  423. end
  424. end
  425. end
  426.  
  427. local function movePlayerToSpawn(playername)
  428. respawnPlayer(playername)
  429. commands.async.tp(playername,SPAWN.x,SPAWN.y,SPAWN.z,SPAWN.a1,SPAWN.a2)
  430. commands.async.tellraw(playername,'["",{"text":"You used your HOMECOMER and TELEPORTED BACK TO SPAWN","color":"white"}]')
  431. commands.async.tellraw(playername,'["",{"text":"Du hast den HEIMKEHRER benutzt um dich zurück zum Anfang zu teleportieren.","color":"gold"}]')
  432. end
  433.  
  434. --takes a list of homecomers and deals with all those players, moving them back to spawn and removing them from game
  435. --also gives them a new homecomer
  436. local function dealWithHomecomers(game, homecomers)
  437. for _,homecomer in pairs(homecomers) do
  438. --remove player from current game if in game
  439. removePlayerFromKew(game,homecomer.name)
  440. --teleport them back to spawn
  441. movePlayerToSpawn(homecomer.name)
  442. --give a new homecomer
  443. giveHomecomer(homecomer.name)
  444. --particle effects
  445. --teleport message
  446. end
  447. --kill all homecomers
  448. if #homecomers>0 then
  449. commands.tp("@e[type="..HOMECOMER_TYPE.."]",100000,200,100000)
  450. commands.kill("@e[type="..HOMECOMER_TYPE.."]")
  451. os.sleep(#homecomers*0.2)
  452. end
  453. end
  454.  
  455.  
  456.  
  457.  
  458. --creates a villager with special items
  459. local function spawnVillager(x,y,z)
  460. 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"]}}} ]}}')
  461. end
  462.  
  463.  
  464. --displays a time as experience points to a selection of players
  465. local function displayTime(selector,minutes,seconds)
  466. --commands.title("@a["..selector.."]","subtitle",'{text:"Time left: '..minutes..":"..seconds..'",color:red,bold:false,underlined:false,italic:false,strikethrough:false,obfuscated:false}')
  467. commands.async.xp("-1000000L","@a["..selector.."]")
  468. local secondstot = (minutes * 60) + seconds
  469. commands.async.xp(tostring(secondstot).."L","@a["..selector.."]")
  470. end
  471.  
  472. --displays a title to a selection of players
  473. local function displayTitle(selector,text)
  474. commands.async.title("@a["..selector.."]","title",'{text:"'..text..'"}')
  475. end
  476.  
  477. --simply runs displayTitle on a list of players
  478. local function displayTitleToGroup(playerlist,text)
  479. for i,player in ipairs(playerlist) do
  480. displayTitle("name="..player.name,text)
  481. end
  482. end
  483.  
  484. --simply runs displayTime on a list of players
  485. local function displayTimeToGroup(playerlist,minutes,seconds)
  486. for i,player in ipairs(playerlist) do
  487. displayTime("name="..player.name,minutes,seconds)
  488. end
  489. end
  490.  
  491. --teleports a list of players to an exact place and sends them a message about it
  492. local function teleportToPoint(x,y,z,playerlist,clear,textEN, textDE)
  493. for i,player in ipairs(playerlist) do
  494. player.x = x
  495. player.y = y
  496. player.z = z
  497. commands.async.gamemode(2,player.name)
  498. if clear then
  499. commands.async.clear(player.name,"wool")
  500. commands.async.clear(player.name,"stone_pickaxe")
  501. end
  502. commands.tp("@a[name="..player.name.."]",x,y,z)
  503. commands.async.tellraw(player.name,'["",{"text":"'..textEN..'","color":"white"}]')
  504. commands.async.tellraw(player.name,'["",{"text":"'..textDE..'","color":"gold"}]')
  505. end
  506. end
  507.  
  508. --teleports a list of players to a given buildzone
  509. local function teleportToZone(buildzone,playerlist,textEN, textDE)
  510. teleportToPoint(buildzone.x+2+(buildzone.w/2),buildzone.y+5,buildzone.z+2+(buildzone.w/2),playerlist,true,textEN, textDE)
  511.  
  512. end
  513.  
  514. --gives the same list of items to a list of players
  515. local function giveItems(playerlist,itemlist)
  516. local given = 0
  517. for i,player in ipairs(playerlist) do
  518. --commands.async.clear(player.name)
  519. for j,item in ipairs(itemlist) do
  520. commands.async.give("@a[name="..player.name.."]",item)
  521. given = given +1
  522. end
  523. giveHomecomer(player.name)
  524. end
  525. return given
  526. end
  527.  
  528. --a multi builder which uses the vocab constructor to create sets of vocab
  529. local function makeVocabZones(quant,w)
  530. local x,y,z = FIRSTVOCAB.x, FIRSTVOCAB.y, FIRSTVOCAB.z
  531. local result = {}
  532. local id = 1
  533. for i=0,quant-1 do
  534. for k=0,3 do
  535. local zpos = i-4
  536. local ypos = k
  537. --print("vocab at X")
  538. --print(x-(2*w)-6)
  539. --print("and Z")
  540. --print(z+((w+1)*zpos))
  541. local nextVocab = newVocabZone(
  542. x-(2*w)-6,y+(ypos*(VOCAB_HEIGHT+3)),
  543. z+((w+1)*zpos),
  544. w,
  545. id,
  546. REWARDS[id] or DEFAULT_REWARD,
  547. VOCABS_DATA[id].nameEN or DEFAULT_NAME,
  548. VOCABS_DATA[id].nameDE or DEFAULT_NAME,
  549. VOCABS_DATA[id].typeEN,
  550. VOCABS_DATA[id].typeDE,
  551. VOCABS_DATA[id].height,
  552. VOCABS_DATA[id].slots,
  553. VOCABS_DATA[id].green,
  554. VOCABS_DATA[id].greenSlots,
  555. VOCABS_DATA[id].rewardUrban,
  556. VOCABS_DATA[id].rewardCount
  557. )
  558. table.insert(result,nextVocab)
  559. id = id +1
  560. end
  561. end
  562. return result
  563. end
  564.  
  565. --finds the next free location(or buildzone) for a new game in a given area.
  566. --giving force as True will mean it overrides the first location no matter what
  567. local function findNextLoc(width,zones,force)
  568. local x,y,z,locid = 0,0,0,1
  569. for i,loc in ipairs(LOCS) do
  570. locid = i
  571. x,y,z = FIRSTZONE.x+(loc.x*(width+1)),FIRSTZONE.y,FIRSTZONE.z+(-loc.z*(width+1)) -- these are the coordinates of this LOC in the minecraft world
  572. --print("testing for available zone at: "..x..", "..y..", "..z)
  573. --print("which is at grid cell at: "..loc.x..", "..loc.z)
  574. --local result,message = commands.testforblock(x,y+BUILDZONE_FLOOR_HEIGHT,z,"minecraft:air") -- this was used for the testing based on the minecraft model
  575. local result = true
  576. if loc.played then
  577. result = false
  578. print("zone has been played")
  579. end
  580. --print("testing done")
  581. --force the first zone to be selected unless it is taken in the "zones" parameter
  582. if force then result = true end
  583. --checks if the zone is already in the list of unavailable zones passed as parameter
  584. local zonefree = true
  585. for i,zone in ipairs(zones) do
  586. if zone.x == x and zone.z == z then
  587. zonefree = false
  588. end
  589. end
  590. --print("next position free is ",loc.x*width,oy,loc.z*width)
  591. --if result then print("true") else print("false") end
  592. if result and zonefree then
  593. --print("using loc: ",loc.x,loc.z)
  594. return x,y,z,locid --returns the coordinates of the new zone, plus its id in the LOCS table
  595. end
  596. end
  597. return nil,nil,nil, nil --returns empty if no zone is available
  598.  
  599. end
  600.  
  601. --relocates a buildzone to a new coordinate safely
  602. --avoids overlapping with other buildzones
  603. function moveBuildzone(buildzone,zones)
  604. local x,y,z,locid = findNextLoc(buildzone.w,zones)
  605. if x and y and z and locid then
  606. print("moved buildzone from "..buildzone.x..","..buildzone.z.." to "..x..","..y)
  607. local w = buildzone.w
  608. buildzone.x,buildzone.y,buildzone.z = x,y+BUILDZONE_FLOOR_HEIGHT,z
  609. buildzone.locid = locid --reassign the location id corresponding to the LOCS item for the grid cell of the moved zone
  610. buildzone.selector = "x="..x..",y="..tostring(y-1)..",z="..z..",dx="..w..",dy=256,dz="..w
  611. buildzone.structures = {} --a list of all vocabularies which have been contructed
  612. else
  613. print("buildzone at "..buildzone.x..","..buildzone.z.." stayed where it is")
  614. end
  615. end
  616.  
  617. --multi builder to create sets of buildzones using the buildzone constructor
  618. local function makeBuildzones(quant,vocab,width,height)
  619. local result = {}
  620. for i=1,quant do
  621. --print("locating available slot")
  622. local x,y,z,locid = findNextLoc(width,result)
  623. if x and y and z and locid then
  624. --print("made new buildzone at",x,y,z)
  625. table.insert(result,newBuildZone(x,y+height,z,width,vocab,locid))
  626. else
  627. --print("failed to make new buildzone")
  628. end
  629. end
  630.  
  631. local remaining = NUMBER_OF_BUILDZONES - #result
  632. --print("doing this remaining thing")
  633. for i=1, remaining do
  634. local x,y,z,locid = findNextLoc(width,result,true)
  635. if x and y and z and locid then
  636. --print("forced new buildzone at",x,y,z)
  637. table.insert(result,newBuildZone(x,y+height,z,width,vocab, locid))
  638. else
  639. print("failed to force new buildzone")
  640. end
  641. end
  642.  
  643.  
  644. return result
  645. end
  646.  
  647. --vocab constructor. Enforces some data structure
  648. function newVocabZone(x,y,z,w,id, reward,nameEN, nameDE, typeEN, typeDE, height, slots,green,greenSlots, rewardUrban, rewardCount)
  649. local nvz = {}
  650. nvz.x ,nvz.y ,nvz.z ,nvz.w = x,y,z,w
  651.  
  652. nvz.cx = nvz.x - nvz.w - 2
  653. nvz.cy = nvz.y
  654. nvz.cz = nvz.z
  655. nvz.nameEN = nameEN
  656. nvz.reward = reward
  657. --- new stuff
  658. nvz.id = id
  659. nvz.nameDE = nameDE
  660. nvz.typeEN = typeEN
  661. nvz.typeDE = typeDE
  662. nvz.height = height
  663. nvz.slots = slots
  664. nvz.green = green
  665. nvz.greenSlots = greenSlots
  666. nvz.rewardUrban = rewardUrban
  667. nvz.rewardCount = rewardCount
  668.  
  669. return nvz
  670.  
  671. end
  672.  
  673. --buildzone constructor. Enforces some data structure
  674. function newBuildZone(x,y,z,w,vocabZones,locid)
  675. local nbz = {}
  676. nbz.x ,nbz.y ,nbz.z ,nbz.w = x,y,z,w
  677. nbz.selector = "x="..x..",y="..(y-5)..",z="..z..",dx="..w..",dy=256,dz="..w
  678. nbz.structures = {} --a list of all vocabularies names which have been contructed
  679. nbz.buildings = {} --a list of all vocabularies with full data (x,y,z,id,name) which have been contructed
  680. nbz.filledSlots = 0 --to count how many slots have been filled with buildings. the matrix is 7x7x20 slots. one slot is 9x9x9 blocks big
  681. nbz.greenSlots = 0 --to count how many of the slots are green. the matrix is 7x7x20 slots. one slot is 9x9x9 blocks big
  682. 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
  683. nbz.waitingForCheck = {}
  684. nbz.highest = 0
  685. nbz.vocab = vocabZones
  686. nbz.locid = locid
  687.  
  688. return nbz
  689. end
  690.  
  691. --kew constructor. Enforces some data structure
  692. function newQueue(buildzone,maxplayers)
  693. local q = {}
  694. q.timer = 1
  695. q.phase = 1
  696.  
  697. q.victory = false
  698. q.phases = {
  699. {
  700. name = "Selecting Players",
  701. length = 25,
  702. displaylength = 15
  703. },
  704. {
  705. name = "Game In Progress",
  706. length = GAME_LENGTH,
  707. displaylength = 70
  708. },
  709. {
  710. name = "Round Complete",
  711. length = 35,
  712. displaylength = 5
  713. }
  714. }
  715. q.playerlist = {}
  716. q.maxplayers = maxplayers
  717. q.buildzone = buildzone
  718.  
  719. return q
  720. end
  721.  
  722.  
  723. --creates a ring of blocks using coordinates
  724. function fillRing(x,y,z,w,block)
  725. commands.fill(x,y,z,x+w,y,z,block)
  726. commands.fill(x+w,y,z,x+w,y,z+w,block)
  727. commands.fill(x,y,z+w,x+w,y,z+w,block)
  728. commands.fill(x,y,z+w,x,y,z,block)
  729. end
  730.  
  731. function setup()
  732. print("debug: starting setup function.")
  733. local game = {}
  734. game.vocab = {}
  735. game.builds = {}
  736. game.queues = {}
  737. game.waitlist = {}
  738. game.spawn = SPAWN
  739. game.lastClock = os.clock()
  740. game.nowTime = os.clock()
  741.  
  742. --generate vocab rewards
  743. for i=1,#VOCABS_DATA do
  744. if VOCABS_DATA[i].rewardUrban then
  745. REWARDS[i] = houseBlock(VOCABS_DATA[i].rewardCount)
  746. else
  747. REWARDS[i] = gardenBlock(VOCABS_DATA[i].rewardCount)
  748. end
  749. end
  750.  
  751. --kill all villagers
  752. commands.exec("kill @e[type=Villager]")
  753.  
  754. --buildzone and vocabzone creation
  755. print("debug-setup: making vocab zones.")
  756. game.vocab = makeVocabZones(NUMBER_OF_VOCAB,VOCAB_WIDTH)
  757. print("debug-setup: making building zones.")
  758. game.builds = makeBuildzones(NUMBER_OF_BUILDZONES,game.vocab,BUILDZONE_WIDTH,BUILDZONE_FLOOR_HEIGHT)
  759.  
  760. for i,build in ipairs(game.builds) do
  761. table.insert(game.queues,newQueue(build,4))
  762. end
  763. print("debug-setup: testing for properly setup vocabs.")
  764. for i,vz in ipairs(game.vocab) do
  765. local x,y,z,w = vz.x,vz.y,vz.z,vz.w
  766. local cx,cy,cz = vz.cx,vz.cy,vz.cz
  767.  
  768. local detector, message1 = commands.testforblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT.block)
  769. local blocker, message2 = commands.testforblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT_DEAD.block)
  770. if not (detector or blocker) then
  771. for nx=0,2 do
  772. for nz=0,2 do
  773. commands.setblock(x+(nx*9)+4,y-1,z+(nz*9)+4,BLOCKS.VOCAB_REPLACE.block)
  774. commands.setblock(cx+(nx*9)+4,cy-1,cz+(nz*9)+4,BLOCKS.VOCAB_DETECT.block)
  775. end
  776. end
  777. commands.setblock(x+(math.floor(w/2)),y,z+(math.floor(w/2)),BLOCKS.DETECT_DEAD.block)
  778.  
  779. end
  780.  
  781. end
  782.  
  783. print("debug-setup: adding scoreboards.")
  784. --[[
  785. for i, name in ipairs(VOCAB_NAMES) do
  786. commands.scoreboard("objectives","add",name,"dummy")
  787. end
  788. --]]
  789.  
  790. --print(#VOCABS_DATA)
  791. for i=1,#VOCABS_DATA do
  792. commands.scoreboard("objectives","add","building_"..i,"dummy")
  793. end
  794.  
  795. --commands.gamerule("doDaylightCycle",false) -- this is included in the spawn controller script
  796. commands.gamerule("keepInventory",true)
  797. --commands.gamerule("doTileDrops",false) -- this is included in the spawn controller script
  798. --commands.gamerule("logAdminCommands",false) -- this is included in the spawn controller script
  799. --commands.gamerule("commandBlockOutput",false) -- this is included in the spawn controller script
  800. --commands.time("set",6000) -- this is included in the spawn controller script
  801. commands.scoreboard("objectives","add","highscores","dummy","Best Neighbourhoods")
  802. commands.scoreboard("objectives","add","VillagerLife","dummy")
  803. commands.scoreboard("objectives","add","built","dummy", "Structures Built")
  804. commands.scoreboard("objectives","add","highest","dummy", "Personal Highest")
  805. commands.scoreboard("objectives","add","played","dummy","Games Played")
  806.  
  807. commands.title("@a","times",0,30,30) -- what does this do?
  808.  
  809. math.randomseed( os.time() )
  810. commands.scoreboard("objectives","setdisplay","sidebar","highscores")
  811. commands.scoreboard("objectives","setdisplay","list","played")
  812.  
  813. --print("time is: "..os.time())
  814. --print( "time is: "..textutils.formatTime( os.time(), false ) )
  815. --print("day is: "..os.day())
  816. print("computer clock is: "..os.clock())
  817.  
  818. if DEBUG_MODE then
  819. for i,build in ipairs(game.builds) do
  820. build.phase = 2
  821. build.timer = 500
  822. end
  823. end
  824.  
  825. print("Computer Co-ordinates ",ox,oy,oz)
  826. print("20.000 Blocks Active!")
  827.  
  828. return game
  829. end
  830.  
  831. function checkForHomecomers(game)
  832. --execute on all homecomers
  833. local homecomers = getHomecomers()
  834. dealWithHomecomers(game,homecomers)
  835. end
  836.  
  837. --main game loop
  838. --runs the game object through each of these update steps in order
  839. function update(game)
  840. local elapsed = updateClock(game)
  841. --update players
  842. checkPlayers(game)
  843. doTimerUpdates(game,elapsed)
  844. doPhaseUpdates(game)
  845. doPhaseEnds(game)
  846. checkBoundaries(game)
  847. checkForHomecomers(game)
  848. if #game.waitlist > 0 then allocateWaiters(game) end
  849. end
  850.  
  851. --calculates elapsed time during a game tick
  852. function updateClock(game)
  853. game.nowTime = os.clock()
  854. local elapsed = game.nowTime - game.lastClock
  855. game.lastClock = game.nowTime
  856. return elapsed
  857. end
  858.  
  859. --updates all kews in the game object based on elapsed time
  860. function doTimerUpdates(game,elapsed)
  861. for i,kew in ipairs(game.queues) do
  862. kew.timer = kew.timer - elapsed
  863. end
  864. end
  865.  
  866. --check players are inside their buildzone and move them back if not
  867. function checkBoundaries(game)
  868. for i,kew in ipairs(game.queues) do
  869. if kew.phase ==2 then
  870. --boundaries
  871. local x_min = kew.buildzone.x
  872. local x_max = kew.buildzone.x+kew.buildzone.w
  873. local z_min = kew.buildzone.z
  874. local z_max = kew.buildzone.z+kew.buildzone.w
  875.  
  876. local toBeCorrected = {}
  877.  
  878. for j,player in ipairs(kew.playerlist) do
  879. local listOfOne = getAllPos('m=2,name='..player.name)
  880. if listOfOne and listOfOne[1] then
  881. player.x = listOfOne[1].x
  882. player.y = listOfOne[1].y
  883. player.z = listOfOne[1].z
  884. local changed = false
  885. if player.x > x_max then
  886. changed = true
  887. player.x = x_max-2
  888. end
  889. if player.x < x_min then
  890. changed = true
  891. player.x = x_min+2
  892. end
  893. if player.z > z_max then
  894. changed = true
  895. player.z = z_max-2
  896. end
  897. if player.z < z_min then
  898. changed = true
  899. player.z = z_min+2
  900. end
  901. if changed then teleportToPoint(player.x,kew.buildzone.y,player.z,{player},false,"TELEPORTED BACK TO GAME: Please stay inside the building zone or use HOMECOMER to leave the game!", "Zurück ins Spiel teleportiert: Bitte bleib innerhalb des Baufeldes oder nutze den HEIMKEHRER um das Spiel zu verlassen!") end
  902. end
  903. end
  904. end
  905. end
  906. end
  907.  
  908.  
  909. --here you can set the logic which determines if a buildzone was valuable.
  910. --Return true if it is crap and should be replaced
  911. function checkIfBuildzoneIsCrap(buildzone)
  912. if #buildzone.structures < 5 then
  913. print("Buildzone was crap")
  914. return true
  915. end
  916. print("Buildzone was ok")
  917. return false
  918. end
  919.  
  920.  
  921. --Everything that happens after a buildzone was completed
  922. --due to time limit.
  923. function cleanAfterVictory(buildzone)
  924. commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,BLOCKS.VICTORY_MARKER.block)
  925. fillRing(buildzone.x,buildzone.y,buildzone.z,buildzone.w,"minecraft:air",0,"replace",BLOCKS.CONSTRUCTION.block,BLOCKS.CONSTRUCTION.data)
  926. for h=0,256-buildzone.y do
  927. 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)
  928. 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)
  929. 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)
  930. 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)
  931. end
  932. 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)
  933. 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")
  934.  
  935. local wasCrap = checkIfBuildzoneIsCrap(buildzone)
  936. if wasCrap then
  937. --mark this buildzone for replacement
  938. commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,"minecraft:air")
  939. else
  940. --need to find the LOCS item corresponding to this buildzone
  941. --change the flag to played=true
  942. LOCS[buildzone.locid].played = true
  943. --and write the LOCS object to the json file
  944. writeGridToFile()
  945. end
  946. end
  947.  
  948. --these happen every tick and require the game object
  949. --updates are performed on each Queue (kew) and within each
  950. --of those on each buildzone.
  951. function doPhaseUpdates(game)
  952. for i,kew in ipairs(game.queues) do
  953.  
  954. local minutes = string.format("%02d",math.floor(kew.timer/60))
  955. local seconds = string.format("%02d",math.floor(kew.timer - (minutes*60)))
  956. if kew.timer <= 0 then
  957. minutes = "00"
  958. seconds = "00"
  959. end
  960.  
  961. if kew.phase == 1 then
  962. --waiting phase
  963. if #kew.playerlist == kew.maxplayers and kew.timer > 5 then kew.timer = 5 end
  964. if not DEBUG_MODE and #kew.playerlist == 0 then kew.timer = kew.phases[1].length end
  965.  
  966. displayTitleToGroup(kew.playerlist,"Game starting!")
  967. displayTimeToGroup(kew.playerlist,minutes,seconds)
  968. --show countdown
  969. elseif kew.phase == 2 then
  970. --playing phase
  971. if #kew.playerlist == 0 then timer = 0 end -- finish if all players quit
  972. -- do vocab logic
  973. local victory = updatePlayedZone(kew.buildzone) --currently victory updatePlayedZone returns always false
  974. --
  975. displayTimeToGroup(kew.playerlist,minutes,seconds)
  976.  
  977. elseif kew.phase == 3 then
  978. --end phase
  979. displayTitleToGroup(kew.playerlist,"Use HOMECOMER to return")
  980. --displayTimeToGroup(kew.playerlist,minutes,seconds)
  981.  
  982.  
  983. end
  984. end
  985. end
  986.  
  987. --this runs after a buildzone is completed
  988. --it should tally structure types and set scoreboard highscores
  989. --it also rewards all participants with more played score
  990. function processHighscores(kew)
  991. local buildzone = kew.buildzone
  992.  
  993.  
  994.  
  995. --add score to players who finished this game
  996. for _,player in ipairs(kew.playerlist) do
  997. commands.async.scoreboard("players","add",player.name,"played",1)
  998. end
  999. end
  1000.  
  1001. --function to export a buildzone detail once it is complete
  1002. --requires a kew so it can access the playerlist
  1003. local function exportKewData(kew)
  1004. local buildzone = kew.buildzone
  1005. local saved = {}
  1006. saved.position =
  1007. {
  1008. x=buildzone.x,
  1009. y=buildzone.y,
  1010. z=buildzone.z
  1011. }
  1012. local timestamp = math.floor(os.clock())
  1013. --saved.timeCompleted = timestamp
  1014. saved.players = {}
  1015. for _, player in ipairs(kew.playerlist) do
  1016. table.insert(saved.players,player.name)
  1017. end
  1018. --saved.structures = buildzone.structures
  1019. saved.buildings = buildzone.buildings
  1020. saved.totals = tracker.tallyTable(buildzone.structures)
  1021. --saved.highest = buildzone.highest
  1022. saved.stats = {
  1023. cityVersion = CITY_VERSION,
  1024. height = buildzone.highest,
  1025. densityIndex = math.floor(100*buildzone.filledSlots/49), -- the density index is made from built area (filledSlots) over the ground area (7x7 slots = 49)
  1026. greenIndex = math.floor(100*buildzone.greenSlots/49), --the green index is made from green area (greenSlots) over the ground area (7x7 slots = 49)
  1027. variety = tablelength(buildzone.variety),
  1028. timeCompleted = timestamp,
  1029. gameLength = GAME_LENGTH
  1030. }
  1031.  
  1032. fs.makeDir("/records")
  1033.  
  1034. local file = fs.open("/records/"..timestamp.."at"..buildzone.x.."_"..buildzone.z..".yaml","w")
  1035. file.write(json.encodePretty(saved))
  1036. file.close()
  1037. end
  1038.  
  1039. --this code runs ONCE at the end of each phase
  1040. --what actually happens is specific to which phase the
  1041. --particular kew is in.
  1042. function doPhaseEnds(game)
  1043. for i,kew in ipairs(game.queues) do
  1044. if kew.timer <= 0 then
  1045. if kew.phase == 1 then
  1046. --waiting phase ends goto play phase
  1047.  
  1048. moveBuildzone(kew.buildzone,game.builds)
  1049. teleportToZone(kew.buildzone,kew.playerlist,"Your game has started! BUILD A HOUSE!", "Das Spiel hat begonnen! BAUE EIN HAUS!")--teleport selected players
  1050. cleanBuildzone(kew.buildzone)
  1051. prepareBuildzone(kew.buildzone)--prepare build zone
  1052. giveItems(kew.playerlist,STARTING_ITEMS) --give starting items
  1053. displayTitle(kew.buildzone.selector,"BUILD!")
  1054. kew.victory = false
  1055. --displayTime(kew.buildzone.selector,0,0)
  1056. kew.phase = 2
  1057. kew.timer = kew.phases[2].length
  1058. elseif kew.phase == 2 then
  1059. --playing phase ends goto end phase
  1060. processHighscores(kew)
  1061. exportKewData(kew)
  1062. cleanAfterVictory(kew.buildzone)
  1063. kew.phase = 3
  1064. --displayTime(kew.buildzone.selector,0,0)
  1065. kew.timer = kew.phases[3].length
  1066. elseif kew.phase == 3 then
  1067. --end phase ends goto waiting phase
  1068. removePlayersFromKew(game,kew)
  1069. kew.phase = 1
  1070. --displayTime(kew.buildzone.selector,0,0)
  1071. kew.timer = kew.phases[1].length
  1072. end
  1073. end
  1074. end
  1075. end
  1076.  
  1077.  
  1078. --Replaces everything that is needed to start the game. Does not rebuild the floor, or clear anything away.
  1079. --based on the settings it creates a full grid, or a partial grid, or no grid
  1080. --it also places the ring, although this is disabled for now
  1081. function prepareBuildzone(buildzone)
  1082. local bz = buildzone
  1083. local x,y,z,w = bz.x,bz.y,bz.z,bz.w
  1084.  
  1085. commands.async.fill(x,y-1,z,x+w,y-1,z+w,BLOCKS.CAMP_FLOOR.block) --place the white grid accross the full buildzone as a base
  1086.  
  1087. fillRing(buildzone.x,buildzone.y-1,buildzone.z,buildzone.w,BLOCKS.CONSTRUCTION.block) --this draws the construction stripe around the buildzone
  1088. --create the grid of detectors surrounded by plus plugs
  1089. if DO_GRID then
  1090. for x=0,6 do
  1091. for z=0,6 do
  1092. local rand = math.random()*100
  1093. --local result, text = commands.testforblock(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+4,BLOCKS.CAMP_FLOOR.block)
  1094. if rand > GRID_HOLE_CHANCE then --and result then
  1095. commands.async.setblock(bz.x+(x*9)+4,bz.y,bz.z+(z*9)+4,BLOCKS.DETECT.block,BLOCKS.DETECT.data,"replace","minecraft:air")
  1096. 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)
  1097. 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)
  1098. --commands.async.setblock(bz.x+(x*9)+4,bz.y-1,bz.z+(z*9)+4,BLOCKS.CAMP_FLOOR.block)
  1099. end
  1100. end
  1101. end
  1102. end
  1103. commands.async.setblock(buildzone.x,buildzone.y,buildzone.z,BLOCKS.CONSTRUCTION.block)
  1104. end
  1105.  
  1106. --deletes everything inside the buildzone
  1107. function cleanBuildzone(buildzone)
  1108. print("Cleaning buildzone")
  1109. for h=0,VICTORY_HEIGHT+20 do
  1110. commands.async.fill(buildzone.x,buildzone.y+h,buildzone.z,buildzone.x+buildzone.w,buildzone.y+h,buildzone.z+buildzone.w,"minecraft:air")
  1111. end
  1112. end
  1113.  
  1114. --[[
  1115. --moves all players assigned to the queue into the waiting area for the provided game.
  1116. --It also changes them to Adventure mode and clears their inventory
  1117. function respawnPlayers(game,kew)
  1118. 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
  1119. for i,player in ipairs(kew.playerlist) do
  1120. --table.insert(game.waitlist,player)
  1121. respawnPlayer(player,"")
  1122. end
  1123. kew.playerlist = {}
  1124. end
  1125. --]]
  1126.  
  1127. function removePlayersFromKew(game,kew)
  1128. for _, player in ipairs(kew.playerlist) do
  1129. --commands.tell(player.name,"Your game is over. Use your Heimkehrer to return to spawn")
  1130. -- announce success in English
  1131. commands.async.tellraw(player.name,'["",{"text":"TIME OUT! GAME COMPLETE! Use your HOMECOMER to return to spawn.","color":"white"}]')
  1132. -- announce success in German
  1133. commands.async.tellraw(player.name,'["",{"text":"ENDE! SPIEL ABGESCHLOSSEN! Nutze den HEIMKEHRER um zum Anfang zurück zu kehren.","color":"gold"}]')
  1134. end
  1135. kew.playerlist = {}
  1136. end
  1137.  
  1138. function respawnPlayer(playername,message)
  1139. commands.tell(playername,message)
  1140. commands.async.gamemode(2,playername)
  1141. commands.async.clear(playername,"minecraft:wool")
  1142. commands.async.clear(playername,"minecraft:stone_pickaxe")
  1143. end
  1144.  
  1145. function checkForPlayerInBuildzone(player,buildzone)
  1146. local result,message = commands.testfor('@a[name='..player.name..','..buildzone.selector..']')
  1147. return result
  1148. end
  1149.  
  1150. function checkForPlayerInWaitzone(player)
  1151. local selector = "x="..WAITZONE.x..",y="..WAITZONE.y..",z="..WAITZONE.z..",dx="..WAITZONE.w..",dy=256,dz="..WAITZONE.l
  1152. local result,message = commands.testfor('@a[name='..player.name..','..selector..']')
  1153. return result
  1154. end
  1155.  
  1156. function checkPlayers(game)
  1157. local selector = "x="..WAITZONE.x..",y="..WAITZONE.y..",z="..WAITZONE.z..",dx="..WAITZONE.w..",dy=256,dz="..WAITZONE.l
  1158. local loggedIn = getAllPos('m=2,'..selector)
  1159. --refresh waitlist
  1160. game.waitlist = loggedIn
  1161. --check currently playing players
  1162. for l,kew in ipairs(game.queues) do
  1163. for i,builder in ipairs(kew.playerlist) do
  1164. local isPlaying = checkForPlayerInBuildzone(builder,kew.buildzone)
  1165. --remove players who are already in kews from the waitlist
  1166. for j, player in ipairs(loggedIn) do
  1167. if player.name == builder.name then
  1168. table.remove(loggedIn,j)
  1169. end
  1170. end
  1171. --if the game is in progress and the player is not found then remove them from the gamekew
  1172. if not isPlaying and kew.phase == 2 then
  1173. --table.remove(kew.playerlist,i)
  1174. --print("Removed "..builder.name.." from game in progress")
  1175. end
  1176. end
  1177. end
  1178. end
  1179.  
  1180. --adds players who wait in the orange room to slots in waiting buildzones
  1181. function allocateWaiters(game)
  1182. --find free slots
  1183. local freeslots = {}
  1184. for i, kew in ipairs(game.queues) do
  1185. if kew.phase == 1 and #kew.playerlist < kew.maxplayers then
  1186. local slots = kew.maxplayers - #kew.playerlist
  1187. for j=1,slots do
  1188. table.insert(freeslots,kew)
  1189. end
  1190. end
  1191. end
  1192.  
  1193. --RE-ENABLE SECOND SHUFFLETABLE IF YOU WANT RANDOM PLAYER MATCHUPS
  1194. shuffleTable(game.waitlist)
  1195. --shuffleTable(freeslots)
  1196.  
  1197. while #freeslots > 0 and #game.waitlist > 0 do
  1198. local player = table.remove(game.waitlist,1)
  1199. local freeslot = table.remove(freeslots,1).playerlist
  1200. table.insert(freeslot,player)
  1201. end
  1202. end
  1203.  
  1204. --PARTICLE FUNCTIONS
  1205. --particles shown to player while their shape is being checked for match
  1206. function searchParticle(x,y,z)
  1207. commands.async.particle("fireworksSpark",x,y,z,0.01,3,0.01,0.01,100)
  1208. end
  1209. -- particles shown to player on successful vocab match
  1210. function successParticle(x,y,z)
  1211. commands.async.particle("happyVillager",x,y,z,2,2,2,1,1000)
  1212. commands.async.playsound("random.levelup","@a",x,y,z,1,1.2)
  1213. end
  1214. --- particles shown to player on failed vocab match
  1215. function failParticle(x,y,z)
  1216. commands.async.particle("reddust",x,y,z,0.1,0.1,1.5,1,200)
  1217. commands.async.particle("reddust",x,y,z,1.5,0.1,0.1,1,200)
  1218. commands.async.playsound("random.bowhit","@a",x,y,z,1,0.8)
  1219. end
  1220.  
  1221. --makes sure that incoming check requests dont exist already
  1222. function addToChecklist(player,buildzone)
  1223. for _, detector in ipairs(buildzone.waitingForCheck) do
  1224. if detector.x == player.x and detector.y == player.y and detector.z == player.z then
  1225. return false
  1226. end
  1227. end
  1228. table.insert(buildzone.waitingForCheck,player)
  1229. return true
  1230. end
  1231.  
  1232. --removes all barrier blocks from a buildzone which are used to carve space in vocabs
  1233. function cleanBarriers(buildzone)
  1234. for h=0,200 do
  1235. 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")
  1236. end
  1237. end
  1238.  
  1239. --The main chunk of code which deals with stepping on detector blocks and reading the vocab
  1240. function updatePlayedZone(buildzone)
  1241. local victory = false
  1242. local buildzoneSelector = buildzone.selector
  1243. --get all players on diamond, add them to the list of things to check
  1244. local detectLocations = getAllOnBlockType(BLOCKS.DETECT.block,buildzoneSelector)
  1245. for _, player in ipairs(detectLocations) do
  1246. addToChecklist(player,buildzone)
  1247. end
  1248.  
  1249. --DEAL WITH THE DETECTOR AT THE TOP OF THE LIST IF THERE IS ONE
  1250. if #buildzone.waitingForCheck > 0 then
  1251. --DO PARTICLE EFFECTS IF A DETECTING BLOCK THAT IS DETECTING
  1252. for i,loc in ipairs(buildzone.waitingForCheck) do
  1253. searchParticle(loc.x,loc.y+1,loc.z)
  1254. end
  1255. local totalResult = false
  1256. local checked = table.remove(buildzone.waitingForCheck,1)
  1257. local x,y,z,name = checked.x,checked.y,checked.z,checked.name
  1258. for i,vocab in pairs(buildzone.vocab) do
  1259. 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")
  1260. if result then
  1261. --clone in the correct vocab
  1262. 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")
  1263. if DEBUG_MODE then
  1264. print(clonemes[1])
  1265. end
  1266. commands.async.give(name,vocab.reward)
  1267. -- announce vocab success in English
  1268. local rewardType = 'nature'
  1269. local rewardTypeDE = 'grüne'
  1270. if vocab.rewardUrban then
  1271. rewardType = 'urban'
  1272. rewardTypeDE = 'urbane'
  1273. end
  1274. --print(vocab.typeEN)
  1275. --print(vocab.nameEN)
  1276. --print(vocab.height)
  1277. --print(vocab.slots)
  1278. --print(vocab.greenSlots)
  1279. --print(vocab.rewardCount)
  1280. --print(rewardType)
  1281. commands.async.tellraw(name,'["",{"text":"You built a '..vocab.nameEN.. ' ('..vocab.typeEN..'), which is '..vocab.height..'m tall and gives '..vocab.slots..' density pts, '..vocab.greenSlots..' green pts and '..vocab.rewardCount..'x '..rewardType..' resource!","color":"white"}]')
  1282. -- announce vocab success in German
  1283. commands.async.tellraw(name,'["",{"text":"Du hast ein '..vocab.typeDE..' | '..vocab.nameDE.. ' gebaut, das '..vocab.height..' Meter hoch ist und dir '..vocab.slots..' Punkte für die Dichte einbringt, jedoch '..vocab.greenSlots..' Punkte für Grünflächen und '..vocab.rewardCount..' '..rewardTypeDE..' Ressourcen!","color":"gold"}]')
  1284. --clear out barrier blocks
  1285. cleanBarriers(buildzone)
  1286.  
  1287. --ADD THE NEW STRUCTURE TO THE RECORDS
  1288. table.insert(buildzone.structures,vocab.nameEN) ---CHANGE HERE to make it record the place of the vocab too x, y, z and vocab id
  1289. local building = {id=vocab.id,xpos=x,ypos=y,zpos=z,name=vocab.nameEN,time=os.clock(),player=name}
  1290. table.insert(buildzone.buildings, building)
  1291. --if vocab.green then
  1292. buildzone.greenSlots = buildzone.greenSlots + vocab.greenSlots
  1293. --end
  1294. buildzone.filledSlots = buildzone.filledSlots + vocab.slots
  1295. 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
  1296. if newHeight > buildzone.highest then
  1297. buildzone.highest = newHeight
  1298. end
  1299. -- count variety
  1300. --print("adding variety: "..vocab.id)
  1301. 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
  1302. --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
  1303. 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
  1304. 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
  1305. 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
  1306. 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
  1307. if varietyId ~= 17 and varietyId ~= 18 then --skip the two riser as they ar enot buildings
  1308. if buildzone.variety[varietyId] then
  1309. --print("increasing existing item")
  1310. buildzone.variety[varietyId] = buildzone.variety[varietyId] + 1
  1311. else
  1312. --print("adding new item")
  1313. buildzone.variety[varietyId] = 1
  1314. end
  1315. end
  1316.  
  1317. --- CHECK FOR PERSONAL RECORDS
  1318. --- check if the new structure is the highest
  1319. --- CHANGE here to live detect the contribution of the new structure to the 4 goals and update them
  1320.  
  1321. local personalbest = tracker.getScore(name,"highest")
  1322. if personalbest.count < newHeight then
  1323. --commands.async.tell(name,"You just topped your personal record for highest structure!")
  1324. commands.async.scoreboard("players","add",name,"highest",1)
  1325. -- announce success in English
  1326. commands.async.tellraw(name,'["",{"text":"You just topped your personal record for highest neighbourhood!","color":"green"}]')
  1327. -- announce success in German
  1328. commands.async.tellraw(name,'["",{"text":"Du hast soeben deinen persönlichen Rekord für die höchste Nachbarschaft gebrochen!","color":"gold"}]')
  1329. end
  1330.  
  1331. ---
  1332. ---
  1333. -- CHECK if placing the current structure would result in beating a server-wide record on the 4 goals
  1334. --calculate total slots - FOR GOAL "DENSEST NEIGHBOURHOOD"
  1335. local most = tracker.getScore("Densest_[points]","highscores")
  1336. local Kint = math.floor(100 * buildzone.filledSlots / 49) -- Kint is the density index made from built area (filledSlots) over ground area (7x7 slots = 49)
  1337. if Kint > most.count then
  1338. commands.async.scoreboard("players","set","Densest_[points]","highscores",Kint)
  1339. -- announce success in English
  1340. commands.async.tellraw("@a",'["",{"text":"Great! '..name.. ' just topped the record for the DENSEST NEIGHBOURHOOD!","color":"green"}]')
  1341. -- announce success in German
  1342. commands.async.tellraw("@a",'["",{"text":"Sehr gut! '..name.. ' hat einen neuen Rekord für die DICHTESTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1343. --commands.async.say("@a","The record for the Densest Neighbourhood has been topped!")
  1344. end
  1345.  
  1346. -- FOR THE GOAL "MOST DIVERSE NEIGHBOURHOOD"
  1347. -- here we need to count how many varieties of buildings there are
  1348. --local structures = tracker.tallyTable(buildzone.structures) -- this counts the variety of buildings in a game
  1349. local mostDiverse = tracker.getScore("Most-Diverse_[out-of-26]","highscores")
  1350. local typeCount = tablelength(buildzone.variety)
  1351. --print("variety count is: "..typeCount)
  1352. if typeCount > mostDiverse.count then
  1353. commands.async.scoreboard("players","set","Most-Diverse_[out-of-26]","highscores", typeCount)
  1354. -- announce success in English
  1355. commands.async.tellraw("@a",'["",{"text":"Wow! '..name.. ' just topped the record for the MOST DIVERSE NEIGHBOURHOOD!","color":"green"}]')
  1356. -- announce success in German
  1357. commands.async.tellraw("@a",'["",{"text":"Wow! '..name.. ' hat soeben einen neuen Rekord für die VIELSEITIGSTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1358. --commands.async.say("@a","The record for the Most Diverse Neighbourhood has been topped!")
  1359. end
  1360.  
  1361. -- FOR THE GOAL "GREENEST NEIGHBOURHOOD"
  1362. -- here we need to count the number of green vocabs
  1363. local greenest = tracker.getScore("Greenest_[points]","highscores")
  1364. local Gint = math.floor(100*buildzone.greenSlots/49) --Gint is the green index, made from green area (greenSlots) over ground area (7x7 slots = 49)
  1365. if Gint > greenest.count then
  1366. commands.async.scoreboard("players","set","Greenest_[points]","highscores",Gint)
  1367. -- announce success in English
  1368. commands.async.tellraw("@a",'["",{"text":"Awesome! '..name.. ' just topped the record for the GREENEST NEIGHBOURHOOD!","color":"green"}]')
  1369. -- announce success in German
  1370. commands.async.tellraw("@a",'["",{"text":"Klasse! '..name.. ' hat einen neuen Rekord für die GRÜNSTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1371. ---commands.async.say("@a","The record for the Densest Neighbourhood has been topped!")
  1372. end
  1373.  
  1374. --calculate highest placement -- FOR THE GOAL "TALLEST NEIGHBOURHOOD"
  1375. local highest = tracker.getScore("Tallest_[meters]","highscores")
  1376. if buildzone.highest > highest.count then
  1377. commands.async.scoreboard("players","set","Tallest_[meters]","highscores",buildzone.highest)
  1378. -- announce success in English
  1379. commands.async.tellraw("@a",'["",{"text":"Incredible! '..name..' just topped the record for TALLEST NEIGHBOURHOOD!","color":"green"}]')
  1380. -- announce success in German
  1381. commands.async.tellraw("@a",'["",{"text":"Unglaublich! '..name..' hat einen neuen Rekord für die HÖCHSTE NACHBARSCHAFT aufgestellt!","color":"gold"}]')
  1382. --commands.async.say("@a","The record for the Tallest Negihbourhood has been topped!")
  1383. end
  1384.  
  1385.  
  1386. --increase the "how many structures did i build" score for the building player
  1387. commands.async.scoreboard("players","add",name,"built",1)
  1388. commands.async.scoreboard("players","add",name,"building_"..vocab.id,1)
  1389.  
  1390. totalResult = true
  1391. break
  1392.  
  1393. end
  1394. end
  1395. if totalResult then
  1396. --yey win, do a happy time
  1397. successParticle(x,y,z)
  1398. else
  1399. --no vocab found so do a fail particle
  1400. --announce in English
  1401. commands.async.tellraw(name,'["",{"text":"The shape you have built does not match any shape in the catalogue, try a different one.","color":"red"}]')
  1402. -- announce in German
  1403. commands.async.tellraw(name,'["",{"text":"Die Kombination, die du gebaut hast passt leider zu keinem Gebäude, versuche es mit einer anderen Form.","color":"gold"}]')
  1404. failParticle(x,y-1,z)
  1405. end
  1406. end
  1407. return victory
  1408. end
  1409.  
  1410. -- returns how many items are in a table/list
  1411. function tablelength(T)
  1412. local count = 0
  1413. for _ in pairs(T) do count = count + 1 end
  1414. return count
  1415. end
  1416.  
  1417. --Display game information on the monitor
  1418. function debugDisplay(game)
  1419. monitor.clear()
  1420. if blink then
  1421. monitor.setCursorPos(1,1)
  1422. monitor.setTextColor(colors.red)
  1423. monitor.write("Running")
  1424. monitor.setTextColor(colors.white)
  1425. redstone.setOutput("top",true)
  1426. blink = false
  1427. else
  1428. redstone.setOutput("top",false)
  1429. blink = true
  1430. end
  1431. local line = 2
  1432.  
  1433. for i,kew in ipairs(game.queues) do
  1434. monitor.setCursorPos(1,line)
  1435. local minutes = string.format("%02d",math.floor(kew.timer/60))
  1436. local seconds = string.format("%02d",math.floor(kew.timer - (minutes*60)))
  1437. monitor.write("Buildzone "..i.." | Phase: "..kew.phase.." | Time: "..minutes..":"..seconds)
  1438. monitor.setCursorPos(1,line+1)
  1439. for i,player in ipairs(kew.playerlist) do
  1440. monitor.write(player.name.." ")
  1441. end
  1442. line = line +2
  1443. end
  1444.  
  1445. monitor.setCursorPos(1,10)
  1446. for i,player in ipairs(game.waitlist) do
  1447. monitor.write(player.name.." ")
  1448. end
  1449. end
  1450.  
  1451. --BEGIN RUNTIME CODE
  1452. local blink = true
  1453. local game = setup()
  1454. while true do
  1455. update(game)
  1456. if monitor then debugDisplay(game) end
  1457. commands.async.weather("clear",10000)
  1458.  
  1459. local resetbutton = redstone.getInput("left")
  1460. if resetbutton then
  1461. print("reset!")
  1462. for i,kew in ipairs(game.queues) do
  1463. if kew.phase == 2 then
  1464. kew.timer = 5
  1465. end
  1466. end
  1467. end
  1468. sleep(2)
  1469. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement