Needing help fixing a problem

I’m trying to achieve an ore mining thing, like azure mines. The way I’m trying to get it is to basically, make it do this if you go down. It creates an ore at the left, right, front, back and bottom. If there is no ore above it’d make one at the top, I don’t know how to do this. I only made an attempt. Contact me on discord, #petrkc#4168 to talk more. I got screenshots there.

Had this problem for days now, nobody even helped at all. If anyone is willing to help, contact me on discord like I said above. I’m tired of making projects to go to waste. If you do want to help, payment is not possible as I do not have a credit card nor robux. Readers, please understand and be nice to help.

local rep = game:GetService("ReplicatedStorage")
local ore_Generation = rep:WaitForChild("GenerateOre")
local ores = game.ReplicatedStorage.Ores
local orelist = {"Dirt","Iron","Ore"}
local function getchoice()
	local choice = math.random(1,100)
	return choice
end
ore_Generation.OnServerEvent:Connect(function(player,hitpos,surface,hit)
	local choice = getchoice()
	local orechoice = orelist[math.random(1,#orelist)]
	if orechoice ~= ores.Dirt.Name then
		local p = ores[orechoice]:Clone()
		p.Parent = workspace.OreList
		p.Position = Vector3.new(hit.Position.X,hit.Position.Y-6,hit.Position.Z)
		local p2 = ores[orechoice]:Clone()
		p2.Parent = workspace.OreList
		p2.Position = Vector3.new(hit.Position.X,hit.Position.Y,hit.Position.Z-6)
		local p3 = ores[orechoice]:Clone()
		p3.Parent = workspace.OreList
		p3.Position = Vector3.new(hit.Position.X,hit.Position.Y,hit.Position.Z+6)
		local p4 = ores[orechoice]:Clone()
		p4.Parent = workspace.OreList
		p4.Position = Vector3.new(hit.Position.X-6,hit.Position.Y,hit.Position.Z)
		local p5 = ores[orechoice]:Clone()
		p5.Parent = workspace.OreList
		p5.Position = Vector3.new(hit.Position.X+6,hit.Position.Y,hit.Position.Z)
		hit:Destroy()
	else
		local p = ores.Dirt:Clone()
		p.Parent = workspace.OreList
		p.Position = Vector3.new(hit.Position.X,hit.Position.Y-6,hit.Position.Z)
		hit:Destroy()
	end
end)

Problem: https://gyazo.com/88b66369d32b01c1c9cea0b3c8410c8d

I’ve been stuck on this for nearly 1 week. Can someone even help me?!

1 Like

I’d love to assist here, but I am lacking some info as to what exactly the issue is. Are you just stuck and want some put you back on track to continue the project, or is there something that isn’t working as expected? A quick read through the code provided on my part didn’t turn up any obvious errors, assuming all the variables are defined correctly. Knowing what exactly is passed to the RemoteEvent from the client would also help.

1 Like

Like, you see. I can’t get the directions, from left, right, front, back, aswell as the top as I’m only going down, since my lua knowledge is terrible. If you mine a block next to you, it goes inside of you. Basically, can only go down because I don’t know much about mining games, get stuck if you mine a block next to you.

The code provided does indeed assume that the block was mined in a downward direction. In order to proceed with making this script work in all directions, you’ll need to determine exactly which positions need to be filled with a block. How exactly you would go about this is a little more complicated.

Here’s some things you can use to determine this:

  • If another block is already occupying the area, you shouldn’t add a new block.
  • If a player is occupying the area, you shouldn’t place a new block provided a player is never able to exit ‘the cave’. (I wouldn’t rely on this.)
  • If there is no blocks below the position you are trying to place a block in, you should place a block. (‘Open hole towards the void’) (This is also true for all of the other axis)
  • If the face of the block that was mined is known, a block should never be placed on that mined surface provided a player is never able to exit the cave.

One of the issues with the above criterions is the fact that this would get quite inefficient quite quickly. The criterions I have provided above are also non-inclusive. There are plenty of cases where these checks will fail to place blocks properly.

As far as my knowledge extends, I am currently unable to assist you further. I do believe checking for each block seperately is the way to go, as the possible situations don’t limit themselves to cases where you need to add five blocks.

Even though I can’t help, I hope you can get on a little bit further with this.

My first guess is that you will need a three-dimensional dictionary of each and every block within your game:

local Space = {}

Set and get methods for x-y-z:

local function getSpace(pos)
	local xSpace = Space[pos.X]
	if not xSpace then return end

	local ySpace = xSpace[pos.Y]
	if not ySpace then return end

	return ySpace[pos.Z]
end
local function setSpace(pos, value)
	local xSpace = Space[pos.X]
	if not xSpace then
		Space[pos.X] = {
			[pos.Y] = { [pos.Z] = value }
		}
		return
	end

	local ySpace = xSpace[pos.Y]
	if not ySpace then
		xSpace[pos.Y] = { [pos.Z] = value }
		return
	end

	ySpace[pos.Z] = value
end

From there, you can use getSpace to check for already existing blocks and setSpace for new ones. You would also have to create a special value for air too, I would just use a newproxy() symbol.

-- with space code from above

local RNG = Random.new()

local AIR = newproxy()
local BLOCK_SIZE = 6

local NORMAL_DIR = {
	Vector3.new(1, 0, 0),
	Vector3.new(-1, 0, 0),
	Vector3.new(0, 1, 0),
	Vector3.new(0, -1, 0),
	Vector3.new(0, 0, 1),
	Vector3.new(0, 0, -1)
}

local function convert(position)
	return position / BLOCK_SIZE
end
local function _convert(position)
	return position * BLOCK_SIZE
end

local oreFolder = -- a folder in server storage
-- put all your 6x6x6 blocks in the oreFolder
local allOres = oreFolder:GetChildren()
local function getOreChoice()
	return allOres[RNG:NextInteger(1, #allOres)]
end

local function createBlock(blockBase, position)
	position = _convert(position)
	local newBlock = blockBase:Clone()
	newBlock.Position = position
	newBlock.Parent = workspace -- or wherever
	return newBlock
end

-- position is a vector3
ore_Generation.OnServerEvent:Connect(function(player, position)
	position = convert(position)
	local hit = getSpace(position)
	if not hit or hit == AIR then return end
    
	-- create a new ore for each normal direction
	-- if there is no block there
	for _, normal in ipairs(NORMAL_DIR) do
		local newPosition = position + normal
		local occupied = getSpace(newPosition)
		if occupied then continue end

		local oreChoice = getOreChoice()
		local oreBlock = createBlock(oreChoice, newPosition)
		setSpace(newPosition, oreBlock)
	end

	hit:Destroy()
	setSpace(position, AIR)
end)

You would of course want to create a base in Space first that describes what the player sees already:

for x = -25, 25 do
	for z = -25, 25 do
		local newPosition = Vector3.new(x, 0, z)
        
		-- this is so blocks don't get created upwards
		local airPosition = Vector3.new(x, 1, z)

		local block = createBlock(oreFolder.Dirt, newPosition)
		setSpace(newPosition, block)
		setSpace(airPosition, AIR)
	end
end

You might also want to make sure there aren’t any existing blocks in workspace just so it doesn’t become cluttered with unregistered blocks.
And you might also want to define a cube of air or unmineable blocks so that there are boundaries for how far the mine goes in each direction.
That should be just about it for what you’re trying to do. Let me know if you need more help!

Edit: forgot to change arguments to setSpace from x y z to a vector3, it’s fixed now
Edit 2: There should be a continue when looping through NORMAL_DIR and finding an occupied space, not return, my bad.
Edit 3: Also forgot to return newBlock when createBlock is called
Edit 4: Tested this on my own: it works.

1 Like