Mining Game System with a Pickaxe

Right now I’m trying to make a simple mining game so me and my friends can play and mess around in it. Currently I’ve done a decent amount of work, I’ve gotten generation and a mining (bad) system, plus the actual like leaderstat for blocks mined.

Now I’ve realized that having clickdetectors and scripts in EVERY SINGLE BLOCK is not the best or greatest idea, so I’m trying to rebrand it if you get what I mean.

My friend said to use an advanced loop in ServerScriptService, so all I have right now is just:

for _,v in workspace.Cubes:GetChildren() and workspace.Cubes.Generated:GetChildren() do
	--function
end

I’ve looked all around the DevForum and while I got my mining system and all that from here, I can’t find anything for the pickaxe system and now I’m here to ask what I would do to make it like that. There is a Youtube tutorial that I tried but it lowkey sucked and I tried to see if I could make anything with a little research and I ended up entirely breaking my game soooooo.

If you want to know what I mean and what I’m trying to make play REx: Reincarnated that’s the only reason I’m making this so then I can get some of my friends and myself off of it for like a day at least (I’m playing it as I’m writing and making the game).

Uhh here’s this other script that’s important except it’s been like a month since I’ve touched this game and I don’t know what is meant to be what half this stuff might be redundant I don’t know.

local loottable = require(game.ServerStorage:WaitForChild("LootTable"))

local bCounter = 0
local oCounter = 0
local gCounter = 0
local tCounter = 0
local pCounter = 0
local sCounter = 0

local bValue = game.Workspace.bananaCounter
local oValue = game.Workspace.orangeCounter
local gValue = game.Workspace.grassCounter
local tValue = game.Workspace.tappleCounter
local pValue = game.Workspace.particleCounter
local sValue = game.Workspace.stenchCounter

local players = game:GetService("Players")
local updateText = game.ReplicatedStorage.updateText

local Ores2 = {
	["grass"] = game.ServerStorage.Ores.grass,
	["banana"] = game.ServerStorage.Ores.banana,
	["orange"] = game.ServerStorage.Ores.orange,
	["transparent apple"] = game.ServerStorage.Ores.transparent_apple,
	["particle"] = game.ServerStorage.Ores.particle,
	["green stench"] = game.ServerStorage.Ores["green stench"],
	["dynamo of bass"] = game.ServerStorage.Ores["Dynamo of grass no reference"]
}

local positions = {
	Vector3.new(6,0,0);
	Vector3.new(-6,0,0);
	Vector3.new(0,6,0);
	Vector3.new(0,-6,0);
	Vector3.new(0,0,6);
	Vector3.new(0,0,-6);
}

function Generate(pos)
	if pos then
		for _,pos2 in pairs(positions) do
			local newPos = pos+pos2
			local previouslyGenerated
			for _,generated in pairs(workspace.Cubes.Generated:GetChildren()) do
				if generated.Value == newPos then
					previouslyGenerated = true
				end
			end
			if newPos.Y > 0 then
				previouslyGenerated = true
			end
			if not previouslyGenerated then
				function GetRandomOre()
					local Sum=0
					for OreName,Chance in pairs(loottable) do
						Sum += Chance
					end
					local RandomNumber = math.random(Sum)
					for OreName,Chance in pairs(loottable) do
						if RandomNumber <= Chance then
							return OreName
						else
							RandomNumber -= Chance
						end
						end
					end
				local ore = Ores2[GetRandomOre()]:Clone()
				local oregenerated = ore
				--print(ore)
				--local ore = Ores[math.random(1, 2)]:Clone
				ore.Position = newPos
				ore.Parent = workspace.Cubes
				ore.ClickDetector.MouseClick:Connect(function()
					if ore.Name == "banana" then
						--print("BANANA")
						bCounter += 1
						bValue.Value = bCounter
						--print(bCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.bananaCounter.Text = bValue.Value
					end
					if ore.Name == "orange" then
						--print("ORANGE")
						oCounter += 1
						oValue.Value = oCounter
						--print(oCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.orangeCounter.Text = oCounter
					end
					if ore.Name == "grass" then
						--print("GRASS")
						gCounter += 1
						gValue.Value = gCounter
						--print(gCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.grassCounter.Text = gCounter
					end
					if ore.Name == "transparent_apple" then
						--print("TRANSPARENT APPLE")
						tCounter += 1
						tValue.Value = tCounter
						--print(tCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.tappleCounter.Text = tCounter
					end
					if ore.Name == "particle" then
						--print("PARTICLE")
						pCounter += 1
						pValue.Value = pCounter
						--print(pCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.particleCounter.Text = pCounter
					end
					if ore.Name == "green stench" then
						--print("PARTICLE")
						sCounter += 1
						sValue.Value = sCounter
						--print(pCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.stenchCounter.Text = sCounter
					end
					Generate(ore.Position)
					ore:Destroy()
				end)
				local val = Instance.new("Vector3Value")
				val.Value = newPos
				val.Parent = workspace.Cubes.Generated
			end
		end
	end
end

for i,cube in pairs(workspace.Cubes:GetChildren()) do
	if cube:IsA("Part") then
		local val = Instance.new("Vector3Value")
		val.Value = cube.Position
		val.Parent = workspace.Cubes.Generated
		cube.ClickDetector.MouseClick:Connect(function()
			--game.Players.LocalPlayer.leaderstats["Blocks Mined"].Value += 1
			if cube.Name == "Part" then
				--print("BANANA")
				bCounter += 1
				bValue.Value = bCounter
				--print(bCounter)
				--updateText:FireClient(players)
				game.StarterGui.ScreenGui.Frame.bananaCounter.Text = bCounter
			end
			--blocking.Value += 1
			--players.PlayerAdded:Connect(function(player)
			--	local blockMined = player.leaderstats["Blocks Mined"]
			--	blockMined.Value += 1
			--end)
			Generate(cube.Position)
			cube:Destroy()
		end)
	end
end

Thank you to any goats who help me out you’ll get your own ore :heart::heart: it won’t be exceptional though just saying

for _,v in workspace.Cubes:GetChildren() and workspace.Cubes.Generated:GetChildren() do
	--function
end

So if I’m understanding correctly, you want a way to detect when any part in the children group is clicked?

Yes, while the player has the pickaxe tool equipped.

On the server, do something like this

for _,v in workspace.Cubes:GetChildren() and workspace.Cubes.Generated:GetChildren() do
	v:AddTag("Block")	
end

I never knew I could do and when looping through stuff. That’s nice.


On the client, do this

local Player = game:GetService("Players").LocalPlayer
local Mouse = Player:GetMouse()


Mouse.Button1Down:Connect(function()
if not player.char find pickaxe then return end

	local Target = Mouse.Target
	
	if Target and Target:HasTag("Block") then
		-- do the stuff here how you mine blocks, if you're firing a remoteEvent do the same tag checks on the server
	end
end)

This system is similar to how my mining system works.

Where would I put that other code, would I put it in the same script or like StarterPlayer/CharacterScripts (im really bad when it comes to where stuff should be :sob::sob:)

I forgot to mention that.

Server in ServScritService
Client script goes into StarterPlayerScripts.

image
How would I fix this

Use your own method when finding pickaxe. Use Player.Character:FindFirstChild("Pickaxe")

If PickaxeFound then
     Return
end

Okay so the script isn’t doing anything for some reason, there isn’t any errors either and I’m kinda confused now. If I remember correctly the current mining method I have is in that larger script I sent, the whole Generate function which didn’t work at first and took me 2 hours to fix :sob:idk if looking at that could help but yeah

did you add your methods to ths line?

image

Yeah I put

	if Target and Target:HasTag("Block") then
		-- do the stuff here how you mine blocks, if you're firing a remoteEvent do the same tag checks on the server
		local blockMined = Player.leaderstats["Blocks Mined"]
		blockMined.Value += 1
		Target:Destroy()
	end
end)

I think the bug could be that Target:Destroy() is wrong, it’s the first thing I did since it made the most logical sense but I could be wrong about that

This only has the effect on the client by the way. I recommend learning about FE before making systems like this.

Also. Send your generation script, I could be able to analyze why this isn’t doing anything at all.

local loottable = require(game.ServerStorage:WaitForChild("LootTable"))

local bCounter = 0
local oCounter = 0
local gCounter = 0
local tCounter = 0
local pCounter = 0
local sCounter = 0

local bValue = game.Workspace.bananaCounter
local oValue = game.Workspace.orangeCounter
local gValue = game.Workspace.grassCounter
local tValue = game.Workspace.tappleCounter
local pValue = game.Workspace.particleCounter
local sValue = game.Workspace.stenchCounter

local players = game:GetService("Players")
local updateText = game.ReplicatedStorage.updateText

local Ores2 = {
	["grass"] = game.ServerStorage.Ores.grass,
	["banana"] = game.ServerStorage.Ores.banana,
	["orange"] = game.ServerStorage.Ores.orange,
	["transparent apple"] = game.ServerStorage.Ores.transparent_apple,
	["particle"] = game.ServerStorage.Ores.particle,
	["green stench"] = game.ServerStorage.Ores["green stench"],
	["dynamo of bass"] = game.ServerStorage.Ores["Dynamo of grass no reference"]
}

local positions = {
	Vector3.new(6,0,0);
	Vector3.new(-6,0,0);
	Vector3.new(0,6,0);
	Vector3.new(0,-6,0);
	Vector3.new(0,0,6);
	Vector3.new(0,0,-6);
}

function Generate(pos)
	if pos then
		for _,pos2 in pairs(positions) do
			local newPos = pos+pos2
			local previouslyGenerated
			for _,generated in pairs(workspace.Cubes.Generated:GetChildren()) do
				if generated.Value == newPos then
					previouslyGenerated = true
				end
			end
			if newPos.Y > 0 then
				previouslyGenerated = true
			end
			if not previouslyGenerated then
				function GetRandomOre()
					local Sum=0
					for OreName,Chance in pairs(loottable) do
						Sum += Chance
					end
					local RandomNumber = math.random(Sum)
					for OreName,Chance in pairs(loottable) do
						if RandomNumber <= Chance then
							return OreName
						else
							RandomNumber -= Chance
						end
						end
					end
				local ore = Ores2[GetRandomOre()]:Clone()
				local oregenerated = ore
				--print(ore)
				--local ore = Ores[math.random(1, 2)]:Clone
				ore.Position = newPos
				ore.Parent = workspace.Cubes
				ore.ClickDetector.MouseClick:Connect(function()
					if ore.Name == "banana" then
						--print("BANANA")
						bCounter += 1
						bValue.Value = bCounter
						--print(bCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.bananaCounter.Text = bValue.Value
					end
					if ore.Name == "orange" then
						--print("ORANGE")
						oCounter += 1
						oValue.Value = oCounter
						--print(oCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.orangeCounter.Text = oCounter
					end
					if ore.Name == "grass" then
						--print("GRASS")
						gCounter += 1
						gValue.Value = gCounter
						--print(gCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.grassCounter.Text = gCounter
					end
					if ore.Name == "transparent_apple" then
						--print("TRANSPARENT APPLE")
						tCounter += 1
						tValue.Value = tCounter
						--print(tCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.tappleCounter.Text = tCounter
					end
					if ore.Name == "particle" then
						--print("PARTICLE")
						pCounter += 1
						pValue.Value = pCounter
						--print(pCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.particleCounter.Text = pCounter
					end
					if ore.Name == "green stench" then
						--print("PARTICLE")
						sCounter += 1
						sValue.Value = sCounter
						--print(pCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.stenchCounter.Text = sCounter
					end
					Generate(ore.Position)
					ore:Destroy()
				end)
				local val = Instance.new("Vector3Value")
				val.Value = newPos
				val.Parent = workspace.Cubes.Generated
			end
		end
	end
end

for i,cube in pairs(workspace.Cubes:GetChildren()) do
	if cube:IsA("Part") then
		local val = Instance.new("Vector3Value")
		val.Value = cube.Position
		val.Parent = workspace.Cubes.Generated
		cube.ClickDetector.MouseClick:Connect(function()
			--game.Players.LocalPlayer.leaderstats["Blocks Mined"].Value += 1
			if cube.Name == "Part" then
				--print("BANANA")
				bCounter += 1
				bValue.Value = bCounter
				--print(bCounter)
				--updateText:FireClient(players)
				game.StarterGui.ScreenGui.Frame.bananaCounter.Text = bCounter
			end
			--blocking.Value += 1
			--players.PlayerAdded:Connect(function(player)
			--	local blockMined = player.leaderstats["Blocks Mined"]
			--	blockMined.Value += 1
			--end)
			Generate(cube.Position)
			cube:Destroy()
		end)
	end
end
return {
	["grass"] = 200,
	["banana"] = 8788.63898917,
	["orange"] = 1000,
	["transparent apple"] = 10,
	["particle"] = 1,
	["green stench"] = 0.36101083
}

First script is generation script, second is the loot table. Also ignore any of that like bCounter stuff, that’s just my attempts at an inventory system from a while ago :sob::sob:

local Player = game:GetService("Players").LocalPlayer
local Mouse = Player:GetMouse()


Mouse.Button1Down:Connect(function()
	local Target = Mouse.Target
	
	if Target and Target:HasTag("Block") then
		-- do the stuff here how you mine blocks, if you're firing a remoteEvent do the same tag checks on the server
	end
end)

----//SEP

local loottable = require(game.ServerStorage:WaitForChild("LootTable"))

local bCounter = 0
local oCounter = 0
local gCounter = 0
local tCounter = 0
local pCounter = 0
local sCounter = 0

local bValue = game.Workspace.bananaCounter
local oValue = game.Workspace.orangeCounter
local gValue = game.Workspace.grassCounter
local tValue = game.Workspace.tappleCounter
local pValue = game.Workspace.particleCounter
local sValue = game.Workspace.stenchCounter

local players = game:GetService("Players")
local updateText = game.ReplicatedStorage.updateText

local Ores2 = {
	["grass"] = game.ServerStorage.Ores.grass,
	["banana"] = game.ServerStorage.Ores.banana,
	["orange"] = game.ServerStorage.Ores.orange,
	["transparent apple"] = game.ServerStorage.Ores.transparent_apple,
	["particle"] = game.ServerStorage.Ores.particle,
	["green stench"] = game.ServerStorage.Ores["green stench"],
	["dynamo of bass"] = game.ServerStorage.Ores["Dynamo of grass no reference"]
}

local positions = {
	Vector3.new(6,0,0);
	Vector3.new(-6,0,0);
	Vector3.new(0,6,0);
	Vector3.new(0,-6,0);
	Vector3.new(0,0,6);
	Vector3.new(0,0,-6);
}

function Generate(pos)
	if pos then
		for _,pos2 in pairs(positions) do
			local newPos = pos+pos2
			local previouslyGenerated
			for _,generated in pairs(workspace.Cubes.Generated:GetChildren()) do
				if generated.Value == newPos then
					previouslyGenerated = true
				end
			end
			if newPos.Y > 0 then
				previouslyGenerated = true
			end
			if not previouslyGenerated then
				function GetRandomOre()
					local Sum=0
					for OreName,Chance in pairs(loottable) do
						Sum += Chance
					end
					local RandomNumber = math.random(Sum)
					for OreName,Chance in pairs(loottable) do
						if RandomNumber <= Chance then
							return OreName
						else
							RandomNumber -= Chance
						end
					end
				end
				local ore = Ores2[GetRandomOre()]:Clone()
				local oregenerated = ore
				--print(ore)
				--local ore = Ores[math.random(1, 2)]:Clone
				ore.Position = newPos
				ore.Parent = workspace.Cubes
				ore.ClickDetector.MouseClick:Connect(function()
					if ore.Name == "banana" then
						--print("BANANA")
						bCounter += 1
						bValue.Value = bCounter
						--print(bCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.bananaCounter.Text = bValue.Value
					end
					if ore.Name == "orange" then
						--print("ORANGE")
						oCounter += 1
						oValue.Value = oCounter
						--print(oCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.orangeCounter.Text = oCounter
					end
					if ore.Name == "grass" then
						--print("GRASS")
						gCounter += 1
						gValue.Value = gCounter
						--print(gCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.grassCounter.Text = gCounter
					end
					if ore.Name == "transparent_apple" then
						--print("TRANSPARENT APPLE")
						tCounter += 1
						tValue.Value = tCounter
						--print(tCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.tappleCounter.Text = tCounter
					end
					if ore.Name == "particle" then
						--print("PARTICLE")
						pCounter += 1
						pValue.Value = pCounter
						--print(pCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.particleCounter.Text = pCounter
					end
					if ore.Name == "green stench" then
						--print("PARTICLE")
						sCounter += 1
						sValue.Value = sCounter
						--print(pCounter)
						--updateText:FireClient(players)
						game.StarterGui.ScreenGui.Frame.stenchCounter.Text = sCounter
					end
					Generate(ore.Position)
					ore:Destroy()
				end)
				local val = Instance.new("Vector3Value")
				val.Value = newPos
				val.Parent = workspace.Cubes.Generated
			end
		end
	end
end

for index,cube in workspace.Cubes:GetChildren() do
	if cube:IsA("Part") then
		cube:AddTag("Block")
		local val = Instance.new("Vector3Value")
		val.Value = cube.Position
		val.Parent = workspace.Cubes.Generated
		cube.ClickDetector.MouseClick:Connect(function()
			--game.Players.LocalPlayer.leaderstats["Blocks Mined"].Value += 1
			if cube.Name == "Part" then
				--print("BANANA")
				bCounter += 1
				bValue.Value = bCounter
				--print(bCounter)
				--updateText:FireClient(players)
				game.StarterGui.ScreenGui.Frame.bananaCounter.Text = bCounter
			end
			--blocking.Value += 1
			--players.PlayerAdded:Connect(function(player)
			--	local blockMined = player.leaderstats["Blocks Mined"]
			--	blockMined.Value += 1
			--end)
			Generate(cube.Position)
			cube:Destroy()
		end)
	end
end

Here. I made it add the tags correct way. Try testing again.

The client script, aka localscript, aka script with the context set to “client,” is this one

local Player = game:GetService("Players").LocalPlayer
local Mouse = Player:GetMouse()


Mouse.Button1Down:Connect(function()
if not player.char find pickaxe then return end

	local Target = Mouse.Target
	
	if Target and Target:HasTag("Block") then
		-- do the stuff here how you mine blocks, if you're firing a remoteEvent do the same tag checks on the server
	end
end)

In your case it’s a serverScript. Must be client.

It just isn’t working for some reason. No errors, none of those warning things, just ain’t working.

Well that is odd. I can’t help anymore but if this still isn’t solved later I might be able to help.

Alright, still thanks for your help though greatly appreciate it :pray::pray:I’m gonna try and make the inventory system work

1 Like

Use raycast to get the instance