Last active
June 10, 2018 14:03
-
-
Save mkarneim/a86a1e7a6c02fbd850d2ef4d4b618fb3 to your computer and use it in GitHub Desktop.
Tetris Clone for Wizards of Lua, originally created by Adrodoc55
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
This is a simple Tetris clone for Minecraft | |
created with Wizards of Lua magic | |
by Adrodoc55 | |
with some minor patches by mickkay. | |
To load this Gist into your server, just execute the following command: | |
/wol shared-file gist get https://gist.github.com/mkarneim/a86a1e7a6c02fbd850d2ef4d4b618fb3 | |
Then, to create the game, orient yourself facing north, | |
place six blocks where you want them, and use the following 6 commands | |
to turn each of these blocks into one of the 6 controls: | |
/lua require("tetris"):button("start", "lua spell:move('north',23); spell:move('west',6); spell:move('down',4); require('tetris'):start()", 0) | |
/lua require("tetris"):button("left", "lua Events.fire('tetris-left')", 14) | |
/lua require("tetris"):button("right", "lua Events.fire('tetris-right')", 2) | |
/lua require("tetris"):button("counter clockwise", "lua Events.fire('tetris-rotate-counter-clockwise')", 14) | |
/lua require("tetris"):button("clockwise", "lua Events.fire('tetris-rotate-clockwise')", 2) | |
/lua require("tetris"):button("down", "lua Events.fire('tetris-down')", 0) | |
]]-- | |
local tetris = { | |
delay = 10, | |
width = 10, | |
height = 20, | |
rotationCenter = Vec3(0,-1,0) | |
} | |
local log | |
function tetris:button(label, action, rotation) | |
spell.block = Blocks.get("standing_sign"):withData( | |
{rotation=rotation} | |
):withNbt( | |
{ | |
Text1=[[ | |
{"text":"]]..label..[[","clickEvent":{"action":"run_command","value":"]]..action..[["}} | |
]], | |
} | |
) | |
end | |
function tetris:setup() | |
spell.pos = self.origin | |
spell:execute('fill ~ ~-1 ~ ~%s ~%s ~ sandstone', self.width + 1, self.height + 1) | |
spell:execute('fill ~1 ~ ~ ~%s ~%s ~ air', self.width, self.height) | |
end | |
function tetris:start(pos) | |
spell:execute('wol spell break byName tetris') | |
spell.name = "tetris" | |
self.origin = pos or spell.pos | |
self.upperCenter = self.origin + Vec3(self.width//2 + 1, self.height-1+2, 0) | |
self:setup() | |
self.brick = nil | |
self.queue = Events.collect( | |
'tetris-down', | |
'tetris-left', | |
'tetris-right', | |
'tetris-rotate-clockwise', | |
'tetris-rotate-counter-clockwise' | |
) | |
while true do | |
if self.brick == nil or not self.brick:canMoveRelative(Vec3(0, -1, 0)) then | |
if self.brick ~= nil then | |
tetris:clearFullRows() | |
end | |
self.brick = Brick.new(self.upperCenter) | |
if not self.brick:canBePlaced() then | |
spell:execute('tellraw @a[r=50] {"text":"[tetris] Game Over!","color":"gold"}') | |
return | |
end | |
self.brick:place() | |
else | |
self.brick:moveRelative(Vec3(0, -1, 0)) | |
end | |
tetris:handleUserInputUntil(Time.gametime + self.delay) | |
end | |
end | |
function tetris:clearFullRows() | |
for y=1,self.height do | |
while true do | |
for x=1,self.width do | |
spell.pos = self.origin + Vec3(x,y,0) | |
if spell.block.name == 'air' then | |
goto label | |
end | |
end | |
spell.pos = self.origin | |
spell:execute('clone ~1 ~%s ~ ~%s ~%s ~ ~1 ~%s ~ replace move', y , self.width, self.height, y-1) | |
end | |
::label:: | |
end | |
end | |
function tetris:handleUserInputUntil(time) | |
while true do | |
local event = self.queue:next(time - Time.gametime) | |
if event == nil then | |
break | |
elseif event.name == 'tetris-down' then | |
while self.brick:canMoveRelative(Vec3(0, -1, 0)) do | |
self.brick:moveRelative(Vec3(0, -1, 0)) | |
end | |
elseif event.name == 'tetris-left' then | |
local relative = Vec3(-1, 0, 0) | |
if self.brick:canMoveRelative(relative) then | |
self.brick:moveRelative(relative) | |
end | |
elseif event.name == 'tetris-right' then | |
local relative = Vec3(1, 0, 0) | |
if self.brick:canMoveRelative(relative) then | |
self.brick:moveRelative(relative) | |
end | |
elseif event.name == 'tetris-rotate-clockwise' then | |
self.brick:maybeRotateClockwise() | |
elseif event.name == 'tetris-rotate-counter-clockwise' then | |
self.brick:maybeRotateCounterClockwise() | |
end | |
end | |
end | |
declare('Brick') | |
local templates = { | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(0,-2,0),Vec3(0,-3,0)}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(0,-2,0),Vec3(-1,-2,0)}, | |
{Vec3(0,-2,0),Vec3(-1,0,0),Vec3(-1,-1,0),Vec3(-1,-2,0)}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(-1,-1,0),Vec3(-1,-2,0)}, | |
{Vec3(0,-1,0),Vec3(0,-2,0),Vec3(-1,0,0),Vec3(-1,-1,0)}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(0,-2,0),Vec3(-1,-1,0),}, | |
{Vec3(0,0,0),Vec3(0,-1,0),Vec3(-1,0,0),Vec3(-1,-1,0)} | |
} | |
local colors = { | |
'light_blue', | |
'blue', | |
'orange', | |
'red', | |
'lime', | |
'magenta', | |
'yellow' | |
} | |
function Brick.new(pos) | |
if pos == nil then | |
error("pos==nil") | |
end | |
local i = math.random(#templates) | |
local result = { | |
pos = pos, | |
blocks = templates[i], | |
color = colors[i] | |
} | |
setmetatable(result, Brick) | |
return result | |
end | |
function Brick:canBePlaced() | |
for k,blockPos in pairs(self.blocks) do | |
spell.pos = self.pos + blockPos | |
if spell.block.name ~= 'air' then | |
return false | |
end | |
end | |
return true | |
end | |
function Brick:place() | |
self:setBlocks(Blocks.get('wool'):withData({color=self.color})) | |
end | |
function Brick:breakMe() | |
self:setBlocks(Blocks.get('air')) | |
end | |
function Brick:setBlocks(block) | |
for k,blockPos in pairs(self.blocks) do | |
spell.pos = self.pos + blockPos | |
spell.block = block | |
end | |
end | |
function Brick:canMoveRelative(vec) | |
return self:canMoveTo(self.pos + vec) | |
end | |
function Brick:canMoveTo(pos) | |
for k,blockPos in pairs(self.blocks) do | |
local blockPos = pos + blockPos | |
if not self:contains(blockPos) then | |
spell.pos = blockPos | |
if spell.block.name ~= 'air' then | |
return false | |
end | |
end | |
end | |
return true | |
end | |
function Brick:contains(pos) | |
for k,blockPos in pairs(self.blocks) do | |
if pos == self.pos + blockPos then | |
return true | |
end | |
end | |
return false | |
end | |
function Brick:moveRelative(vec) | |
self:moveTo(self.pos + vec) | |
end | |
function Brick:moveTo(pos) | |
self:breakMe() | |
self.pos = pos | |
self:place() | |
end | |
function Brick:maybeRotateClockwise() | |
local blocks = {} | |
for k,blockPos in pairs(self.blocks) do | |
local relative = blockPos - tetris.rotationCenter | |
local result = tetris.rotationCenter + Vec3(relative.y, -relative.x, 0) | |
table.insert(blocks, result) | |
end | |
self:maybeTransformInto(blocks) | |
end | |
function Brick:maybeRotateCounterClockwise() | |
local blocks = {} | |
for k,blockPos in pairs(self.blocks) do | |
local relative = blockPos - tetris.rotationCenter | |
local result = tetris.rotationCenter + Vec3(-relative.y, relative.x, 0) | |
table.insert(blocks, result) | |
end | |
self:maybeTransformInto(blocks) | |
end | |
function Brick:maybeTransformInto(blocks) | |
if self:canTransformInto(blocks) then | |
self:breakMe() | |
self.blocks = blocks | |
self:place() | |
end | |
end | |
function Brick:canTransformInto(blocks) | |
for k,blockPos in pairs(blocks) do | |
blockPos = self.pos + blockPos | |
if not self:contains(blockPos) then | |
spell.pos = blockPos | |
if spell.block.name ~= 'air' then | |
return false | |
end | |
end | |
end | |
return true | |
end | |
-- Logs the given message into the chat | |
function log( message, ...) | |
local n = select('#', ...) | |
if n>0 then | |
message = string.format(message, ...) | |
end | |
spell:execute([[ /say %s ]], message) | |
end | |
return tetris | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment