Advertisement
antonsavov

Untitled

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