Skip to content

Instantly share code, notes, and snippets.

@Adrodoc
Last active October 19, 2021 07:39
Show Gist options
  • Save Adrodoc/9a9f6005d252846ce7bd91dcef363c07 to your computer and use it in GitHub Desktop.
Save Adrodoc/9a9f6005d252846ce7bd91dcef363c07 to your computer and use it in GitHub Desktop.
tetris.lua
require 'mickkay.wol.Spell'
tetris = {}
tetris.delay = 10
tetris.origin = Vec3(453985, 80, -888253)
tetris.width = 10
tetris.height = 20
tetris.rotationCenter = Vec3(0,-1,0)
local upperCenter = tetris.origin + Vec3(tetris.width//2 + 1, tetris.height-1, 0)
function tetris:setup()
spell.pos = self.origin
spell:execute('fill ~ ~ ~ ~%s ~%s ~ sandstone', self.width + 1, self.height + 1)
spell:execute('fill ~1 ~1 ~ ~%s ~%s ~ air', self.width, self.height)
end
function tetris:start()
spell:singleton('tetris')
self:setup()
self.brick = nil
self.queue = Events.connect(
'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(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 + 1, self.width, self.height, y)
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)
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
return tetris
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment