--!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,
	},
}
