codex: stuff
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
This project is a Minecraft-like voxel system for Roblox using Rojo. The server
|
||||
is authoritative over chunks and blocks. Clients only handle input, UI, and
|
||||
requests. Clients must never create or destroy blocks directly. The server must
|
||||
validate distance, block type, and target. Shared modules must not reference
|
||||
Roblox services.
|
||||
# Agents
|
||||
|
||||
Keep in mind that to replicate anything across the client-server model or to
|
||||
write to any instance you must use serial luau
|
||||
- This project is a Minecraft-like voxel system for Roblox using Rojo.
|
||||
- The server is authoritative over chunks and blocks.
|
||||
- Clients only handle input, UI, and requests.
|
||||
- Clients must never create or destroy blocks directly.
|
||||
- The server must validate distance, block type, and target.
|
||||
- Shared modules must not reference Roblox services.
|
||||
|
||||
Note: To replicate anything across the client-server model or to write to any
|
||||
instance you must use serial Luau.
|
||||
|
||||
The main AGENTS.md file is in the `.codex` folder!
|
||||
|
||||
7
src/ReplicatedStorage/Remotes/InventoryRequest.rbxmx
Normal file
7
src/ReplicatedStorage/Remotes/InventoryRequest.rbxmx
Normal file
@@ -0,0 +1,7 @@
|
||||
<roblox version="4">
|
||||
<Item class="RemoteEvent" referent="RBX5B7E5C8D4E2348B78F8C1A2E9E6D4F90">
|
||||
<Properties>
|
||||
<string name="Name">InventoryRequest</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</roblox>
|
||||
7
src/ReplicatedStorage/Remotes/InventorySync.rbxmx
Normal file
7
src/ReplicatedStorage/Remotes/InventorySync.rbxmx
Normal file
@@ -0,0 +1,7 @@
|
||||
<roblox version="4">
|
||||
<Item class="RemoteEvent" referent="RBX7A1C0A5FA0E0412F9B2F5A43B9C4B3A1">
|
||||
<Properties>
|
||||
<string name="Name">InventorySync</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</roblox>
|
||||
32
src/ReplicatedStorage/Shared/Catppuccin.lua
Normal file
32
src/ReplicatedStorage/Shared/Catppuccin.lua
Normal file
@@ -0,0 +1,32 @@
|
||||
local Catppuccin = {}
|
||||
|
||||
Catppuccin.mocha = {
|
||||
rosewater = Color3.fromRGB(245, 224, 220),
|
||||
flamingo = Color3.fromRGB(242, 205, 205),
|
||||
pink = Color3.fromRGB(245, 194, 231),
|
||||
base = Color3.fromRGB(30, 30, 46),
|
||||
mantle = Color3.fromRGB(24, 24, 37),
|
||||
crust = Color3.fromRGB(17, 17, 27),
|
||||
surface0 = Color3.fromRGB(49, 50, 68),
|
||||
surface1 = Color3.fromRGB(69, 71, 90),
|
||||
surface2 = Color3.fromRGB(88, 91, 112),
|
||||
overlay0 = Color3.fromRGB(108, 112, 134),
|
||||
overlay1 = Color3.fromRGB(127, 132, 156),
|
||||
overlay2 = Color3.fromRGB(147, 153, 178),
|
||||
text = Color3.fromRGB(205, 214, 244),
|
||||
subtext0 = Color3.fromRGB(166, 173, 200),
|
||||
subtext1 = Color3.fromRGB(186, 194, 222),
|
||||
mauve = Color3.fromRGB(203, 166, 247),
|
||||
red = Color3.fromRGB(243, 139, 168),
|
||||
maroon = Color3.fromRGB(235, 160, 172),
|
||||
peach = Color3.fromRGB(250, 179, 135),
|
||||
yellow = Color3.fromRGB(249, 226, 175),
|
||||
green = Color3.fromRGB(166, 227, 161),
|
||||
teal = Color3.fromRGB(148, 226, 213),
|
||||
sky = Color3.fromRGB(137, 220, 235),
|
||||
sapphire = Color3.fromRGB(116, 199, 236),
|
||||
blue = Color3.fromRGB(137, 180, 250),
|
||||
lavender = Color3.fromRGB(180, 190, 254),
|
||||
}
|
||||
|
||||
return Catppuccin
|
||||
106
src/ReplicatedStorage/Shared/Inventory.lua
Normal file
106
src/ReplicatedStorage/Shared/Inventory.lua
Normal file
@@ -0,0 +1,106 @@
|
||||
local Inventory = {}
|
||||
|
||||
local HOTBAR_SIZE = 9
|
||||
local slots = table.create(HOTBAR_SIZE)
|
||||
local selectedIndex = 1
|
||||
|
||||
local listeners = {
|
||||
changed = {},
|
||||
selected = {},
|
||||
}
|
||||
|
||||
local function addListener(list, fn)
|
||||
table.insert(list, fn)
|
||||
local active = true
|
||||
return {
|
||||
Disconnect = function()
|
||||
if not active then
|
||||
return
|
||||
end
|
||||
active = false
|
||||
for i, cb in ipairs(list) do
|
||||
if cb == fn then
|
||||
table.remove(list, i)
|
||||
break
|
||||
end
|
||||
end
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local function notify(list, ...)
|
||||
for _, cb in ipairs(list) do
|
||||
cb(...)
|
||||
end
|
||||
end
|
||||
|
||||
function Inventory.GetHotbarSize(): number
|
||||
return HOTBAR_SIZE
|
||||
end
|
||||
|
||||
function Inventory.GetSlots(): {string?}
|
||||
return slots
|
||||
end
|
||||
|
||||
function Inventory.GetSlot(index: number): string?
|
||||
return slots[index]
|
||||
end
|
||||
|
||||
function Inventory.SetSlots(ids: {string?})
|
||||
for i = 1, HOTBAR_SIZE do
|
||||
local value = ids[i]
|
||||
if value == "" then
|
||||
value = nil
|
||||
end
|
||||
slots[i] = value
|
||||
end
|
||||
selectedIndex = math.clamp(selectedIndex, 1, HOTBAR_SIZE)
|
||||
if slots[selectedIndex] == nil then
|
||||
for i = 1, HOTBAR_SIZE do
|
||||
if slots[i] ~= nil then
|
||||
selectedIndex = i
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
notify(listeners.changed, slots)
|
||||
notify(listeners.selected, selectedIndex, Inventory.GetSelectedId())
|
||||
end
|
||||
|
||||
function Inventory.SetSlot(index: number, id: string?)
|
||||
if index < 1 or index > HOTBAR_SIZE then
|
||||
return
|
||||
end
|
||||
slots[index] = id
|
||||
notify(listeners.changed, slots)
|
||||
end
|
||||
|
||||
function Inventory.GetSelectedIndex(): number
|
||||
return selectedIndex
|
||||
end
|
||||
|
||||
function Inventory.SetSelectedIndex(index: number)
|
||||
if index < 1 or index > HOTBAR_SIZE then
|
||||
return
|
||||
end
|
||||
if selectedIndex == index then
|
||||
return
|
||||
end
|
||||
selectedIndex = index
|
||||
notify(listeners.selected, selectedIndex, Inventory.GetSelectedId())
|
||||
end
|
||||
|
||||
function Inventory.GetSelectedId(): string?
|
||||
local id = slots[selectedIndex]
|
||||
return id
|
||||
end
|
||||
|
||||
function Inventory.OnChanged(callback)
|
||||
return addListener(listeners.changed, callback)
|
||||
end
|
||||
|
||||
function Inventory.OnSelected(callback)
|
||||
return addListener(listeners.selected, callback)
|
||||
end
|
||||
|
||||
return Inventory
|
||||
@@ -67,6 +67,8 @@ local tickRemote = ReplicatedStorage.Tick
|
||||
local remotes = ReplicatedStorage:WaitForChild("Remotes")
|
||||
local placeRemote = remotes:WaitForChild("PlaceBlock")
|
||||
local breakRemote = remotes:WaitForChild("BreakBlock")
|
||||
local inventorySync = remotes:WaitForChild("InventorySync")
|
||||
local inventoryRequest = remotes:WaitForChild("InventoryRequest")
|
||||
local blocksFolder = ReplicatedStorage:WaitForChild("Blocks")
|
||||
local function propogate(a, cx, cy, cz, x, y, z, bd)
|
||||
task.synchronize()
|
||||
@@ -75,7 +77,9 @@ local function propogate(a, cx, cy, cz, x, y, z, bd)
|
||||
end
|
||||
|
||||
local MAX_REACH = 24
|
||||
local HOTBAR_SIZE = 9
|
||||
local blockIdMap = {}
|
||||
local playerInventories = {}
|
||||
|
||||
local function rebuildBlockIdMap()
|
||||
table.clear(blockIdMap)
|
||||
@@ -92,6 +96,94 @@ rebuildBlockIdMap()
|
||||
blocksFolder.ChildAdded:Connect(rebuildBlockIdMap)
|
||||
blocksFolder.ChildRemoved:Connect(rebuildBlockIdMap)
|
||||
|
||||
local function buildDefaultSlots(): {string}
|
||||
local ids = {}
|
||||
for _, block in ipairs(blocksFolder:GetChildren()) do
|
||||
local id = block:GetAttribute("n")
|
||||
if id ~= nil then
|
||||
table.insert(ids, tostring(id))
|
||||
end
|
||||
end
|
||||
table.sort(ids, function(a, b)
|
||||
return a < b
|
||||
end)
|
||||
local slots = table.create(HOTBAR_SIZE, "")
|
||||
for i = 1, HOTBAR_SIZE do
|
||||
slots[i] = ids[i]
|
||||
end
|
||||
return slots
|
||||
end
|
||||
|
||||
local function syncInventory(player: Player)
|
||||
local data = playerInventories[player.UserId]
|
||||
if not data then
|
||||
return
|
||||
end
|
||||
task.synchronize()
|
||||
inventorySync:FireClient(player, data.slots)
|
||||
end
|
||||
|
||||
local function rebuildAllInventories()
|
||||
for _, player in ipairs(game:GetService("Players"):GetPlayers()) do
|
||||
local slots = buildDefaultSlots()
|
||||
local allowed = {}
|
||||
for i = 1, HOTBAR_SIZE do
|
||||
local id = slots[i]
|
||||
if id ~= "" then
|
||||
allowed[id] = true
|
||||
end
|
||||
end
|
||||
playerInventories[player.UserId] = {
|
||||
slots = slots,
|
||||
allowed = allowed,
|
||||
}
|
||||
syncInventory(player)
|
||||
end
|
||||
end
|
||||
|
||||
blocksFolder.ChildAdded:Connect(rebuildAllInventories)
|
||||
blocksFolder.ChildRemoved:Connect(rebuildAllInventories)
|
||||
|
||||
game:GetService("Players").PlayerAdded:Connect(function(player: Player)
|
||||
local slots = buildDefaultSlots()
|
||||
local allowed = {}
|
||||
for i = 1, HOTBAR_SIZE do
|
||||
local id = slots[i]
|
||||
if id ~= "" then
|
||||
allowed[id] = true
|
||||
end
|
||||
end
|
||||
playerInventories[player.UserId] = {
|
||||
slots = slots,
|
||||
allowed = allowed,
|
||||
}
|
||||
syncInventory(player)
|
||||
end)
|
||||
|
||||
game:GetService("Players").PlayerRemoving:Connect(function(player: Player)
|
||||
playerInventories[player.UserId] = nil
|
||||
end)
|
||||
|
||||
for _, player in ipairs(game:GetService("Players"):GetPlayers()) do
|
||||
local slots = buildDefaultSlots()
|
||||
local allowed = {}
|
||||
for i = 1, HOTBAR_SIZE do
|
||||
local id = slots[i]
|
||||
if id ~= "" then
|
||||
allowed[id] = true
|
||||
end
|
||||
end
|
||||
playerInventories[player.UserId] = {
|
||||
slots = slots,
|
||||
allowed = allowed,
|
||||
}
|
||||
syncInventory(player)
|
||||
end
|
||||
|
||||
inventoryRequest.OnServerEvent:Connect(function(player: Player)
|
||||
syncInventory(player)
|
||||
end)
|
||||
|
||||
local function getPlayerPosition(player: Player): Vector3?
|
||||
local character = player.Character
|
||||
if not character then
|
||||
@@ -117,6 +209,14 @@ local function resolveBlockId(blockId: any): string | number | nil
|
||||
return blockIdMap[blockId]
|
||||
end
|
||||
|
||||
local function playerHasBlockId(player: Player, blockId: string | number): boolean
|
||||
local data = playerInventories[player.UserId]
|
||||
if not data then
|
||||
return false
|
||||
end
|
||||
return data.allowed[tostring(blockId)] == true
|
||||
end
|
||||
|
||||
local function getServerChunk(cx: number, cy: number, cz: number)
|
||||
task.desynchronize()
|
||||
local chunk = TG:GetChunk(cx, cy, cz)
|
||||
@@ -146,6 +246,9 @@ placeRemote.OnServerEvent:Connect(function(player, cx, cy, cz, x, y, z, blockId)
|
||||
if not resolvedId then
|
||||
return
|
||||
end
|
||||
if not playerHasBlockId(player, resolvedId) then
|
||||
return
|
||||
end
|
||||
|
||||
local chunk = getServerChunk(cx, cy, cz)
|
||||
if chunk:GetBlockAt(x, y, z) then
|
||||
|
||||
@@ -5,6 +5,11 @@ end
|
||||
local ui = script.Parent
|
||||
|
||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
|
||||
local Inventory = require(ReplicatedStorage.Shared.Inventory)
|
||||
local Catppuccin = require(ReplicatedStorage.Shared.Catppuccin)
|
||||
local blocksFolder = ReplicatedStorage:WaitForChild("Blocks")
|
||||
|
||||
local mocha = Catppuccin.mocha
|
||||
|
||||
ReplicatedStorage:WaitForChild("Objects"):WaitForChild("MLLoaded")
|
||||
|
||||
@@ -17,6 +22,165 @@ cd.Parent = game:GetService("Workspace"):FindFirstChildOfClass("Terrain")
|
||||
sky.Parent = game:GetService("Workspace"):FindFirstChildOfClass("Terrain")
|
||||
base.Parent = game:GetService("Workspace"):FindFirstChildOfClass("Terrain")
|
||||
|
||||
local hotbarRoot = ui:WaitForChild("Hotbar")
|
||||
local hotbarSlotsRoot = hotbarRoot:WaitForChild("Frame")
|
||||
local hotbarSelectLabel = ui:WaitForChild("HotbarItemSelectLabel")
|
||||
local hotbarSelectText = hotbarSelectLabel:WaitForChild("TextLabel")
|
||||
local hotbarDebug = ui:WaitForChild("HotbarDebug")
|
||||
local hotbarDebugText = hotbarDebug:WaitForChild("TextLabel")
|
||||
local debugUpperText = ui:WaitForChild("DebugUpperText")
|
||||
local hotbarStroke = hotbarRoot:FindFirstChild("UIStroke")
|
||||
local hotbarSelectStroke = hotbarSelectLabel:FindFirstChild("UIStroke")
|
||||
local hotbarDebugStroke = hotbarDebug:FindFirstChild("UIStroke")
|
||||
|
||||
hotbarRoot.BackgroundColor3 = mocha.base
|
||||
if hotbarStroke then
|
||||
hotbarStroke.Color = mocha.blue
|
||||
end
|
||||
hotbarSelectLabel.BackgroundColor3 = mocha.base
|
||||
if hotbarSelectStroke then
|
||||
hotbarSelectStroke.Color = mocha.blue
|
||||
end
|
||||
hotbarDebug.BackgroundColor3 = mocha.base
|
||||
if hotbarDebugStroke then
|
||||
hotbarDebugStroke.Color = mocha.surface2
|
||||
end
|
||||
hotbarSelectText.TextColor3 = mocha.text
|
||||
hotbarDebugText.TextColor3 = mocha.text
|
||||
debugUpperText.TextColor3 = mocha.text
|
||||
|
||||
local slotFrames = {}
|
||||
local slotStrokes = {}
|
||||
local slotLabels = {}
|
||||
local renderHotbar = nil
|
||||
|
||||
local blockDisplayNames = {}
|
||||
local blockIcons = {}
|
||||
|
||||
local function rebuildBlockMappings()
|
||||
table.clear(blockDisplayNames)
|
||||
table.clear(blockIcons)
|
||||
for _, block in ipairs(blocksFolder:GetChildren()) do
|
||||
local id = block:GetAttribute("n")
|
||||
if id ~= nil then
|
||||
blockDisplayNames[tostring(id)] = block.Name
|
||||
local icon = block:GetAttribute("icon")
|
||||
if typeof(icon) == "string" and icon ~= "" then
|
||||
blockIcons[tostring(id)] = icon
|
||||
end
|
||||
end
|
||||
end
|
||||
if renderHotbar then
|
||||
renderHotbar()
|
||||
end
|
||||
end
|
||||
|
||||
rebuildBlockMappings()
|
||||
blocksFolder.ChildAdded:Connect(rebuildBlockMappings)
|
||||
blocksFolder.ChildRemoved:Connect(rebuildBlockMappings)
|
||||
|
||||
for i = 1, Inventory.GetHotbarSize() do
|
||||
local slotName = `HotbarSlot{i - 1}`
|
||||
local slot = hotbarSlotsRoot:WaitForChild(slotName)
|
||||
slotFrames[i] = slot
|
||||
local stroke = slot:FindFirstChild("UIStroke")
|
||||
if not stroke then
|
||||
stroke = Instance.new("UIStroke")
|
||||
stroke.Parent = slot
|
||||
end
|
||||
slotStrokes[i] = stroke
|
||||
|
||||
local imageLabel = slot:FindFirstChild("ImageLabel")
|
||||
if not imageLabel then
|
||||
imageLabel = Instance.new("ImageLabel")
|
||||
imageLabel.Name = "ImageLabel"
|
||||
imageLabel.BackgroundTransparency = 1
|
||||
imageLabel.Size = UDim2.fromScale(1, 1)
|
||||
imageLabel.ScaleType = Enum.ScaleType.Fit
|
||||
imageLabel.Parent = slot
|
||||
end
|
||||
|
||||
local label = slot:FindFirstChild("TextLabel")
|
||||
if not label then
|
||||
label = Instance.new("TextLabel")
|
||||
label.Name = "TextLabel"
|
||||
label.BackgroundTransparency = 1
|
||||
label.Size = UDim2.fromScale(1, 1)
|
||||
label.TextScaled = true
|
||||
label.Font = Enum.Font.Gotham
|
||||
label.TextColor3 = mocha.text
|
||||
label.TextWrapped = true
|
||||
label.ZIndex = 3
|
||||
label.Parent = slot
|
||||
end
|
||||
slotLabels[i] = label
|
||||
end
|
||||
|
||||
renderHotbar = function()
|
||||
for i = 1, Inventory.GetHotbarSize() do
|
||||
local slot = slotFrames[i]
|
||||
if slot then
|
||||
slot.BackgroundColor3 = mocha.surface0
|
||||
local stroke = slotStrokes[i]
|
||||
if stroke then
|
||||
if i == Inventory.GetSelectedIndex() then
|
||||
stroke.Color = mocha.blue
|
||||
stroke.Thickness = 2
|
||||
else
|
||||
stroke.Color = mocha.surface2
|
||||
stroke.Thickness = 1
|
||||
end
|
||||
end
|
||||
|
||||
local imageLabel = slot:FindFirstChild("ImageLabel")
|
||||
local id = Inventory.GetSlot(i)
|
||||
local displayName = id and (blockDisplayNames[tostring(id)] or tostring(id)) or ""
|
||||
if imageLabel then
|
||||
local icon = id and blockIcons[tostring(id)] or nil
|
||||
imageLabel.Visible = icon ~= nil
|
||||
imageLabel.Image = icon or ""
|
||||
imageLabel.BackgroundTransparency = 1
|
||||
imageLabel.ZIndex = 2
|
||||
end
|
||||
|
||||
local textLabel = slotLabels[i]
|
||||
if textLabel then
|
||||
textLabel.Text = displayName
|
||||
textLabel.TextColor3 = mocha.text
|
||||
textLabel.Visible = displayName ~= ""
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function updateSelectedLabel()
|
||||
local id = Inventory.GetSelectedId()
|
||||
local displayName = id and (blockDisplayNames[tostring(id)] or tostring(id)) or nil
|
||||
if hotbarSelectText then
|
||||
hotbarSelectText.Text = displayName and `Selected: {displayName}` or "Selected: (empty)"
|
||||
end
|
||||
if hotbarDebugText then
|
||||
hotbarDebugText.Text = `Slot {Inventory.GetSelectedIndex()} Id {displayName or "empty"}`
|
||||
end
|
||||
end
|
||||
|
||||
local extraSlot = hotbarSlotsRoot and hotbarSlotsRoot:FindFirstChild("HotbarSlot9")
|
||||
if extraSlot then
|
||||
extraSlot.Visible = false
|
||||
end
|
||||
|
||||
renderHotbar()
|
||||
updateSelectedLabel()
|
||||
|
||||
Inventory.OnChanged(function()
|
||||
renderHotbar()
|
||||
updateSelectedLabel()
|
||||
end)
|
||||
|
||||
Inventory.OnSelected(function()
|
||||
renderHotbar()
|
||||
updateSelectedLabel()
|
||||
end)
|
||||
|
||||
game:GetService("RunService").RenderStepped:Connect(function(dt)
|
||||
local fps = math.round(1/dt)
|
||||
|
||||
@@ -7,12 +7,11 @@ local UIS = game:GetService("UserInputService")
|
||||
|
||||
ReplicatedStorage:WaitForChild("Objects"):WaitForChild("MLLoaded")
|
||||
|
||||
local blocksFolder = ReplicatedStorage:WaitForChild("Blocks")
|
||||
local PM = require(ReplicatedStorage.Shared.PlacementManager)
|
||||
|
||||
local HOTBAR_SIZE = 9
|
||||
local hotbar = table.create(HOTBAR_SIZE)
|
||||
local selectedSlot = 1
|
||||
local Inventory = require(ReplicatedStorage.Shared.Inventory)
|
||||
local remotes = ReplicatedStorage:WaitForChild("Remotes")
|
||||
local inventorySync = remotes:WaitForChild("InventorySync")
|
||||
local inventoryRequest = remotes:WaitForChild("InventoryRequest")
|
||||
|
||||
local keyToSlot = {
|
||||
[Enum.KeyCode.One] = 1,
|
||||
@@ -26,40 +25,25 @@ local keyToSlot = {
|
||||
[Enum.KeyCode.Nine] = 9,
|
||||
}
|
||||
|
||||
local function rebuildHotbar()
|
||||
local ids = {}
|
||||
for _, block in ipairs(blocksFolder:GetChildren()) do
|
||||
local id = block:GetAttribute("n")
|
||||
if id ~= nil then
|
||||
table.insert(ids, tostring(id))
|
||||
local function findNextFilledIndex(startIndex: number, direction: number): number
|
||||
local size = Inventory.GetHotbarSize()
|
||||
for step = 1, size do
|
||||
local idx = ((startIndex - 1 + (direction * step)) % size) + 1
|
||||
if Inventory.GetSlot(idx) ~= nil then
|
||||
return idx
|
||||
end
|
||||
end
|
||||
return startIndex
|
||||
end
|
||||
|
||||
table.sort(ids)
|
||||
for i = 1, HOTBAR_SIZE do
|
||||
hotbar[i] = ids[i] or ""
|
||||
end
|
||||
selectedSlot = math.clamp(selectedSlot, 1, HOTBAR_SIZE)
|
||||
end
|
||||
|
||||
local function getSelectedBlockId(): string?
|
||||
local id = hotbar[selectedSlot]
|
||||
if id == "" then
|
||||
return nil
|
||||
end
|
||||
return id
|
||||
end
|
||||
|
||||
local function setSelectedSlot(slot: number)
|
||||
if slot < 1 or slot > HOTBAR_SIZE then
|
||||
inventorySync.OnClientEvent:Connect(function(slots)
|
||||
if typeof(slots) ~= "table" then
|
||||
return
|
||||
end
|
||||
selectedSlot = slot
|
||||
end
|
||||
Inventory.SetSlots(slots)
|
||||
end)
|
||||
|
||||
rebuildHotbar()
|
||||
blocksFolder.ChildAdded:Connect(rebuildHotbar)
|
||||
blocksFolder.ChildRemoved:Connect(rebuildHotbar)
|
||||
inventoryRequest:FireServer()
|
||||
|
||||
UIS.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean)
|
||||
if gameProcessedEvent then
|
||||
@@ -68,7 +52,9 @@ UIS.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean)
|
||||
|
||||
local slot = keyToSlot[input.KeyCode]
|
||||
if slot then
|
||||
setSelectedSlot(slot)
|
||||
if Inventory.GetSlot(slot) ~= nil then
|
||||
Inventory.SetSelectedIndex(slot)
|
||||
end
|
||||
return
|
||||
end
|
||||
|
||||
@@ -83,10 +69,25 @@ UIS.InputBegan:Connect(function(input: InputObject, gameProcessedEvent: boolean)
|
||||
if not mouseBlock then
|
||||
return
|
||||
end
|
||||
local blockId = getSelectedBlockId()
|
||||
local blockId = Inventory.GetSelectedId()
|
||||
if not blockId then
|
||||
return
|
||||
end
|
||||
PM:PlaceBlock(mouseBlock.chunk.X, mouseBlock.chunk.Y, mouseBlock.chunk.Z, mouseBlock.block.X, mouseBlock.block.Y, mouseBlock.block.Z, blockId)
|
||||
end
|
||||
end)
|
||||
|
||||
UIS.InputChanged:Connect(function(input: InputObject, gameProcessedEvent: boolean)
|
||||
if gameProcessedEvent then
|
||||
return
|
||||
end
|
||||
if input.UserInputType == Enum.UserInputType.MouseWheel then
|
||||
local delta = input.Position.Z
|
||||
if delta == 0 then
|
||||
return
|
||||
end
|
||||
local direction = delta > 0 and -1 or 1
|
||||
local nextIndex = findNextFilledIndex(Inventory.GetSelectedIndex(), direction)
|
||||
Inventory.SetSelectedIndex(nextIndex)
|
||||
end
|
||||
end)
|
||||
|
||||
Reference in New Issue
Block a user