mirror of
				https://github.com/Ukendio/jecs.git
				synced 2025-11-03 18:39:19 +00:00 
			
		
		
		
	Rework observers addon interface
This commit is contained in:
		
							parent
							
								
									35b5f04a7c
								
							
						
					
					
						commit
						56b52286b8
					
				
					 5 changed files with 61 additions and 780 deletions
				
			
		| 
						 | 
				
			
			@ -1,26 +1,22 @@
 | 
			
		|||
local jecs = require("@jecs")
 | 
			
		||||
 | 
			
		||||
type Observer = {
 | 
			
		||||
	callback: (jecs.Entity) -> (),
 | 
			
		||||
	query: jecs.Query<...any>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Monitor = {
 | 
			
		||||
	callback: (jecs.Entity, jecs.Entity) -> (),
 | 
			
		||||
	query: jecs.Query<any>
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export type PatchedWorld = jecs.World & {
 | 
			
		||||
	added: <T>(PatchedWorld, jecs.Id<T>, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (),
 | 
			
		||||
	removed: <T>(PatchedWorld, jecs.Id<T>, (e: jecs.Entity, id: jecs.Id) -> ()) -> () -> (),
 | 
			
		||||
	changed: <T>(PatchedWorld, jecs.Id<T>, (e: jecs.Entity, id: jecs.Id, value: T) -> ()) -> () -> (),
 | 
			
		||||
	observer: (PatchedWorld, Observer) -> (),
 | 
			
		||||
	monitor: (PatchedWorld, Monitor) -> (),
 | 
			
		||||
	observer: (
 | 
			
		||||
		PatchedWorld,
 | 
			
		||||
		any,
 | 
			
		||||
		(jecs.Entity) -> ()
 | 
			
		||||
	) -> (),
 | 
			
		||||
	monitor: (
 | 
			
		||||
		PatchedWorld,
 | 
			
		||||
		any,
 | 
			
		||||
		(jecs.Entity, jecs.Id) -> ()
 | 
			
		||||
	) -> ()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local function observers_new(world, description)
 | 
			
		||||
	local query = description.query
 | 
			
		||||
	local callback = description.callback
 | 
			
		||||
local function observers_new(world, query, callback)
 | 
			
		||||
	local terms = query.filter_with :: { jecs.Id }
 | 
			
		||||
	if not terms then
 | 
			
		||||
		local ids = query.ids
 | 
			
		||||
| 
						 | 
				
			
			@ -94,9 +90,7 @@ local function join(world, component)
 | 
			
		|||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function monitors_new(world, description)
 | 
			
		||||
	local query = description.query
 | 
			
		||||
	local callback = description.callback
 | 
			
		||||
local function monitors_new(world, query, callback)
 | 
			
		||||
	local terms = query.filter_with :: { jecs.Id }
 | 
			
		||||
	if not terms then
 | 
			
		||||
		local ids = query.ids
 | 
			
		||||
| 
						 | 
				
			
			@ -131,7 +125,8 @@ local function monitors_new(world, description)
 | 
			
		|||
		local archetype = r.archetype
 | 
			
		||||
 | 
			
		||||
		if jecs.query_match(query, archetype) then
 | 
			
		||||
			callback(entity, jecs.OnRemove)
 | 
			
		||||
			local EcsOnRemove = jecs.OnRemove :: jecs.Id
 | 
			
		||||
			callback(entity, EcsOnRemove)
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -162,7 +157,7 @@ local function observers_add(world: jecs.World): PatchedWorld
 | 
			
		|||
			listeners = {}
 | 
			
		||||
			signals.added[component] = listeners
 | 
			
		||||
 | 
			
		||||
			local function on_add(entity: number, id: number, value: any)
 | 
			
		||||
			local function on_add(entity, id, value)
 | 
			
		||||
				for _, listener in listeners :: any do
 | 
			
		||||
					listener(entity, id, value)
 | 
			
		||||
				end
 | 
			
		||||
| 
						 | 
				
			
			@ -170,14 +165,15 @@ local function observers_add(world: jecs.World): PatchedWorld
 | 
			
		|||
			local existing_hook = world:get(component, jecs.OnAdd)
 | 
			
		||||
			if existing_hook then
 | 
			
		||||
				table.insert(listeners, existing_hook)
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			local idr = world.component_index[component]
 | 
			
		||||
			if idr then
 | 
			
		||||
				idr.hooks.on_add = on_add
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			else
 | 
			
		||||
				world:set(component, jecs.OnAdd, on_add)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		table.insert(listeners, fn)
 | 
			
		||||
		return function()
 | 
			
		||||
			local n = #listeners
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +192,7 @@ local function observers_add(world: jecs.World): PatchedWorld
 | 
			
		|||
		if not listeners then
 | 
			
		||||
			listeners = {}
 | 
			
		||||
			signals.emplaced[component] = listeners
 | 
			
		||||
			local function on_change(entity: number, id: number, value: any)
 | 
			
		||||
			local function on_change(entity, id, value: any)
 | 
			
		||||
				for _, listener in listeners :: any do
 | 
			
		||||
					listener(entity, id, value)
 | 
			
		||||
				end
 | 
			
		||||
| 
						 | 
				
			
			@ -204,13 +200,14 @@ local function observers_add(world: jecs.World): PatchedWorld
 | 
			
		|||
			local existing_hook = world:get(component, jecs.OnChange)
 | 
			
		||||
			if existing_hook then
 | 
			
		||||
				table.insert(listeners, existing_hook)
 | 
			
		||||
			end
 | 
			
		||||
			local idr = world.component_index[component]
 | 
			
		||||
			if idr then
 | 
			
		||||
				idr.hooks.on_change = on_change
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
			else
 | 
			
		||||
				world:set(component, jecs.OnChange, on_change)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
		table.insert(listeners, fn)
 | 
			
		||||
		return function()
 | 
			
		||||
			local n = #listeners
 | 
			
		||||
| 
						 | 
				
			
			@ -229,23 +226,26 @@ local function observers_add(world: jecs.World): PatchedWorld
 | 
			
		|||
		if not listeners then
 | 
			
		||||
			listeners = {}
 | 
			
		||||
			signals.removed[component] = listeners
 | 
			
		||||
			local function on_remove(entity: number, id: number, value: any)
 | 
			
		||||
			local function on_remove(entity, id)
 | 
			
		||||
				for _, listener in listeners :: any do
 | 
			
		||||
					listener(entity, id, value)
 | 
			
		||||
					listener(entity, id)
 | 
			
		||||
				end
 | 
			
		||||
			end
 | 
			
		||||
			local existing_hook = world:get(component, jecs.OnRemove)
 | 
			
		||||
			if existing_hook then
 | 
			
		||||
				table.insert(listeners, existing_hook)
 | 
			
		||||
			end
 | 
			
		||||
 | 
			
		||||
			local idr = world.component_index[component]
 | 
			
		||||
			if idr then
 | 
			
		||||
				idr.hooks.on_remove = on_remove
 | 
			
		||||
			else
 | 
			
		||||
				world:set(component, jecs.OnRemove, on_remove)
 | 
			
		||||
			end
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
			world:set(component, jecs.OnRemove, on_remove)
 | 
			
		||||
		end
 | 
			
		||||
		table.insert(listeners, fn)
 | 
			
		||||
 | 
			
		||||
		return function()
 | 
			
		||||
			local n = #listeners
 | 
			
		||||
			local i = table.find(listeners, fn)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,18 +0,0 @@
 | 
			
		|||
option ClientOutput = "../net/client.luau"
 | 
			
		||||
option ServerOutput = "../net/server.luau"
 | 
			
		||||
 | 
			
		||||
event UpdateTransform {
 | 
			
		||||
    From: Server,
 | 
			
		||||
    Type: Unreliable,
 | 
			
		||||
    Call: SingleSync,
 | 
			
		||||
    Poll: true,
 | 
			
		||||
    Data: (f64, CFrame)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
event SpawnMob {
 | 
			
		||||
    From: Server,
 | 
			
		||||
    Type: Reliable,
 | 
			
		||||
    Call: SingleSync,
 | 
			
		||||
    Poll: true,
 | 
			
		||||
    Data: (f64, CFrame, u8)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,336 +0,0 @@
 | 
			
		|||
--!strict
 | 
			
		||||
--!native
 | 
			
		||||
--!optimize 2
 | 
			
		||||
--!nolint LocalShadow
 | 
			
		||||
--#selene: allow(shadowing)
 | 
			
		||||
-- File generated by Blink v0.14.1 (https://github.com/1Axen/Blink)
 | 
			
		||||
-- This file is not meant to be edited
 | 
			
		||||
 | 
			
		||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
 | 
			
		||||
local RunService = game:GetService("RunService")
 | 
			
		||||
 | 
			
		||||
if not RunService:IsClient() then
 | 
			
		||||
	error("Client network module can only be required from the client.")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local Reliable: RemoteEvent = ReplicatedStorage:WaitForChild("BLINK_RELIABLE_REMOTE") :: RemoteEvent
 | 
			
		||||
local Unreliable: UnreliableRemoteEvent =
 | 
			
		||||
	ReplicatedStorage:WaitForChild("BLINK_UNRELIABLE_REMOTE") :: UnreliableRemoteEvent
 | 
			
		||||
 | 
			
		||||
local Invocations = 0
 | 
			
		||||
 | 
			
		||||
local SendSize = 64
 | 
			
		||||
local SendOffset = 0
 | 
			
		||||
local SendCursor = 0
 | 
			
		||||
local SendBuffer = buffer.create(64)
 | 
			
		||||
local SendInstances = {}
 | 
			
		||||
 | 
			
		||||
local RecieveCursor = 0
 | 
			
		||||
local RecieveBuffer = buffer.create(64)
 | 
			
		||||
 | 
			
		||||
local RecieveInstances = {}
 | 
			
		||||
local RecieveInstanceCursor = 0
 | 
			
		||||
 | 
			
		||||
type Entry = {
 | 
			
		||||
	value: any,
 | 
			
		||||
	next: Entry?,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Queue = {
 | 
			
		||||
	head: Entry?,
 | 
			
		||||
	tail: Entry?,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BufferSave = {
 | 
			
		||||
	Size: number,
 | 
			
		||||
	Cursor: number,
 | 
			
		||||
	Buffer: buffer,
 | 
			
		||||
	Instances: { Instance },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local function Read(Bytes: number)
 | 
			
		||||
	local Offset = RecieveCursor
 | 
			
		||||
	RecieveCursor += Bytes
 | 
			
		||||
	return Offset
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Save(): BufferSave
 | 
			
		||||
	return {
 | 
			
		||||
		Size = SendSize,
 | 
			
		||||
		Cursor = SendCursor,
 | 
			
		||||
		Buffer = SendBuffer,
 | 
			
		||||
		Instances = SendInstances,
 | 
			
		||||
	}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Load(Save: BufferSave?)
 | 
			
		||||
	if Save then
 | 
			
		||||
		SendSize = Save.Size
 | 
			
		||||
		SendCursor = Save.Cursor
 | 
			
		||||
		SendOffset = Save.Cursor
 | 
			
		||||
		SendBuffer = Save.Buffer
 | 
			
		||||
		SendInstances = Save.Instances
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	SendSize = 64
 | 
			
		||||
	SendCursor = 0
 | 
			
		||||
	SendOffset = 0
 | 
			
		||||
	SendBuffer = buffer.create(64)
 | 
			
		||||
	SendInstances = {}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Invoke()
 | 
			
		||||
	if Invocations == 255 then
 | 
			
		||||
		Invocations = 0
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local Invocation = Invocations
 | 
			
		||||
	Invocations += 1
 | 
			
		||||
	return Invocation
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Allocate(Bytes: number)
 | 
			
		||||
	local InUse = (SendCursor + Bytes)
 | 
			
		||||
	if InUse > SendSize then
 | 
			
		||||
		--> Avoid resizing the buffer for every write
 | 
			
		||||
		while InUse > SendSize do
 | 
			
		||||
			SendSize *= 1.5
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local Buffer = buffer.create(SendSize)
 | 
			
		||||
		buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor)
 | 
			
		||||
		SendBuffer = Buffer
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	SendOffset = SendCursor
 | 
			
		||||
	SendCursor += Bytes
 | 
			
		||||
 | 
			
		||||
	return SendOffset
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function CreateQueue(): Queue
 | 
			
		||||
	return {
 | 
			
		||||
		head = nil,
 | 
			
		||||
		tail = nil,
 | 
			
		||||
	}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Pop(queue: Queue): any
 | 
			
		||||
	local head = queue.head
 | 
			
		||||
	if head == nil then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	queue.head = head.next
 | 
			
		||||
	return head.value
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Push(queue: Queue, value: any)
 | 
			
		||||
	local entry: Entry = {
 | 
			
		||||
		value = value,
 | 
			
		||||
		next = nil,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if queue.tail ~= nil then
 | 
			
		||||
		queue.tail.next = entry
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	queue.tail = entry
 | 
			
		||||
 | 
			
		||||
	if queue.head == nil then
 | 
			
		||||
		queue.head = entry
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local Types = {}
 | 
			
		||||
local Calls = table.create(256)
 | 
			
		||||
 | 
			
		||||
local Events: any = {
 | 
			
		||||
	Reliable = table.create(256),
 | 
			
		||||
	Unreliable = table.create(256),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local Queue: any = {
 | 
			
		||||
	Reliable = table.create(256),
 | 
			
		||||
	Unreliable = table.create(256),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
Queue.Unreliable[0] = CreateQueue()
 | 
			
		||||
Queue.Reliable[0] = CreateQueue()
 | 
			
		||||
 | 
			
		||||
function Types.ReadEVENT_UpdateTransform(): (number, CFrame)
 | 
			
		||||
	-- Read BLOCK: 32 bytes
 | 
			
		||||
	local BLOCK_START = Read(32)
 | 
			
		||||
	local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
	local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8)
 | 
			
		||||
	local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12)
 | 
			
		||||
	local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16)
 | 
			
		||||
	local Position = Vector3.new(X, Y, Z)
 | 
			
		||||
	local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20)
 | 
			
		||||
	local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24)
 | 
			
		||||
	local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28)
 | 
			
		||||
	local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ)
 | 
			
		||||
	return Value1, Value2
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Types.WriteEVENT_UpdateTransform(Value1: number, Value2: CFrame): ()
 | 
			
		||||
	-- Allocate BLOCK: 33 bytes
 | 
			
		||||
	local BLOCK_START = Allocate(33)
 | 
			
		||||
	buffer.writeu8(SendBuffer, BLOCK_START + 0, 0)
 | 
			
		||||
	buffer.writef64(SendBuffer, BLOCK_START + 1, Value1)
 | 
			
		||||
	local Vector = Value2.Position
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z)
 | 
			
		||||
	local rX, rY, rZ = Value2:ToOrientation()
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 21, rX)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 25, rY)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 29, rZ)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Types.ReadEVENT_SpawnMob(): (number, CFrame, number)
 | 
			
		||||
	-- Read BLOCK: 33 bytes
 | 
			
		||||
	local BLOCK_START = Read(33)
 | 
			
		||||
	local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
	local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8)
 | 
			
		||||
	local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12)
 | 
			
		||||
	local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16)
 | 
			
		||||
	local Position = Vector3.new(X, Y, Z)
 | 
			
		||||
	local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20)
 | 
			
		||||
	local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24)
 | 
			
		||||
	local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28)
 | 
			
		||||
	local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ)
 | 
			
		||||
	local Value3 = buffer.readu8(RecieveBuffer, BLOCK_START + 32)
 | 
			
		||||
	return Value1, Value2, Value3
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Types.WriteEVENT_SpawnMob(Value1: number, Value2: CFrame, Value3: number): ()
 | 
			
		||||
	-- Allocate BLOCK: 34 bytes
 | 
			
		||||
	local BLOCK_START = Allocate(34)
 | 
			
		||||
	buffer.writeu8(SendBuffer, BLOCK_START + 0, 0)
 | 
			
		||||
	buffer.writef64(SendBuffer, BLOCK_START + 1, Value1)
 | 
			
		||||
	local Vector = Value2.Position
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z)
 | 
			
		||||
	local rX, rY, rZ = Value2:ToOrientation()
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 21, rX)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 25, rY)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 29, rZ)
 | 
			
		||||
	buffer.writeu8(SendBuffer, BLOCK_START + 33, Value3)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function StepReplication()
 | 
			
		||||
	if SendCursor <= 0 then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local Buffer = buffer.create(SendCursor)
 | 
			
		||||
	buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor)
 | 
			
		||||
	Reliable:FireServer(Buffer, SendInstances)
 | 
			
		||||
 | 
			
		||||
	SendSize = 64
 | 
			
		||||
	SendCursor = 0
 | 
			
		||||
	SendOffset = 0
 | 
			
		||||
	SendBuffer = buffer.create(64)
 | 
			
		||||
	table.clear(SendInstances)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local Elapsed = 0
 | 
			
		||||
RunService.Heartbeat:Connect(function(DeltaTime: number)
 | 
			
		||||
	Elapsed += DeltaTime
 | 
			
		||||
	if Elapsed >= (1 / 61) then
 | 
			
		||||
		Elapsed -= (1 / 61)
 | 
			
		||||
		StepReplication()
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
Reliable.OnClientEvent:Connect(function(Buffer: buffer, Instances: { Instance })
 | 
			
		||||
	RecieveCursor = 0
 | 
			
		||||
	RecieveBuffer = Buffer
 | 
			
		||||
	RecieveInstances = Instances
 | 
			
		||||
	RecieveInstanceCursor = 0
 | 
			
		||||
	local Size = buffer.len(RecieveBuffer)
 | 
			
		||||
	while RecieveCursor < Size do
 | 
			
		||||
		-- Read BLOCK: 1 bytes
 | 
			
		||||
		local BLOCK_START = Read(1)
 | 
			
		||||
		local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
		if Index == 0 then
 | 
			
		||||
			Push(Queue.Reliable[0], table.pack(Types.ReadEVENT_SpawnMob()))
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
Unreliable.OnClientEvent:Connect(function(Buffer: buffer, Instances: { Instance })
 | 
			
		||||
	RecieveCursor = 0
 | 
			
		||||
	RecieveBuffer = Buffer
 | 
			
		||||
	RecieveInstances = Instances
 | 
			
		||||
	RecieveInstanceCursor = 0
 | 
			
		||||
	local Size = buffer.len(RecieveBuffer)
 | 
			
		||||
	while RecieveCursor < Size do
 | 
			
		||||
		-- Read BLOCK: 1 bytes
 | 
			
		||||
		local BLOCK_START = Read(1)
 | 
			
		||||
		local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
		if Index == 0 then
 | 
			
		||||
			Push(Queue.Unreliable[0], table.pack(Types.ReadEVENT_UpdateTransform()))
 | 
			
		||||
		end
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return {
 | 
			
		||||
	StepReplication = StepReplication,
 | 
			
		||||
 | 
			
		||||
	UpdateTransform = {
 | 
			
		||||
		Iter = function(): () -> (number, number, CFrame)
 | 
			
		||||
			local index = 0
 | 
			
		||||
			local queue = Queue.Unreliable[0]
 | 
			
		||||
			return function(): (number, number, CFrame)
 | 
			
		||||
				index += 1
 | 
			
		||||
				local arguments = Pop(queue)
 | 
			
		||||
				if arguments ~= nil then
 | 
			
		||||
					return index, unpack(arguments, 1, arguments.n)
 | 
			
		||||
				end
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
		Next = function(): () -> (number, number, CFrame)
 | 
			
		||||
			local index = 0
 | 
			
		||||
			local queue = Queue.Unreliable[0]
 | 
			
		||||
			return function(): (number, number, CFrame)
 | 
			
		||||
				index += 1
 | 
			
		||||
				local arguments = Pop(queue)
 | 
			
		||||
				if arguments ~= nil then
 | 
			
		||||
					return index, unpack(arguments, 1, arguments.n)
 | 
			
		||||
				end
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
	},
 | 
			
		||||
	SpawnMob = {
 | 
			
		||||
		Iter = function(): () -> (number, number, CFrame, number)
 | 
			
		||||
			local index = 0
 | 
			
		||||
			local queue = Queue.Reliable[0]
 | 
			
		||||
			return function(): (number, number, CFrame, number)
 | 
			
		||||
				index += 1
 | 
			
		||||
				local arguments = Pop(queue)
 | 
			
		||||
				if arguments ~= nil then
 | 
			
		||||
					return index, unpack(arguments, 1, arguments.n)
 | 
			
		||||
				end
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
		Next = function(): () -> (number, number, CFrame, number)
 | 
			
		||||
			local index = 0
 | 
			
		||||
			local queue = Queue.Reliable[0]
 | 
			
		||||
			return function(): (number, number, CFrame, number)
 | 
			
		||||
				index += 1
 | 
			
		||||
				local arguments = Pop(queue)
 | 
			
		||||
				if arguments ~= nil then
 | 
			
		||||
					return index, unpack(arguments, 1, arguments.n)
 | 
			
		||||
				end
 | 
			
		||||
				return
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,372 +0,0 @@
 | 
			
		|||
--!strict
 | 
			
		||||
--!native
 | 
			
		||||
--!optimize 2
 | 
			
		||||
--!nolint LocalShadow
 | 
			
		||||
--#selene: allow(shadowing)
 | 
			
		||||
-- File generated by Blink v0.14.1 (https://github.com/1Axen/Blink)
 | 
			
		||||
-- This file is not meant to be edited
 | 
			
		||||
 | 
			
		||||
local Players = game:GetService("Players")
 | 
			
		||||
local ReplicatedStorage = game:GetService("ReplicatedStorage")
 | 
			
		||||
local RunService = game:GetService("RunService")
 | 
			
		||||
 | 
			
		||||
if not RunService:IsServer() then
 | 
			
		||||
	error("Server network module can only be required from the server.")
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local Reliable: RemoteEvent = ReplicatedStorage:FindFirstChild("BLINK_RELIABLE_REMOTE") :: RemoteEvent
 | 
			
		||||
if not Reliable then
 | 
			
		||||
	local RemoteEvent = Instance.new("RemoteEvent")
 | 
			
		||||
	RemoteEvent.Name = "BLINK_RELIABLE_REMOTE"
 | 
			
		||||
	RemoteEvent.Parent = ReplicatedStorage
 | 
			
		||||
	Reliable = RemoteEvent
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local Unreliable: UnreliableRemoteEvent =
 | 
			
		||||
	ReplicatedStorage:FindFirstChild("BLINK_UNRELIABLE_REMOTE") :: UnreliableRemoteEvent
 | 
			
		||||
if not Unreliable then
 | 
			
		||||
	local UnreliableRemoteEvent = Instance.new("UnreliableRemoteEvent")
 | 
			
		||||
	UnreliableRemoteEvent.Name = "BLINK_UNRELIABLE_REMOTE"
 | 
			
		||||
	UnreliableRemoteEvent.Parent = ReplicatedStorage
 | 
			
		||||
	Unreliable = UnreliableRemoteEvent
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local Invocations = 0
 | 
			
		||||
 | 
			
		||||
local SendSize = 64
 | 
			
		||||
local SendOffset = 0
 | 
			
		||||
local SendCursor = 0
 | 
			
		||||
local SendBuffer = buffer.create(64)
 | 
			
		||||
local SendInstances = {}
 | 
			
		||||
 | 
			
		||||
local RecieveCursor = 0
 | 
			
		||||
local RecieveBuffer = buffer.create(64)
 | 
			
		||||
 | 
			
		||||
local RecieveInstances = {}
 | 
			
		||||
local RecieveInstanceCursor = 0
 | 
			
		||||
 | 
			
		||||
type Entry = {
 | 
			
		||||
	value: any,
 | 
			
		||||
	next: Entry?,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Queue = {
 | 
			
		||||
	head: Entry?,
 | 
			
		||||
	tail: Entry?,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type BufferSave = {
 | 
			
		||||
	Size: number,
 | 
			
		||||
	Cursor: number,
 | 
			
		||||
	Buffer: buffer,
 | 
			
		||||
	Instances: { Instance },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local function Read(Bytes: number)
 | 
			
		||||
	local Offset = RecieveCursor
 | 
			
		||||
	RecieveCursor += Bytes
 | 
			
		||||
	return Offset
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Save(): BufferSave
 | 
			
		||||
	return {
 | 
			
		||||
		Size = SendSize,
 | 
			
		||||
		Cursor = SendCursor,
 | 
			
		||||
		Buffer = SendBuffer,
 | 
			
		||||
		Instances = SendInstances,
 | 
			
		||||
	}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Load(Save: BufferSave?)
 | 
			
		||||
	if Save then
 | 
			
		||||
		SendSize = Save.Size
 | 
			
		||||
		SendCursor = Save.Cursor
 | 
			
		||||
		SendOffset = Save.Cursor
 | 
			
		||||
		SendBuffer = Save.Buffer
 | 
			
		||||
		SendInstances = Save.Instances
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	SendSize = 64
 | 
			
		||||
	SendCursor = 0
 | 
			
		||||
	SendOffset = 0
 | 
			
		||||
	SendBuffer = buffer.create(64)
 | 
			
		||||
	SendInstances = {}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Invoke()
 | 
			
		||||
	if Invocations == 255 then
 | 
			
		||||
		Invocations = 0
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	local Invocation = Invocations
 | 
			
		||||
	Invocations += 1
 | 
			
		||||
	return Invocation
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Allocate(Bytes: number)
 | 
			
		||||
	local InUse = (SendCursor + Bytes)
 | 
			
		||||
	if InUse > SendSize then
 | 
			
		||||
		--> Avoid resizing the buffer for every write
 | 
			
		||||
		while InUse > SendSize do
 | 
			
		||||
			SendSize *= 1.5
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local Buffer = buffer.create(SendSize)
 | 
			
		||||
		buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor)
 | 
			
		||||
		SendBuffer = Buffer
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	SendOffset = SendCursor
 | 
			
		||||
	SendCursor += Bytes
 | 
			
		||||
 | 
			
		||||
	return SendOffset
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function CreateQueue(): Queue
 | 
			
		||||
	return {
 | 
			
		||||
		head = nil,
 | 
			
		||||
		tail = nil,
 | 
			
		||||
	}
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Pop(queue: Queue): any
 | 
			
		||||
	local head = queue.head
 | 
			
		||||
	if head == nil then
 | 
			
		||||
		return
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	queue.head = head.next
 | 
			
		||||
	return head.value
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local function Push(queue: Queue, value: any)
 | 
			
		||||
	local entry: Entry = {
 | 
			
		||||
		value = value,
 | 
			
		||||
		next = nil,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if queue.tail ~= nil then
 | 
			
		||||
		queue.tail.next = entry
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	queue.tail = entry
 | 
			
		||||
 | 
			
		||||
	if queue.head == nil then
 | 
			
		||||
		queue.head = entry
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local Types = {}
 | 
			
		||||
local Calls = table.create(256)
 | 
			
		||||
 | 
			
		||||
local Events: any = {
 | 
			
		||||
	Reliable = table.create(256),
 | 
			
		||||
	Unreliable = table.create(256),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
local Queue: any = {
 | 
			
		||||
	Reliable = table.create(256),
 | 
			
		||||
	Unreliable = table.create(256),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function Types.ReadEVENT_UpdateTransform(): (number, CFrame)
 | 
			
		||||
	-- Read BLOCK: 32 bytes
 | 
			
		||||
	local BLOCK_START = Read(32)
 | 
			
		||||
	local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
	local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8)
 | 
			
		||||
	local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12)
 | 
			
		||||
	local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16)
 | 
			
		||||
	local Position = Vector3.new(X, Y, Z)
 | 
			
		||||
	local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20)
 | 
			
		||||
	local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24)
 | 
			
		||||
	local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28)
 | 
			
		||||
	local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ)
 | 
			
		||||
	return Value1, Value2
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Types.WriteEVENT_UpdateTransform(Value1: number, Value2: CFrame): ()
 | 
			
		||||
	-- Allocate BLOCK: 33 bytes
 | 
			
		||||
	local BLOCK_START = Allocate(33)
 | 
			
		||||
	buffer.writeu8(SendBuffer, BLOCK_START + 0, 0)
 | 
			
		||||
	buffer.writef64(SendBuffer, BLOCK_START + 1, Value1)
 | 
			
		||||
	local Vector = Value2.Position
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z)
 | 
			
		||||
	local rX, rY, rZ = Value2:ToOrientation()
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 21, rX)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 25, rY)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 29, rZ)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Types.ReadEVENT_SpawnMob(): (number, CFrame, number)
 | 
			
		||||
	-- Read BLOCK: 33 bytes
 | 
			
		||||
	local BLOCK_START = Read(33)
 | 
			
		||||
	local Value1 = buffer.readf64(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
	local X = buffer.readf32(RecieveBuffer, BLOCK_START + 8)
 | 
			
		||||
	local Y = buffer.readf32(RecieveBuffer, BLOCK_START + 12)
 | 
			
		||||
	local Z = buffer.readf32(RecieveBuffer, BLOCK_START + 16)
 | 
			
		||||
	local Position = Vector3.new(X, Y, Z)
 | 
			
		||||
	local rX = buffer.readf32(RecieveBuffer, BLOCK_START + 20)
 | 
			
		||||
	local rY = buffer.readf32(RecieveBuffer, BLOCK_START + 24)
 | 
			
		||||
	local rZ = buffer.readf32(RecieveBuffer, BLOCK_START + 28)
 | 
			
		||||
	local Value2 = CFrame.new(Position) * CFrame.fromOrientation(rX, rY, rZ)
 | 
			
		||||
	local Value3 = buffer.readu8(RecieveBuffer, BLOCK_START + 32)
 | 
			
		||||
	return Value1, Value2, Value3
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
function Types.WriteEVENT_SpawnMob(Value1: number, Value2: CFrame, Value3: number): ()
 | 
			
		||||
	-- Allocate BLOCK: 34 bytes
 | 
			
		||||
	local BLOCK_START = Allocate(34)
 | 
			
		||||
	buffer.writeu8(SendBuffer, BLOCK_START + 0, 0)
 | 
			
		||||
	buffer.writef64(SendBuffer, BLOCK_START + 1, Value1)
 | 
			
		||||
	local Vector = Value2.Position
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 9, Vector.X)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 13, Vector.Y)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 17, Vector.Z)
 | 
			
		||||
	local rX, rY, rZ = Value2:ToOrientation()
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 21, rX)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 25, rY)
 | 
			
		||||
	buffer.writef32(SendBuffer, BLOCK_START + 29, rZ)
 | 
			
		||||
	buffer.writeu8(SendBuffer, BLOCK_START + 33, Value3)
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
local PlayersMap: { [Player]: BufferSave } = {}
 | 
			
		||||
 | 
			
		||||
Players.PlayerRemoving:Connect(function(Player)
 | 
			
		||||
	PlayersMap[Player] = nil
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
local function StepReplication()
 | 
			
		||||
	for Player, Send in PlayersMap do
 | 
			
		||||
		if Send.Cursor <= 0 then
 | 
			
		||||
			continue
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		local Buffer = buffer.create(Send.Cursor)
 | 
			
		||||
		buffer.copy(Buffer, 0, Send.Buffer, 0, Send.Cursor)
 | 
			
		||||
		Reliable:FireClient(Player, Buffer, Send.Instances)
 | 
			
		||||
 | 
			
		||||
		Send.Size = 64
 | 
			
		||||
		Send.Cursor = 0
 | 
			
		||||
		Send.Buffer = buffer.create(64)
 | 
			
		||||
		table.clear(Send.Instances)
 | 
			
		||||
	end
 | 
			
		||||
end
 | 
			
		||||
 | 
			
		||||
RunService.Heartbeat:Connect(StepReplication)
 | 
			
		||||
 | 
			
		||||
Reliable.OnServerEvent:Connect(function(Player: Player, Buffer: buffer, Instances: { Instance })
 | 
			
		||||
	RecieveCursor = 0
 | 
			
		||||
	RecieveBuffer = Buffer
 | 
			
		||||
	RecieveInstances = Instances
 | 
			
		||||
	RecieveInstanceCursor = 0
 | 
			
		||||
	local Size = buffer.len(RecieveBuffer)
 | 
			
		||||
	while RecieveCursor < Size do
 | 
			
		||||
		-- Read BLOCK: 1 bytes
 | 
			
		||||
		local BLOCK_START = Read(1)
 | 
			
		||||
		local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
Unreliable.OnServerEvent:Connect(function(Player: Player, Buffer: buffer, Instances: { Instance })
 | 
			
		||||
	RecieveCursor = 0
 | 
			
		||||
	RecieveBuffer = Buffer
 | 
			
		||||
	RecieveInstances = Instances
 | 
			
		||||
	RecieveInstanceCursor = 0
 | 
			
		||||
	local Size = buffer.len(RecieveBuffer)
 | 
			
		||||
	while RecieveCursor < Size do
 | 
			
		||||
		-- Read BLOCK: 1 bytes
 | 
			
		||||
		local BLOCK_START = Read(1)
 | 
			
		||||
		local Index = buffer.readu8(RecieveBuffer, BLOCK_START + 0)
 | 
			
		||||
	end
 | 
			
		||||
end)
 | 
			
		||||
 | 
			
		||||
return {
 | 
			
		||||
	StepReplication = StepReplication,
 | 
			
		||||
 | 
			
		||||
	UpdateTransform = {
 | 
			
		||||
		Fire = function(Player: Player, Value1: number, Value2: CFrame): ()
 | 
			
		||||
			Load()
 | 
			
		||||
			Types.WriteEVENT_UpdateTransform(Value1, Value2)
 | 
			
		||||
			local Buffer = buffer.create(SendCursor)
 | 
			
		||||
			buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor)
 | 
			
		||||
			Unreliable:FireClient(Player, Buffer, SendInstances)
 | 
			
		||||
		end,
 | 
			
		||||
		FireAll = function(Value1: number, Value2: CFrame): ()
 | 
			
		||||
			Load()
 | 
			
		||||
			Types.WriteEVENT_UpdateTransform(Value1, Value2)
 | 
			
		||||
			local Buffer = buffer.create(SendCursor)
 | 
			
		||||
			buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor)
 | 
			
		||||
			Unreliable:FireAllClients(Buffer, SendInstances)
 | 
			
		||||
		end,
 | 
			
		||||
		FireList = function(List: { Player }, Value1: number, Value2: CFrame): ()
 | 
			
		||||
			Load()
 | 
			
		||||
			Types.WriteEVENT_UpdateTransform(Value1, Value2)
 | 
			
		||||
			local Buffer = buffer.create(SendCursor)
 | 
			
		||||
			buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor)
 | 
			
		||||
			for _, Player in List do
 | 
			
		||||
				Unreliable:FireClient(Player, Buffer, SendInstances)
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
		FireExcept = function(Except: Player, Value1: number, Value2: CFrame): ()
 | 
			
		||||
			Load()
 | 
			
		||||
			Types.WriteEVENT_UpdateTransform(Value1, Value2)
 | 
			
		||||
			local Buffer = buffer.create(SendCursor)
 | 
			
		||||
			buffer.copy(Buffer, 0, SendBuffer, 0, SendCursor)
 | 
			
		||||
			for _, Player in Players:GetPlayers() do
 | 
			
		||||
				if Player == Except then
 | 
			
		||||
					continue
 | 
			
		||||
				end
 | 
			
		||||
				Unreliable:FireClient(Player, Buffer, SendInstances)
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
	},
 | 
			
		||||
	SpawnMob = {
 | 
			
		||||
		Fire = function(Player: Player, Value1: number, Value2: CFrame, Value3: number): ()
 | 
			
		||||
			Load(PlayersMap[Player])
 | 
			
		||||
			Types.WriteEVENT_SpawnMob(Value1, Value2, Value3)
 | 
			
		||||
			PlayersMap[Player] = Save()
 | 
			
		||||
		end,
 | 
			
		||||
		FireAll = function(Value1: number, Value2: CFrame, Value3: number): ()
 | 
			
		||||
			Load()
 | 
			
		||||
			Types.WriteEVENT_SpawnMob(Value1, Value2, Value3)
 | 
			
		||||
			local Buffer, Size, Instances = SendBuffer, SendCursor, SendInstances
 | 
			
		||||
			for _, Player in Players:GetPlayers() do
 | 
			
		||||
				Load(PlayersMap[Player])
 | 
			
		||||
				local Position = Allocate(Size)
 | 
			
		||||
				buffer.copy(SendBuffer, Position, Buffer, 0, Size)
 | 
			
		||||
				table.move(Instances, 1, #Instances, #SendInstances + 1, SendInstances)
 | 
			
		||||
				PlayersMap[Player] = Save()
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
		FireList = function(List: { Player }, Value1: number, Value2: CFrame, Value3: number): ()
 | 
			
		||||
			Load()
 | 
			
		||||
			Types.WriteEVENT_SpawnMob(Value1, Value2, Value3)
 | 
			
		||||
			local Buffer, Size, Instances = SendBuffer, SendCursor, SendInstances
 | 
			
		||||
			for _, Player in List do
 | 
			
		||||
				Load(PlayersMap[Player])
 | 
			
		||||
				local Position = Allocate(Size)
 | 
			
		||||
				buffer.copy(SendBuffer, Position, Buffer, 0, Size)
 | 
			
		||||
				table.move(Instances, 1, #Instances, #SendInstances + 1, SendInstances)
 | 
			
		||||
				PlayersMap[Player] = Save()
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
		FireExcept = function(Except: Player, Value1: number, Value2: CFrame, Value3: number): ()
 | 
			
		||||
			Load()
 | 
			
		||||
			Types.WriteEVENT_SpawnMob(Value1, Value2, Value3)
 | 
			
		||||
			local Buffer, Size, Instances = SendBuffer, SendCursor, SendInstances
 | 
			
		||||
			for _, Player in Players:GetPlayers() do
 | 
			
		||||
				if Player == Except then
 | 
			
		||||
					continue
 | 
			
		||||
				end
 | 
			
		||||
				Load(PlayersMap[Player])
 | 
			
		||||
				local Position = Allocate(Size)
 | 
			
		||||
				buffer.copy(SendBuffer, Position, Buffer, 0, Size)
 | 
			
		||||
				table.move(Instances, 1, #Instances, #SendInstances + 1, SendInstances)
 | 
			
		||||
				PlayersMap[Player] = Save()
 | 
			
		||||
			end
 | 
			
		||||
		end,
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -4,10 +4,24 @@ local test = testkit.test()
 | 
			
		|||
local CASE, TEST, FINISH, CHECK = test.CASE, test.TEST, test.FINISH, test.CHECK
 | 
			
		||||
local observers_add = require("@addons/observers")
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
TEST("addons/observers", function()
 | 
			
		||||
	local world = observers_add(jecs.world())
 | 
			
		||||
 | 
			
		||||
	do CASE "Should work even if set after the component has been used"
 | 
			
		||||
		local A = world:component()
 | 
			
		||||
 | 
			
		||||
		world:set(world:entity(), A, 1)
 | 
			
		||||
		local ran = false
 | 
			
		||||
		world:added(A, function()
 | 
			
		||||
			ran = true
 | 
			
		||||
		end)
 | 
			
		||||
 | 
			
		||||
		local entity = world:entity()
 | 
			
		||||
		world:set(entity, A, 2)
 | 
			
		||||
 | 
			
		||||
		CHECK(ran)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	do CASE "Should not override hook"
 | 
			
		||||
		local A = world:component()
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -17,12 +31,12 @@ TEST("addons/observers", function()
 | 
			
		|||
		end
 | 
			
		||||
 | 
			
		||||
		world:set(A, jecs.OnAdd, counter)
 | 
			
		||||
		world:set(world:entity(), A, true)
 | 
			
		||||
		CHECK(count == 1)
 | 
			
		||||
		world:added(A, counter)
 | 
			
		||||
		world:set(world:entity(), A, true)
 | 
			
		||||
		CHECK(count == 2)
 | 
			
		||||
		world:set(world:entity(), A, true)
 | 
			
		||||
 | 
			
		||||
		CHECK(count == 3)
 | 
			
		||||
		CHECK(count == 4)
 | 
			
		||||
	end
 | 
			
		||||
 | 
			
		||||
	do CASE "Ensure ordering between signals and observers"
 | 
			
		||||
| 
						 | 
				
			
			@ -33,10 +47,8 @@ TEST("addons/observers", function()
 | 
			
		|||
		local function counter()
 | 
			
		||||
			count += 1
 | 
			
		||||
		end
 | 
			
		||||
		world:observer({
 | 
			
		||||
			callback = counter,
 | 
			
		||||
			query = world:query(A, B),
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		world:observer(world:query(A, B), counter)
 | 
			
		||||
 | 
			
		||||
		world:added(A, counter)
 | 
			
		||||
		world:added(A, counter)
 | 
			
		||||
| 
						 | 
				
			
			@ -56,10 +68,8 @@ TEST("addons/observers", function()
 | 
			
		|||
		local function counter()
 | 
			
		||||
			count += 1
 | 
			
		||||
		end
 | 
			
		||||
		world:observer({
 | 
			
		||||
			query = world:query(A),
 | 
			
		||||
			callback = counter
 | 
			
		||||
		})
 | 
			
		||||
 | 
			
		||||
		world:observer(world:query(A), counter)
 | 
			
		||||
 | 
			
		||||
		local e = world:entity()
 | 
			
		||||
		world:set(e, A, true)
 | 
			
		||||
| 
						 | 
				
			
			@ -79,10 +89,7 @@ TEST("addons/observers", function()
 | 
			
		|||
			count += 1
 | 
			
		||||
		end
 | 
			
		||||
 | 
			
		||||
		world:monitor({
 | 
			
		||||
			query = world:query(A),
 | 
			
		||||
			callback = counter
 | 
			
		||||
		})
 | 
			
		||||
		world:monitor(world:query(A), counter)
 | 
			
		||||
 | 
			
		||||
		local e = world:entity()
 | 
			
		||||
		world:set(e, A, true)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue