Advertisement
antonsavov

Untitled

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