minewswep

Run Settings
LanguageLua
Language Version
Run Command
-- ceat_ceat -- missing textures and colors LOL -- original https://pastebin.com/KAjDQugX -- whitelist feature + some code cleanup by datz warn("mineswep by ceat yay") if game:GetService("RunService"):IsStudio() then require(game.ServerStorage.lsbenv)() owner,printf,warnf,LoadLibrary,LoadAssets,NLS=owner,printf,warnf,LoadLibrary,LoadAssets,NLS end local Players = game:GetService("Players") local TweenService = game:GetService("TweenService") local Debris = game:GetService("Debris") local DEFAULT_TILE_WIDTH = 1.5 local FIELD_RADIUS = 1 local RESTART_TIME = 3 local UNOPENED_TEX = "rbxassetid://15144071117" local OPENED_TEX = "rbxassetid://13348346487" local MINE_TEX = "rbxassetid://13348250535" local FLAG_TEX = "rbxassetid://10720664742" local BLANK_TEX = "rbxassetid://12381187927" local NUMBER_FONT = Enum.Font.SourceSansBold local WIN_MINE_COLOR = Color3.new(0.5, 1, 0.5) local DIG_SOUND = "rbxassetid://3498493622" local FLAG_SOUND = "rbxassetid://8388724806" local CORRECT_SOUND = "rbxassetid://3422389728" local YAY_SOUND = "rbxassetid://9068897474" local ALARM_SOUND = "rbxassetid://2778386920" local EXPLODE_SOUND = "rbxassetid://165969964" local COLORS = { Color3.fromRGB(0, 0, 255), Color3.fromRGB(39, 107, 31), Color3.fromRGB(255, 0, 0), Color3.fromRGB(0, 0, 130), Color3.fromRGB(157, 0, 0), Color3.fromRGB(0, 214, 146), Color3.fromRGB(98, 0, 168), Color3.fromRGB(100, 100, 100), } local FLASH_TWEENINFO = TweenInfo.new(0.3, Enum.EasingStyle.Quad, Enum.EasingDirection.In) local WIN_FLASH_TWEENINFO = TweenInfo.new(0.75, Enum.EasingStyle.Linear, Enum.EasingDirection.In) local whitelist = false local whitelisted = {} local settings = { tileWidth = DEFAULT_TILE_WIDTH, use3DFlags = false, width = 25, height = 25, mineCount = 90, debug = false } local currentGame local baseTilePart do baseTilePart = Instance.new("Part") baseTilePart.Anchored = true local tileDecal = Instance.new("Decal") tileDecal.Name = "TileTexture" tileDecal.Texture = UNOPENED_TEX tileDecal.Face = Enum.NormalId.Top tileDecal.Parent = baseTilePart local clickDetector = Instance.new("ClickDetector") clickDetector.Name = "ClickDetector" clickDetector.MaxActivationDistance = 30 clickDetector.Parent = baseTilePart end local function createTilePart(cf, tileWidth) local part = baseTilePart:Clone() part.CFrame = cf part.Size = Vector3.new(tileWidth, 0.5, tileWidth) return part end local baseFlagDecal do baseFlagDecal = Instance.new("Decal") baseFlagDecal.Name = "FlagDecal" baseFlagDecal.Texture = FLAG_TEX baseFlagDecal.Face = Enum.NormalId.Top baseFlagDecal.ZIndex = 5 end local function createFlagDecal(part) local decal = baseFlagDecal:Clone() decal.Parent = part return decal end local baseNumberSurface, baseTileFlashDecal do baseNumberSurface = Instance.new("SurfaceGui") baseNumberSurface.Name = "NumberFace" baseNumberSurface.Face = Enum.NormalId.Top baseNumberSurface.SizingMode = Enum.SurfaceGuiSizingMode.PixelsPerStud baseNumberSurface.PixelsPerStud = 25 local label = Instance.new("TextLabel") label.Name = "NumberLabel" label.Font = NUMBER_FONT label.TextScaled = true label.BackgroundTransparency = 1 label.AnchorPoint = Vector2.new(0.5, 0.5) label.Position = UDim2.fromScale(0.5, 0.5) label.Size = UDim2.fromScale(2, 2) label.TextTransparency = 1 label.Rotation = -90 label.Parent = baseNumberSurface baseTileFlashDecal = Instance.new("Decal") baseTileFlashDecal.Texture = BLANK_TEX baseTileFlashDecal.Face = Enum.NormalId.Top baseTileFlashDecal.ZIndex = 5 baseTileFlashDecal.Transparency = 0 baseTileFlashDecal.Parent = baseNumberSurface end local function displayNumber(tile) local surfaceGui = baseNumberSurface:Clone() local label = surfaceGui.NumberLabel local flashDecal = baseTileFlashDecal:Clone() label.Text = tostring(tile.minesAround) label.TextColor3 = COLORS[tile.minesAround] flashDecal.Parent = tile.part label.Parent = surfaceGui surfaceGui.Parent = tile.part TweenService:Create(flashDecal, FLASH_TWEENINFO, { Transparency = 1 }):Play() TweenService:Create(label, TweenInfo.new(0.2), { TextTransparency = 0 }):Play() TweenService:Create(label, TweenInfo.new(0.2 + math.random()*0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.In), { Size = UDim2.fromScale(1, 1) }):Play() Debris:AddItem(flashDecal, FLASH_TWEENINFO.Time) end local function iterTiles(tiles) local width = #tiles local height = #tiles[1] local x = 1 local y = 1 return function() if x > width then x = 1 y += 1 if y > height then return end end local x1 = x x += 1 return x1, y, tiles[x1][y] end end local function disableTile(tile) tile.enabled = false tile.leftClickConnection:Disconnect() tile.rightClickConnection:Disconnect() tile.leftClickConnection = nil tile.rightClickConnection = nil tile.clickDetector:Destroy() end local function unflagTile(tile) if tile.flagInstance then tile.flagInstance:Destroy() tile.flagInstance = nil end end local function getTilesToFlash(tiles, x, y, offset) local flashyGuys = {} -- top left -> top right for xOff = -offset, offset do local tile = tiles[x - xOff] and tiles[x - xOff][y - offset] if tile then table.insert(flashyGuys, tile) end end -- bottom left -> bottom right for xOff = -offset, offset do local tile = tiles[x + xOff] and tiles[x + xOff][y + offset] if tile and not table.find(flashyGuys, tile) then table.insert(flashyGuys, tile) end end -- top left -> bottom left if tiles[x - offset] then for yOff = -offset, offset do local tile = tiles[x - offset][y + yOff] if tile and not table.find(flashyGuys, tile) then table.insert(flashyGuys, tile) end end end -- top right -> bottom right if tiles[x + offset] then for yOff = -offset, offset do local tile = tiles[x + offset][y + yOff] if tile and not table.find(flashyGuys, tile) then table.insert(flashyGuys, tile) end end end return flashyGuys end local function flashTilesWave(tiles, tile, width, height, winner, color) local baseX = tile.x local baseY = tile.y for i = 0, math.max(width, height) do for _, tile in getTilesToFlash(tiles, baseX, baseY, i) do if tile.isFlagged then tile.isFlagged = false unflagTile(tile) end if winner then tile.tileTexture.Texture = OPENED_TEX else if tile.isMine then tile.tileTexture.Texture = MINE_TEX end end tile.tileTexture.Color3 = color if not tile.isMine then TweenService:Create(tile.tileTexture, WIN_FLASH_TWEENINFO, { Color3 = Color3.new(1, 1, 1) }):Play() end end task.wait() end end local function playSound(part, soundId, pitch) local sound = Instance.new("Sound") sound.SoundId = soundId sound.Pitch = pitch sound.Parent = part sound:Play() Debris:AddItem(sound, 4) return sound end local function isWhitelisted(plr) if whitelist and not whitelisted[plr.UserId] and plr ~= owner then return false end return true end -- debug visuals local function highlightTile(tile, color) local part = Instance.new("Part") part.Anchored = true part.CanCollide = false part.CanTouch = false part.CanQuery = false part.Material = Enum.Material.Neon part.Color = color part.Size = Vector3.new(settings.tileWidth, 0.7, settings.tileWidth) part.Transparency = 0.8 part.CFrame = tile.part.CFrame return part end local function showNeighbors(tiles, tile) local main = highlightTile(tile, Color3.new(1, 0, 0)) main.Parent = script local neighborParts = {} for _, position in tile.neighbors do local part = highlightTile(tiles[position.x][position.y], Color3.new(0, 0, 1)) part.Parent = script table.insert(neighborParts, part) end task.wait() main:Destroy() for _, part in neighborParts do part:Destroy() end end -- game wow local restartTask local function restart(spawnCF, width, height, numMines) restartTask = task.delay(RESTART_TIME, function() restartTask = nil stopGame(currentGame) currentGame = createGame(spawnCF, width, height, numMines) end) end function createGame(spawnCF, width, height, numMines) local gameObject = {} local gameSettings = table.clone(settings) gameObject.settings = gameSettings local model = Instance.new("Model") model.Name = "Minesweeper" gameObject.model = model local tiles = {} gameObject.tiles = tiles local active = true local didFirstClick = false local function layMines(clickedTile) local validPositions = {} -- filter out start field for x, y, tile in iterTiles(tiles) do if math.abs(x - clickedTile.x) <= FIELD_RADIUS and math.abs(y - clickedTile.y) <= FIELD_RADIUS then continue end table.insert(validPositions, { x = x, y = y }) end for i = 1, math.min(numMines, #validPositions) do local pos = table.remove(validPositions, math.random(#validPositions)) local tile = tiles[pos.x][pos.y] tile.isMine = true if gameSettings.debug then tile.tileTexture.Color3 = Color3.new(1, 0.5, 0.5) end end -- count mines around tiles for x, y, tile in iterTiles(tiles) do for _, position in tile.neighbors do if tiles[position.x][position.y].isMine then tile.minesAround += 1 end end if gameSettings.debug then showNeighbors(tiles, tile) end end end local function onLose(plr, tile) active = false for x, y, tile in iterTiles(tiles) do if tile.enabled then disableTile(tile) end if tile.isMine then tile.tileTexture.Texture = MINE_TEX end end tile.part.CFrame *= CFrame.new(0, 1, 0) tile.part.Anchored = false tile.part.Velocity = Vector3.new(-3 + math.random()*6, math.random(20, 30), -3 + math.random()*6) tile.part.RotVelocity = Vector3.new(math.random(-10, 10), math.random(-10, 10), math.random(-10, 10)) playSound(tile.part, ALARM_SOUND, 1).TimePosition = 0.35 playSound(tile.part, EXPLODE_SOUND, 1) local explod = Instance.new("Explosion") explod.BlastPressure = 0 explod.BlastRadius = 0 explod.Position = tile.part.Position explod.Parent = workspace flashTilesWave(tiles, tile, width, height, false, Color3.new(1, 0.5, 0.5)) restart(spawnCF, width, height, numMines) warn(`{plr} lost the game`) end local function onWin(tile) for x, y, tile in iterTiles(tiles) do if tile.enabled then disableTile(tile) end end playSound(tile.part, CORRECT_SOUND, 1) playSound(tile.part, YAY_SOUND, 1) flashTilesWave(tiles, tile, width, height, true, WIN_MINE_COLOR) restart(spawnCF, width, height, numMines) end local mineTile -- scream local function chordTile(plr, tile) local unflaggedTiles = {} local numFlagged = 0 for _, position in tile.neighbors do local otherTile = tiles[position.x][position.y] if otherTile.opened then continue end if otherTile.isFlagged then numFlagged += 1 else table.insert(unflaggedTiles, otherTile) end end if numFlagged == tile.minesAround then for _, otherTile in unflaggedTiles do mineTile(plr, otherTile) end end end function mineTile(plr, tile) if not active then return end if tile.isMine then onLose(plr, tile) return end if tile.opened then chordTile(plr, tile) return end if tile.isFlagged then tile.isFlagged = false unflagTile(tile) end tile.opened = true tile.tileTexture.Texture = OPENED_TEX if tile.minesAround == 0 then disableTile(tile) for _, position in tile.neighbors do local otherTile = tiles[position.x][position.y] if otherTile.opened then continue end mineTile(plr, otherTile) end else displayNumber(tile) end end local function checkWin() local numNonMines = 0 local numOpened = 0 for x, y, tile in iterTiles(tiles) do if not tile.isMine then numNonMines += 1 end if tile.opened then numOpened += 1 end end return numNonMines == numOpened end local function onLeftClick(tile) return function(plr) if not isWhitelisted(plr) then return end if tile.isFlagged then return end if not didFirstClick then didFirstClick = true layMines(tile) end playSound(tile.part, DIG_SOUND, 0.9 + math.random()*0.2) mineTile(plr, tile) if checkWin() then onWin(tile) end end end local function onRightClick(tile) return function(plr) if not isWhitelisted(plr) then return end if tile.opened then return end tile.isFlagged = not tile.isFlagged playSound(tile.part, FLAG_SOUND, 0.8 + math.random()*0.4) if tile.isFlagged then if gameSettings.use3DFlags then -- not implemented else tile.flagInstance = createFlagDecal(tile.part) end else unflagTile(tile) end end end local originCF = spawnCF * CFrame.new(-width/2*gameSettings.tileWidth, 0, -height/2*gameSettings.tileWidth) for x = 1, width do local row = {} for y = 1, height do local tileCF = originCF * CFrame.new(x*gameSettings.tileWidth, 0, y*gameSettings.tileWidth) local part = createTilePart(tileCF, gameSettings.tileWidth) --part.CanCollide = false --part.Transparency = 1 local self = { x = x, y = y, enabled = true, opened = false, isMine = false, isFlagged = false, neighbors = {}, -- {x = num, y = num} minesAround = 0, -- decided by layMines part = part, tileTexture = part.TileTexture, clickDetector = part.ClickDetector, flagInstance = nil, -- decal or instance leftClickConnection = nil, rightClickConnection = nil, } self.leftClickConnection = self.clickDetector.MouseClick:Connect(onLeftClick(self)) self.rightClickConnection = self.clickDetector.RightMouseClick:Connect(onRightClick(self)) for xOffset = -1, 1 do for yOffset = -1, 1 do if xOffset == 0 and yOffset == 0 then continue end local x2 = x + xOffset local y2 = y + yOffset if x2 < 1 or x2 > width then continue end if y2 < 1 or y2 > height then continue end table.insert(self.neighbors, { x = x2, y = y2 }) end end part.Parent = model --local delayTime = (y - 1)*(width)*0.00005 + x*0.00005 --TweenService:Create(part, TweenInfo.new(0.15 + math.random()*0.15, Enum.EasingStyle.Quad, Enum.EasingDirection.In), { -- Transparency = 0, -- CFrame = tileCF, -- CanCollide = true --}):Play() row[y] = self end tiles[x] = row end model.Parent = script return gameObject end function stopGame(gameObject) for x, y, tile in iterTiles(gameObject.tiles) do if tile.enabled then disableTile(tile) end end gameObject.model:Destroy() end -- currentGame = createGame(CFrame.new(0, 5, 0), settings.width, settings.height, settings.mineCount) local function getRootPos() local humanoid = owner.Character and owner.Character:FindFirstChildOfClass("Humanoid") if humanoid and humanoid.RootPart then return humanoid.RootPart.CFrame.Position end end local function findPlayer(target) target = target:lower() for _, plr in Players:GetPlayers() do if plr.Name:lower():sub(1, #target) == target then return plr end end end owner.Chatted:Connect(function(msg) local cmdString = msg:match("ms/(.+)") if not cmdString then return end local args = cmdString:split("/") local cmdName = table.remove(args, 1) if cmdName == "size" then if args[2] then settings.width = tonumber(args[1]) settings.height = tonumber(args[2]) printf(`set size to <b>{settings.width}x{settings.height}</b>`) else local size = tonumber(args[1]) if not size then return printf("<i>pls provide size</i>") end settings.width = size settings.height = size printf(`set size to <b>{size}x{size}</b>`) end elseif cmdName == "mines" then local mineCount = tonumber(args[1]) if not mineCount then return printf("<i>pls provide minecount</i>") end settings.mineCount = mineCount printf(`set mine count to <b>{settings.mineCount}</b>`) elseif cmdName == "minefreq" then local freq = tonumber(args[1]) if not freq then return printf("<i>pls provide freq</i>") end settings.mineCount = math.floor(settings.width*settings.height*freq) printf(`set mine count to <b>{settings.mineCount}</b>`) elseif cmdName == "game" then local rootPos = getRootPos() if not rootPos then return printf("<i>could not find rootpos</i>") end if currentGame then stopGame(currentGame) end currentGame = createGame(CFrame.new(rootPos + Vector3.new(0, -1.75, 0)), settings.width, settings.height, settings.mineCount) printf("<i>started game</i>") elseif cmdName == "stop" then if restartTask then task.cancel(restartTask) restartTask = nil end if currentGame then stopGame(currentGame) else printf("<i>no game active</i>") end elseif cmdName == "debug" then settings.debug = not settings.debug printf(`<i>debug {settings.debug and "enabled" or "disabled"}</i>`) elseif cmdName == "whitelist" then whitelist = not whitelist printf(`<i>whitelist {whitelist and "enabled" or "disabled"}</i>`) elseif cmdName == "allow" then local username = tostring(args[1]) if not username then return printf("<i>pls provide username</i>") end local plr = findPlayer(username) if not plr then return printf("<i>player not found</i>") end if whitelisted[plr.UserId] then return printf("<i>player is already whitelisted</i>") end whitelisted[plr.UserId] = true printf(`added <b>{plr}</b> to whitelist`) elseif cmdName == "unallow" then local username = tostring(args[1]) if not username then return printf("<i>pls provide username</i>") end local plr = findPlayer(username) if not plr then return printf("<i>player not found</i>") end if not whitelisted[plr.UserId] then return printf("<i>player is not whitelisted</i>") end whitelisted[plr.UserId] = nil printf(`removed <b>{plr}</b> from whitelist`) elseif cmdName == "cmds" then printf([[ <b>ms/size/[width]/[height]</b> set board size to (width, height) <b>ms/size/[sideLength]</b> set board size to (sideLength, sideLength) <b>ms/mines/[mineCount]</b> set mine count to mineCount <b>ms/minefreq/[mineFrequency]</b> set mine count to width*height*mineFrequency <b>ms/game</b> start game <b>ms/stop</b> end game <b>ms/whitelist</b> toggle the whitelist <b>ms/allow/[name]</b> add a player to the whitelist <b>ms/unallow/[name]</b> remove a player from the whitelist <b>ms/cmds</b> this thing]]) else printf("<i>invalid ms/ command</i>") end end) print("ms/cmds for list of commands (works with /e)")
Editor Settings
Theme
Key bindings
Full width
Lines