Advertisement
antonsavov

Untitled

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