local function CreateOre(ore, position)
ore.Parent = Mine
ore.CFrame = position
print(position.Y)
if position.Y > 13995 or BlockData:FindFirstChild(tostring(ore.CFrame)) then
ore:Destroy()
end
Instance.new('Folder', BlockData).Name = tostring(ore.CFrame)
end
For some reason, it only starts working a layer down
Shows that when I mine the top layer, it gets destroyed. I tried changing the code to
local function CreateOre(ore, position)
ore.Parent = Mine
ore.CFrame = position
print(position.Y)
if position.Y > 14000 or BlockData:FindFirstChild(tostring(ore.CFrame)) then
ore:Destroy()
end
Instance.new('Folder', BlockData).Name = tostring(ore.CFrame)
end
Unfortunately I don’t think we can particularly help much without knowing more about those magic numbers you use for your Y coordinates. What are the sizes of your blocks / what size grid are they aligned upon?
If you add more information on this, it will be easier for other people to figure out what your code does and find a solution to your issue
(also, have you considered using a constant for your magic number?)
I suspect this is a combination of multiple issues with your code.
The first change I’d make is to not use the CFrame to name your block data instances. Instead, I’d use string.format to generate a string containing the integer block position and use that instead;
local function CreateOre(ore, position)
ore.Parent = Mine
ore.CFrame = position
local blockDataName = ("%d,%d,%d"):format(ore.Position.X, ore.Position.Y, ore.Position.Z)
if position.Y > 13995 or BlockData:FindFirstChild(blockDataName) then
ore:Destroy()
end
Instance.new('Folder', BlockData).Name = blockDataName
end
Secondly, I’d change your altitude checking code to round the position;
local function CreateOre(ore, position)
ore.Parent = Mine
ore.CFrame = position
local blockDataName = ("%d,%d,%d"):format(ore.Position.X, ore.Position.Y, ore.Position.Z)
if math.floor(position.Y + 0.5) > 14000 or BlockData:FindFirstChild(blockDataName) then
ore:Destroy()
end
Instance.new('Folder', BlockData).Name = blockDataName
end
I’ve tried setting like a grid position, so if the position is anywhere with the starting grid then it doesn’t create a block
-- Above the grid
if position.Y > 14000 then
ore:Destroy()
end
if position.Y > 13995 or BlockData:FindFirstChild(tostring(ore.CFrame)) then
if position.X < 36 and position.Z > -36 then
if position.X > -36 and position.Z > 36 then
ore:Destroy()
end
end
end
If I get the 2 opposite corners of a square, they are
28, -28
-28,28
So that’s the opposite corners of the starting blocks
Try what I suggested above, it may help.
More specifically, you might be running into floating point precision errors by converting your ore’s CFrame to a string and using it to uniquely index each grid position.
Haha it was a lot simpler then! I’d recommend reusing the function (you used to place the blocks around where you dig) for placing the floor blocks to avoid that in future
The function you posted should work with different block types pretty easily; all it does is set the parent and CFrame, and adds its position to BlockData. The only condition where it wouldn’t place the block would be either if you try to place the block above ground level or if you place a block where another block exists (determined by the instances in BlockData). Therefore it shouldn’t be an issue to simply call that function with each floor block and it’s intended position, just like you presumably are doing elsewhere in your code to place each block in its position around your mined block.
I’d personally use two nested for loops, possibly something like this;
local function CreateFloor()
local blockSize = 8
for xPos=-24, 24, blockSize do
for zPos=-24, 24, blockSize do
local block = YourBlockInstanceInStorage:Clone()
CreateOre(block, CFrame.new(xPos, 14000, zPos))
end
end
end
The -24 and 24 represent the range of block positions along the X and Z axes; feel free to modify those to fit your surface’s size. Calling that function would in theory place a brand new floor at the surface.
You’d probably want a function like this for if/when you reset the blocks to their initial state anyways. Hope it helps
local function CreateOre(ore, position)
ore.Parent = Mine
ore.CFrame = position -- Cframe expected, got Vector
local blockDataName = ("%d,%d,%d"):format(ore.Position.X, ore.Position.Y, ore.Position.Z)
if math.floor(position.Y + 0.5) > 14000 or BlockData:FindFirstChild(blockDataName) then
ore:Destroy()
end
Instance.new('Folder', BlockData).Name = blockDataName
end
local function CreateFloor()
local blockSize = 8
for xPos=-24, 24, blockSize do
for zPos=-24, 24, blockSize do
local block = Blocks.Dirt:Clone()
CreateOre(block, Vector3.new(xPos, 14000, zPos))
end
end
end
Would I change the CFrame to Vector3, or the Vector3 to CFrame?
That’s unnecessarily complex for Ninjo’s use case; in most cases, it’s usually better not to introduce multiple ways of doing things where it’s not explicitly needed.
Ok that seems to all be working But I just realised that spawning blocks on the surface layer would mean that there’d be no roof, like example:
If I have grass or whatever above it as like natural land, ye it’s good, but players could just mine well past that
And it wouldn’t make sense to just extend the grass, so my solution would be create bedrock on that top layer, but how I can determine that?
local function CreateBedrock(_, position)
local Bedrock = Blocks:FindFirstChild('Bedrock')
if Bedrock then
local Clone = Bedrock:Clone()
Clone.Parent = Mine
Clone.CFrame = position
end
end
local function CreateOre(ore, position)
ore.Parent = Mine
ore.CFrame = position
local blockDataName = ("%d,%d,%d"):format(ore.Position.X, ore.Position.Y, ore.Position.Z)
if math.floor(position.Y + 0.5) > 14000 or BlockData:FindFirstChild(blockDataName) then
ore:Destroy()
end
-- Somehow check if block is at surface level (same level as the default dirt)
-- if it is, then use CreateBedrock() function
Instance.new('Folder', BlockData).Name = blockDataName
end
That is indeed the solution I’ve seen most mining games use! Typically the first layer of blocks is all bedrock, except for the middle area where you dig down. This stops people from digging back up to the surface outside of the middle area.
The way I’d approach this is by first writing a function to determine whether bedrock should be placed at a given location;
local function ShouldPlaceBedrockAt(position)
if position.Y < 14000 then
-- don't place bedrock if the vertical position is below the first laer
return false
end
if (position.X >= -24 and position.X <= 24) and (position.Z >= -24 and position.Z <= 24) then
-- don't place bedrock if the horizontal position is in the middle area
return false
end
-- place bedrock here; this position is not in the middle area and not below the first layer
return true
end
Then, I’d use the result of that function in the code which determines which block types to place when you dig a block. Specifically, for each block surrounding the mined block, if ShouldPlaceBedrockAt(position) returns true, use the bedrock block type, otherwise calculate your block type as usual.
Have to go to sleep, but that should work. If you have any other issues, I’m sure there’s plenty of others willing to help here! I’ll check back in with this thread in the morning just in case