Hi! I’m RenKa. I’ve been on the platform since 2016 and have been developing on it for about 5 years.
I like performance, code readability, and quality-of-life in everything I do. I aim to create clean, extensible systems that are effective to use and extend.
I write Modular, extensible, and responsive systems
I am totally obsessed with code cleanliness, from naming to memory management
I design performance-first, avoiding unnecessary abstractions
I have experience in:
Trello & Notion for project management
Git, GitHub & Rojo
OOP (Object-Oriented Programming)
Frameworks like Knit, Nevermore Engine, and other Luau frameworks. including one I made myself
Building organized, type-safe, and memory-safe codebases
Working with large existing codebases
Efficiently work and communicate with large groups
Performing well under pressure
Project management
🔧 Tool Framework
I have designed a Tool Framework for my personal project, designed to work as a framework for all my tool types and make production easier and faster.
One of the tool types in my game is melee, which works with state machines and proving huge performance!
BaseFramework.luau is ~300 lines.
Melee Type
local replicatedStorage = game:GetService("ReplicatedStorage")
local httpService = game:GetService("HttpService")
local customPackages = replicatedStorage.CustomPackages
local packages = replicatedStorage.Packages
local shared = replicatedStorage.Shared
local robloxStateMachine = require(customPackages.RobloxStateMachine)
local shapecastHitbox = require(customPackages.ShapecastHitbox)
local baseFramework = require(script.Parent.BaseFramework)
local instanceUtils = require(packages.InstanceUtils)
local actionBinder = require(packages.ActionBinder)
local valueObject = require(packages.ValueObject)
local tableUtils = require(packages.TableUtils)
local combat = require(customPackages.Combat)
local vfxActions = require(shared.VFXActions)
local utils = require(customPackages.Utils)
local rx = require(packages.Rx)
local defaultSettings = {
HasHitboxes = true,
CanReplicate = true,
}
local melee = {}
melee.__index = melee
function melee.new(tool: Tool, config: typeof(defaultSettings)?)
local self = setmetatable(baseFramework.new(tool), melee) :: Melee
self.MaxSwings = self.Janitor:Add(valueObject.new(#tableUtils.Values(self.ToolData.Animations.Swings), "number"))
self.SwingIndex = self.Janitor:Add(valueObject.new(0, "number"))
self.LastSwing = self.Janitor:Add(valueObject.new(0, "number"))
self._Hitboxes = {}
self.Config = tableUtils.Reconcile(config or {}, defaultSettings)
self.StateMachine = self.Janitor:Add(robloxStateMachine.new("None", robloxStateMachine:LoadDirectory(script), self))
self:LoadAnimList(self.ToolData.Animations)
local swingParams = RaycastParams.new()
swingParams.FilterType = Enum.RaycastFilterType.Exclude
swingParams.FilterDescendantsInstances = {self.Entity, workspace.Terrain}
swingParams.IgnoreWater = true
for name in self.ToolData.Animations.Swings do
local track = self:GetTrack(name)
if not track then
continue
end
local hitboxIndex = httpService:JSONDecode(track.Animation:GetAttribute("HitboxIndex"))
for _, side in hitboxIndex do
local hitboxPart = self.Tool.Hitboxes:FindFirstChild(side)
if not side then
warn("No side hitbox for", side, tool)
continue
end
table.insert(self._Hitboxes, side, self.Janitor:Add(shapecastHitbox.new(hitboxPart, swingParams)))
end
end
self.Janitor:Add(self.Equipped:Connect(function()
self:_onEquipped()
end))
self.Janitor:Add(self.Unequipped:Connect(function()
self:_onUnequipped()
end))
if self.IsEquipped then
self:_onEquipped()
end
return self
end
function melee.Replicate(self: Melee, data: {any})
if not self.Config.CanReplicate then
return
end
data.Name = self.ToolData.Name
data.ToolID = self:GetID()
vfxActions:Replicate("ToolAction", self.Entity:GetAttribute("ID"), data)
end
function melee._onEquipped(self: Melee)
self.StateMachine:ChangeState("Equip")
for name in self.ToolData.Animations.Swings do
local track = self:GetTrack(name)
if not track then
continue
end
local hitboxIndex = httpService:JSONDecode(track.Animation:GetAttribute("HitboxIndex"))
self.EquippedJanitor:Add(track:GetMarkerReachedSignal("startHit"):Connect(function()
for _, side in hitboxIndex do
local hitbox = self._Hitboxes[side]
local hitParts = {}
hitbox:HitStart(nil):OnHit(function(raycastResult: RaycastResult)
local instance = raycastResult.Instance
if table.find(hitParts, instance) then
return
end
local humanoid = instance.Parent:FindFirstChildWhichIsA("Humanoid")
if not humanoid or table.find(hitParts, humanoid) or not humanoid.Parent:GetAttribute("ID") then
return
end
table.insert(hitParts, humanoid)
local hitData = {
TargetID = humanoid.Parent:GetAttribute("ID"),
ToolID = self:GetID()
}
utils:ContextAction("Server", function()
combat:MeleeHit(self.Entity:GetAttribute("ID"), hitData)
end)
utils:ContextAction("Client", function()
local result = combat:MeleeHit(nil, hitData)
if result then
utils:ShakeCamera({
FadeInTime = 0,
FadeOutTime = 0.3,
Frequency = 0.1,
Amplitude = math.min(self.ToolData.Damage, 100),
PositionInfluence = Vector3.one * 0.1,
RotationInfluence = Vector3.zero
})
utils:ImpulseFov(self.ToolData.Damage / 10)
end
end)
end):OnStopped(function(clearCallbacks)
clearCallbacks()
table.clear(hitParts)
end)
end
end))
local function stopHitboxes()
for _, side in hitboxIndex do
local hitbox = self._Hitboxes[side]
hitbox:HitStop()
end
end
self.EquippedJanitor:Add(track:GetMarkerReachedSignal("stopHit"):Connect(stopHitboxes))
self.EquippedJanitor:Add(instanceUtils.ObserveProperty(track, "IsPlaying"):Pipe({
rx.where(function(isPlaying: boolean)
return isPlaying == false
end)
}):Subscribe(stopHitboxes))
end
utils:ContextAction("Client", function()
for _, state in self.StateMachine:GetStates() do
if not state.InputData then
continue
end
self.EquippedJanitor:Add(actionBinder.BindActionAtPriority(state.Name, function(inputState: Enum.UserInputState)
if inputState == Enum.UserInputState.Begin then
local result, wasCalled = utils:OptionalCall(state, "ShouldActivate")
if not result and wasCalled then
return
end
self.StateMachine:ChangeState(state.Name)
return
end
return Enum.ContextActionResult.Pass
end, state.InputData.Priority, table.unpack(state.InputData.Keys)))
end
end)
end
function melee._onUnequipped(self: Melee)
self.StateMachine:ChangeState("None")
self:Replicate({
Action = "Unequip"
})
end
export type Melee = baseFramework.BaseFramework & {
StateMachine: robloxStateMachine.RobloxStateMachine,
MaxSwings: valueObject.ValueObject<number>,
SwingIndex: valueObject.ValueObject<number>,
Hitboxes: {shapecastHitbox.Hitbox},
Replicate: (self: Melee, Data: {any}) -> (),
Config: typeof(defaultSettings),
}
return melee
💾 DataStore Module
Wraps ProfileStore and ReplicaService.
local replicatedStorage = game:GetService("ReplicatedStorage")
local players = game:GetService("Players")
local packages = replicatedStorage.Packages
local replicaServer = require(script.ReplicaServer)
local playerUtils = require(packages.PlayerUtils)
local profileStore = require(script.ProfileStore)
local janitor = require(packages.Janitor)
local signal = require(packages.Signal)
local dataStore = {
Active = {},
NewDataStore = signal.new() :: signal.Signal<string, dataStore>
}
dataStore.__index = dataStore
function dataStore.new<T>(name: string, template: T, createReplica: boolean?)
local self = setmetatable({}, dataStore)
self.Name = name
self.Janitor = janitor.new()
self.ProfileLoaded = self.Janitor:Add(signal.new()) :: signal.Signal<Player, profileStore.Profile<T>, replicaServer.Replica>
self.ProfileReleasing = self.Janitor:Add(signal.new()) :: signal.Signal<Player, profileStore.Profile<T>>
self.Profiles = {}
self.Store = profileStore.New(name, template)
if createReplica then
self.ReplicaToken = replicaServer.Token(name)
end
self.Janitor:Add(
playerUtils.observePlayers(nil, function(player: Player, playerJanitor)
local profile = playerJanitor:Add(
self.Store:StartSessionAsync(`{player.UserId}`, {
Cancel = function()
return not player:IsDescendantOf(players)
end,
}), "EndSession"
)
if profile then
profile:AddUserId(player.UserId)
profile:Reconcile()
playerJanitor:Add(function()
self.ProfileReleasing:Fire(player, profile)
end)
profile.OnSessionEnd:Connect(function()
self.Profiles[player] = nil
player:Kick("Session end - Please rejoin")
end)
if player:IsDescendantOf(players) then
self.Profiles[player] = {
Profile = profile,
}
if createReplica then
local replica = replicaServer.New({
Token = self.ReplicaToken,
Data = profile.Data
})
self.Profiles[player].Replica = replica
replica:Subscribe(player)
end
self.ProfileLoaded:Fire(player, profile, self.Profiles[player].Replica)
else
profile:EndSession()
end
else
player:Kick("Failed to load data - Please rejoin")
end
end)
)
dataStore.Active[name] = self
dataStore.NewDataStore:Fire(self.Name, self)
return self
end
function dataStore.GetProfile(self: dataStore, player: Player)
return self.Profiles[player]
end
function dataStore.Destroy(self: dataStore)
self.Janitor:Destroy()
dataStore.Active[self.Name] = nil
setmetatable(self, nil)
table.clear(self)
end
function dataStore.Get(name: string)
local target = dataStore.Active[name]
if not target then
local thread = coroutine.running()
local addedConnection
local startTime = os.clock()
task.spawn(function()
repeat
task.wait()
until os.clock() - startTime >= 5 or target ~= nil
if coroutine.status(thread) == "suspended" then
coroutine.resume(thread)
end
end)
addedConnection = dataStore.NewDataStore:Connect(function(_name: string, _dataStore)
if _name ~= name then
return
end
target = _dataStore
addedConnection:Disconnect()
if coroutine.status(thread) == "suspended" then
coroutine.resume(thread)
end
end)
coroutine.yield()
return target :: dataStore
end
return target
end
function dataStore.GetProfileFromDataStore(player: Player, name: string)
return dataStore.Get(name):GetProfile(player)
end
export type dataStore = typeof(dataStore.new())
return dataStore
Discord:
renkamens