@quenty/clipcharacters 12.4.0 → 12.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/package.json +11 -3
- package/src/Client/ClipCharacters.lua +80 -0
- package/src/Client/ClipCharactersServiceClient.lua +47 -0
- package/src/Server/ClipCharactersService.lua +32 -0
- package/src/Shared/ClipCharactersServiceConstants.lua +11 -0
- package/test/default.project.json +22 -0
- package/test/scripts/Client/ClientMain.client.lua +12 -0
- package/test/scripts/Server/ServerMain.server.lua +12 -0
- package/src/Shared/ClipCharacters.lua +0 -141
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,17 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [12.4.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/clipcharacters@12.4.0...@quenty/clipcharacters@12.4.1) (2024-05-14)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Bug Fixes
|
|
10
|
+
|
|
11
|
+
* Update ClipCharacters to act as a service ([b6651b6](https://github.com/Quenty/NevermoreEngine/commit/b6651b6d01375857e022641f62461e179292a97c))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
6
17
|
# [12.4.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/clipcharacters@12.3.0...@quenty/clipcharacters@12.4.0) (2024-05-09)
|
|
7
18
|
|
|
8
19
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quenty/clipcharacters",
|
|
3
|
-
"version": "12.4.
|
|
3
|
+
"version": "12.4.1",
|
|
4
4
|
"description": "Clip characters locally on the client of other clients so they don't interfer with physics.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Roblox",
|
|
@@ -25,12 +25,20 @@
|
|
|
25
25
|
"Quenty"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"@quenty/baseobject": "^10.3.0",
|
|
29
|
+
"@quenty/brio": "^14.3.0",
|
|
30
|
+
"@quenty/characterutils": "^12.3.0",
|
|
28
31
|
"@quenty/loader": "^10.3.0",
|
|
29
32
|
"@quenty/maid": "^3.2.0",
|
|
30
|
-
"@quenty/
|
|
33
|
+
"@quenty/playerutils": "^8.3.0",
|
|
34
|
+
"@quenty/remoting": "^12.4.0",
|
|
35
|
+
"@quenty/servicebag": "^11.4.0",
|
|
36
|
+
"@quenty/statestack": "^14.4.0",
|
|
37
|
+
"@quenty/table": "^3.5.0",
|
|
38
|
+
"@quenty/valueobject": "^13.3.0"
|
|
31
39
|
},
|
|
32
40
|
"publishConfig": {
|
|
33
41
|
"access": "public"
|
|
34
42
|
},
|
|
35
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "4955d2477353af4833f444483d41428faa446a4f"
|
|
36
44
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
Clip characters locally on the client of other clients so they don't interfer with physics.
|
|
3
|
+
@class ClipCharacters
|
|
4
|
+
]=]
|
|
5
|
+
|
|
6
|
+
local require = require(script.Parent.loader).load(script)
|
|
7
|
+
|
|
8
|
+
local BaseObject = require("BaseObject")
|
|
9
|
+
local ClipCharactersServiceConstants = require("ClipCharactersServiceConstants")
|
|
10
|
+
local RxBrioUtils = require("RxBrioUtils")
|
|
11
|
+
local RxCharacterUtils = require("RxCharacterUtils")
|
|
12
|
+
local RxPlayerUtils = require("RxPlayerUtils")
|
|
13
|
+
|
|
14
|
+
local ClipCharacters = setmetatable({}, BaseObject)
|
|
15
|
+
ClipCharacters.ClassName = "ClipCharacters"
|
|
16
|
+
ClipCharacters.__index = ClipCharacters
|
|
17
|
+
|
|
18
|
+
--[=[
|
|
19
|
+
Prevents characters from clipping together
|
|
20
|
+
|
|
21
|
+
@return ClipCharacters
|
|
22
|
+
]=]
|
|
23
|
+
function ClipCharacters.new()
|
|
24
|
+
local self = setmetatable(BaseObject.new(), ClipCharacters)
|
|
25
|
+
|
|
26
|
+
self._maid:GiveTask(RxPlayerUtils.observePlayersBrio():Pipe({
|
|
27
|
+
RxBrioUtils.flatMapBrio(function(player)
|
|
28
|
+
return RxCharacterUtils.observeLastCharacterBrio(player)
|
|
29
|
+
end)
|
|
30
|
+
}):Subscribe(function(brio)
|
|
31
|
+
if brio:IsDead() then
|
|
32
|
+
return
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
local maid, character = brio:ToMaidAndValue()
|
|
36
|
+
self:_setupCharacter(maid, character)
|
|
37
|
+
end))
|
|
38
|
+
|
|
39
|
+
return self
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
function ClipCharacters:_onDescendantAdded(originalTable, descendant)
|
|
43
|
+
if not originalTable[descendant] and descendant:IsA("BasePart") then
|
|
44
|
+
originalTable[descendant] = descendant.CollisionGroup
|
|
45
|
+
descendant.CollisionGroup = ClipCharactersServiceConstants.COLLISION_GROUP_NAME
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
function ClipCharacters:_onDescendantRemoving(originalTable, descendant)
|
|
50
|
+
if originalTable[descendant] then
|
|
51
|
+
descendant.CollisionGroup = originalTable[descendant]
|
|
52
|
+
originalTable[descendant] = nil
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
function ClipCharacters:_setupCharacter(maid, character)
|
|
57
|
+
local originalTable = {}
|
|
58
|
+
|
|
59
|
+
maid:GiveTask(character.DescendantAdded:Connect(function(descendant)
|
|
60
|
+
self:_onDescendantAdded(originalTable, descendant)
|
|
61
|
+
end))
|
|
62
|
+
|
|
63
|
+
maid:GiveTask(character.DescendantRemoving:Connect(function(descendant)
|
|
64
|
+
self:_onDescendantRemoving(originalTable, descendant)
|
|
65
|
+
end))
|
|
66
|
+
|
|
67
|
+
-- Cleanup
|
|
68
|
+
maid:GiveTask(function()
|
|
69
|
+
for descendant, _ in pairs(originalTable) do
|
|
70
|
+
self:_onDescendantRemoving(originalTable, descendant)
|
|
71
|
+
end
|
|
72
|
+
end)
|
|
73
|
+
|
|
74
|
+
-- Initialize
|
|
75
|
+
for _, descendant in pairs(character:GetDescendants()) do
|
|
76
|
+
self:_onDescendantAdded(originalTable, descendant)
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
return ClipCharacters
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class ClipCharactersServiceClient
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local ClipCharacters = require("ClipCharacters")
|
|
8
|
+
local Maid = require("Maid")
|
|
9
|
+
local StateStack = require("StateStack")
|
|
10
|
+
|
|
11
|
+
local ClipCharactersServiceClient = {}
|
|
12
|
+
ClipCharactersServiceClient.ServiceName = "ClipCharactersServiceClient"
|
|
13
|
+
|
|
14
|
+
function ClipCharactersServiceClient:Init(serviceBag)
|
|
15
|
+
assert(not self._serviceBag, "Already initialized")
|
|
16
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
17
|
+
self._maid = Maid.new()
|
|
18
|
+
|
|
19
|
+
self._disableCollisions = self._maid:Add(StateStack.new(false, "boolean"))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
--[=[
|
|
23
|
+
Disables collisions between default geometry and other charaters which stops some random physics
|
|
24
|
+
glitches from occuring.
|
|
25
|
+
]=]
|
|
26
|
+
function ClipCharactersServiceClient:PushDisableCharacterCollisionsWithDefault()
|
|
27
|
+
return self._disableCollisions:PushState(true)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
function ClipCharactersServiceClient:Start()
|
|
31
|
+
self._maid:GiveTask(self._disableCollisions:ObserveBrio(function(value)
|
|
32
|
+
return value
|
|
33
|
+
end):Subscribe(function(brio)
|
|
34
|
+
if brio:IsDead() then
|
|
35
|
+
return
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
local maid = brio:ToMaid()
|
|
39
|
+
maid:GiveTask(ClipCharacters.new())
|
|
40
|
+
end))
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
function ClipCharactersServiceClient:Destroy()
|
|
44
|
+
self._maid:DoCleaning()
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
return ClipCharactersServiceClient
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
--[=[
|
|
2
|
+
@class ClipCharactersService
|
|
3
|
+
]=]
|
|
4
|
+
|
|
5
|
+
local require = require(script.Parent.loader).load(script)
|
|
6
|
+
|
|
7
|
+
local PhysicsService = game:GetService("PhysicsService")
|
|
8
|
+
|
|
9
|
+
local Maid = require("Maid")
|
|
10
|
+
local ClipCharactersServiceConstants = require("ClipCharactersServiceConstants")
|
|
11
|
+
|
|
12
|
+
local ClipCharactersService = {}
|
|
13
|
+
ClipCharactersService.ServiceName = "ClipCharactersService"
|
|
14
|
+
|
|
15
|
+
function ClipCharactersService:Init(serviceBag)
|
|
16
|
+
assert(not self._serviceBag, "Already initialized")
|
|
17
|
+
self._serviceBag = assert(serviceBag, "No serviceBag")
|
|
18
|
+
self._maid = Maid.new()
|
|
19
|
+
|
|
20
|
+
self:_setupPhysicsGroup()
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
function ClipCharactersService:_setupPhysicsGroup()
|
|
24
|
+
PhysicsService:RegisterCollisionGroup(ClipCharactersServiceConstants.COLLISION_GROUP_NAME)
|
|
25
|
+
PhysicsService:CollisionGroupSetCollidable(ClipCharactersServiceConstants.COLLISION_GROUP_NAME, "Default", false)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
function ClipCharactersService:Destroy()
|
|
29
|
+
self._maid:DoCleaning()
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
return ClipCharactersService
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ClipCharactersTest",
|
|
3
|
+
"globIgnorePaths": [ "**/.package-lock.json" ],
|
|
4
|
+
"tree": {
|
|
5
|
+
"$className": "DataModel",
|
|
6
|
+
"ServerScriptService": {
|
|
7
|
+
"clipcharacters": {
|
|
8
|
+
"$path": ".."
|
|
9
|
+
},
|
|
10
|
+
"Script": {
|
|
11
|
+
"$path": "scripts/Server"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"StarterPlayer": {
|
|
15
|
+
"StarterPlayerScripts": {
|
|
16
|
+
"Main": {
|
|
17
|
+
"$path": "scripts/Client"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
--[[
|
|
2
|
+
@class ClientMain
|
|
3
|
+
]]
|
|
4
|
+
local loader = game:GetService("ReplicatedStorage"):WaitForChild("clipcharacters"):WaitForChild("loader")
|
|
5
|
+
local require = require(loader).bootstrapGame(loader.Parent)
|
|
6
|
+
|
|
7
|
+
local serviceBag = require("ServiceBag").new()
|
|
8
|
+
serviceBag:GetService(require("ClipCharactersServiceClient"))
|
|
9
|
+
serviceBag:Init()
|
|
10
|
+
serviceBag:Start()
|
|
11
|
+
|
|
12
|
+
serviceBag:GetService(require("ClipCharactersServiceClient")):PushDisableCharacterCollisionsWithDefault()
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
--[[
|
|
2
|
+
@class ServerMain
|
|
3
|
+
]]
|
|
4
|
+
local ServerScriptService = game:GetService("ServerScriptService")
|
|
5
|
+
|
|
6
|
+
local loader = ServerScriptService:FindFirstChild("LoaderUtils", true).Parent
|
|
7
|
+
local require = require(loader).bootstrapGame(ServerScriptService.clipcharacters)
|
|
8
|
+
|
|
9
|
+
local serviceBag = require("ServiceBag").new()
|
|
10
|
+
serviceBag:GetService(require("ClipCharactersService"))
|
|
11
|
+
serviceBag:Init()
|
|
12
|
+
serviceBag:Start()
|
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
--[=[
|
|
2
|
-
Clip characters locally on the client of other clients so they don't interfer with physics.
|
|
3
|
-
@class ClipCharacters
|
|
4
|
-
]=]
|
|
5
|
-
|
|
6
|
-
local require = require(script.Parent.loader).load(script)
|
|
7
|
-
|
|
8
|
-
local PhysicsService = game:GetService("PhysicsService")
|
|
9
|
-
local Players = game:GetService("Players")
|
|
10
|
-
|
|
11
|
-
local Maid = require("Maid")
|
|
12
|
-
local GetRemoteFunction = require("GetRemoteFunction")
|
|
13
|
-
|
|
14
|
-
local REMOTE_FUNCTION_NAME = "GetClipCharactersId"
|
|
15
|
-
|
|
16
|
-
local ClipCharacters = {}
|
|
17
|
-
ClipCharacters.ClassName = "ClipCharacters"
|
|
18
|
-
ClipCharacters.__index = ClipCharacters
|
|
19
|
-
ClipCharacters.COLLISION_GROUP_NAME = "ClipCharacters"
|
|
20
|
-
|
|
21
|
-
--[=[
|
|
22
|
-
Initialize on server
|
|
23
|
-
@server
|
|
24
|
-
]=]
|
|
25
|
-
function ClipCharacters.initServer()
|
|
26
|
-
local groupId = PhysicsService:CreateCollisionGroup(ClipCharacters.COLLISION_GROUP_NAME)
|
|
27
|
-
PhysicsService:CollisionGroupSetCollidable(ClipCharacters.COLLISION_GROUP_NAME, "Default", false)
|
|
28
|
-
|
|
29
|
-
local remoteFunction = GetRemoteFunction(REMOTE_FUNCTION_NAME)
|
|
30
|
-
remoteFunction.OnServerInvoke = function(_)
|
|
31
|
-
return groupId
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
--[=[
|
|
36
|
-
Initialize clipping on the client. Returns a new inst
|
|
37
|
-
@client
|
|
38
|
-
@return ClipCharacters
|
|
39
|
-
]=]
|
|
40
|
-
function ClipCharacters.new()
|
|
41
|
-
local self = setmetatable({}, ClipCharacters)
|
|
42
|
-
|
|
43
|
-
self._remoteFunction = GetRemoteFunction(REMOTE_FUNCTION_NAME)
|
|
44
|
-
|
|
45
|
-
self._maid = Maid.new()
|
|
46
|
-
self:_bindUpdatesYielding()
|
|
47
|
-
|
|
48
|
-
return self
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
function ClipCharacters:_onDescendantAdded(originalTable, descendant)
|
|
52
|
-
if not originalTable[descendant] and descendant:IsA("BasePart") then
|
|
53
|
-
originalTable[descendant] = descendant.CollisionGroupId
|
|
54
|
-
descendant.CollisionGroupId = self._collisionGroupId
|
|
55
|
-
end
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
function ClipCharacters:_onDescendantRemoving(originalTable, descendant)
|
|
59
|
-
if originalTable[descendant] then
|
|
60
|
-
descendant.CollisionGroupId = originalTable[descendant]
|
|
61
|
-
originalTable[descendant] = nil
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
function ClipCharacters:_onCharacterAdd(playerMaid, character)
|
|
66
|
-
local maid = Maid.new()
|
|
67
|
-
|
|
68
|
-
local originalTable = {}
|
|
69
|
-
|
|
70
|
-
maid:GiveTask(character.DescendantAdded:Connect(function(descendant)
|
|
71
|
-
self:_onDescendantAdded(originalTable, descendant)
|
|
72
|
-
end))
|
|
73
|
-
|
|
74
|
-
maid:GiveTask(character.DescendantRemoving:Connect(function(descendant)
|
|
75
|
-
self:_onDescendantRemoving(originalTable, descendant)
|
|
76
|
-
end))
|
|
77
|
-
|
|
78
|
-
-- Cleanup
|
|
79
|
-
maid:GiveTask(function()
|
|
80
|
-
for descendant, _ in pairs(originalTable) do
|
|
81
|
-
self:_onDescendantRemoving(originalTable, descendant)
|
|
82
|
-
end
|
|
83
|
-
end)
|
|
84
|
-
|
|
85
|
-
-- Initialize
|
|
86
|
-
for _, descendant in pairs(character:GetDescendants()) do
|
|
87
|
-
self:_onDescendantAdded(originalTable, descendant)
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
playerMaid._characterMaid = maid
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
function ClipCharacters:_onPlayerAdded(player)
|
|
94
|
-
if player == Players.LocalPlayer then
|
|
95
|
-
return
|
|
96
|
-
end
|
|
97
|
-
|
|
98
|
-
local maid = Maid.new()
|
|
99
|
-
|
|
100
|
-
maid:GiveTask(player.CharacterAdded:Connect(function(character)
|
|
101
|
-
self:_onCharacterAdd(maid, character)
|
|
102
|
-
end))
|
|
103
|
-
|
|
104
|
-
if player.Character then
|
|
105
|
-
self:_onCharacterAdd(maid, player.Character)
|
|
106
|
-
end
|
|
107
|
-
|
|
108
|
-
self._maid[player] = maid
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
function ClipCharacters:_bindUpdatesYielding()
|
|
112
|
-
self._collisionGroupId = self._remoteFunction:InvokeServer()
|
|
113
|
-
|
|
114
|
-
if not self._collisionGroupId then
|
|
115
|
-
warn("[ClipCharacters] - No self._collisionGroupId")
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
for _, player in pairs(Players:GetPlayers()) do
|
|
119
|
-
self:_onPlayerAdded(player)
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
self._maid:GiveTask(Players.PlayerAdded:Connect(function(player)
|
|
123
|
-
self:_onPlayerAdded(player)
|
|
124
|
-
end))
|
|
125
|
-
|
|
126
|
-
self._maid:GiveTask(Players.PlayerRemoving:Connect(function(player)
|
|
127
|
-
self._maid[player] = nil
|
|
128
|
-
end))
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
--[=[
|
|
132
|
-
Stop clipping on client
|
|
133
|
-
]=]
|
|
134
|
-
function ClipCharacters:Destroy()
|
|
135
|
-
self._maid:DoCleaning()
|
|
136
|
-
self._maid = nil
|
|
137
|
-
|
|
138
|
-
setmetatable({}, nil)
|
|
139
|
-
end
|
|
140
|
-
|
|
141
|
-
return ClipCharacters
|