Skip to content

Instantly share code, notes, and snippets.

@mkarneim
Last active June 10, 2018 14:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkarneim/a86a1e7a6c02fbd850d2ef4d4b618fb3 to your computer and use it in GitHub Desktop.
Save mkarneim/a86a1e7a6c02fbd850d2ef4d4b618fb3 to your computer and use it in GitHub Desktop.
Tetris Clone for Wizards of Lua, originally created by Adrodoc55
--[[
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