Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
M
MDPro3
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
6
Issues
6
List
Boards
Labels
Service Desk
Milestones
Merge Requests
4
Merge Requests
4
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
赤子奈落
MDPro3
Commits
4f20c828
Commit
4f20c828
authored
Mar 10, 2026
by
Senator John
💬
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'patch' into 'master'
Patch See merge request
!30
parents
6cb91510
d94a1ad4
Changes
10
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
714 additions
and
84 deletions
+714
-84
Assets/Scripts/MDPro3/Duel/BG/DuelBGManager.cs
Assets/Scripts/MDPro3/Duel/BG/DuelBGManager.cs
+64
-24
Assets/Scripts/MDPro3/Duel/GameCard.cs
Assets/Scripts/MDPro3/Duel/GameCard.cs
+33
-5
Assets/Scripts/MDPro3/Duel/OnlineAppearanceSync.cs
Assets/Scripts/MDPro3/Duel/OnlineAppearanceSync.cs
+265
-0
Assets/Scripts/MDPro3/Duel/OnlineAppearanceSync.cs.meta
Assets/Scripts/MDPro3/Duel/OnlineAppearanceSync.cs.meta
+2
-0
Assets/Scripts/MDPro3/Duel/TcpHelper.cs
Assets/Scripts/MDPro3/Duel/TcpHelper.cs
+30
-0
Assets/Scripts/MDPro3/Managers/CameraManager.cs
Assets/Scripts/MDPro3/Managers/CameraManager.cs
+22
-10
Assets/Scripts/MDPro3/Servant/OcgCore.cs
Assets/Scripts/MDPro3/Servant/OcgCore.cs
+45
-0
Assets/Scripts/MDPro3/Servant/RoomServant.cs
Assets/Scripts/MDPro3/Servant/RoomServant.cs
+100
-1
Assets/Scripts/MDPro3/UI/SelectionButton/SelectionToggle_AppearanceItem.cs
...Pro3/UI/SelectionButton/SelectionToggle_AppearanceItem.cs
+71
-43
Assets/Scripts/MDPro3/UI/ServantUI/RoomServantUI.cs
Assets/Scripts/MDPro3/UI/ServantUI/RoomServantUI.cs
+82
-1
No files found.
Assets/Scripts/MDPro3/Duel/BG/DuelBGManager.cs
View file @
4f20c828
...
...
@@ -96,6 +96,10 @@ namespace MDPro3.Duel
&&
File
.
Exists
(
Program
.
PATH_DECK
+
deckName
+
Program
.
EXPANSION_YDK
))
deck
=
new
Deck
(
Program
.
PATH_DECK
+
deckName
+
Program
.
EXPANSION_YDK
);
var
hasSide0Appearance
=
RoomServant
.
TryGetOnlineAppearanceForSide
(
0
,
out
var
side0Appearance
);
var
hasSide1Appearance
=
RoomServant
.
TryGetOnlineAppearanceForSide
(
1
,
out
var
side1Appearance
);
var
overrideDeckAppearance
=
Config
.
GetBool
(
"OverrideDeckAppearance"
,
false
);
UIManager
.
UIBlackIn
(
Core
.
TransitionTime
);
await
UniTask
.
WaitForSeconds
(
Core
.
TransitionTime
);
await
UniTask
.
WaitUntil
(()
=>
Appearance
.
loaded
);
...
...
@@ -142,16 +146,21 @@ namespace MDPro3.Duel
var
path
=
Program
.
items
.
GetAssetPath
(
Config
.
Get
(
condition
.
ToString
()
+
"Field0"
,
Program
.
items
.
mats
[
0
].
id
.
ToString
()),
Items
.
ItemType
.
Mat
);
if
(
deck
!=
null
&&
!
Config
.
GetBool
(
"OverrideDeckAppearance"
,
false
))
if
(
condition
==
Condition
.
Watch
&&
hasSide0Appearance
)
path
=
Program
.
items
.
GetAssetPath
(
side0Appearance
.
Field
.
ToString
(),
Items
.
ItemType
.
Mat
);
else
if
(
deck
!=
null
&&
!
overrideDeckAppearance
)
path
=
Program
.
items
.
GetAssetPath
(
deck
.
Field
.
ToString
(),
Items
.
ItemType
.
Mat
);
path
=
"MasterDuel/"
+
path
;
var
field0
=
await
ABLoader
.
LoadFromFileAsync
(
path
+
"_near"
,
false
,
true
);
field0
.
transform
.
SetParent
(
Program
.
instance
.
container_3D
,
false
);
field0Manager
=
field0
.
GetComponent
<
BgEffectManager
>();
var
field1Config
=
Config
.
Get
(
condition
.
ToString
()
+
"Field1"
,
Program
.
items
.
mats
[
0
].
id
.
ToString
());
if
(
hasSide1Appearance
)
field1Config
=
side1Appearance
.
Field
.
ToString
();
var
field1
=
await
ABLoader
.
LoadFromFileAsync
(
"MasterDuel/"
+
Program
.
items
.
GetAssetPath
(
Config
.
Get
(
condition
.
ToString
()
+
"Field1"
,
Program
.
items
.
mats
[
0
].
id
.
ToString
()),
Items
.
ItemType
.
Mat
,
1
)
+
"_far"
Program
.
items
.
GetAssetPath
(
field1Config
,
Items
.
ItemType
.
Mat
,
1
)
+
"_far"
,
false
,
true
);
field1
.
transform
.
SetParent
(
Program
.
instance
.
container_3D
,
false
);
field1Manager
=
field1
.
GetComponent
<
BgEffectManager
>();
...
...
@@ -180,7 +189,9 @@ namespace MDPro3.Duel
path
=
Program
.
items
.
GetAssetPath
(
Config
.
Get
(
condition
.
ToString
()
+
"Grave0"
,
Program
.
items
.
graves
[
0
].
id
.
ToString
()),
Items
.
ItemType
.
Grave
);
if
(
deck
!=
null
&&
!
Config
.
GetBool
(
"OverrideDeckAppearance"
,
false
))
if
(
condition
==
Condition
.
Watch
&&
hasSide0Appearance
)
path
=
Program
.
items
.
GetAssetPath
(
side0Appearance
.
Grave
.
ToString
(),
Items
.
ItemType
.
Grave
);
else
if
(
deck
!=
null
&&
!
overrideDeckAppearance
)
path
=
Program
.
items
.
GetAssetPath
(
deck
.
Grave
.
ToString
(),
Items
.
ItemType
.
Grave
);
path
=
"MasterDuel/"
+
path
;
...
...
@@ -188,9 +199,12 @@ namespace MDPro3.Duel
grave0
.
transform
.
SetParent
(
pos_Grave_near
,
false
);
grave0Manager
=
grave0
.
GetComponent
<
BgEffectManager
>();
var
grave1Config
=
Config
.
Get
(
condition
.
ToString
()
+
"Grave1"
,
Program
.
items
.
graves
[
0
].
id
.
ToString
());
if
(
hasSide1Appearance
)
grave1Config
=
side1Appearance
.
Grave
.
ToString
();
var
grave1
=
await
ABLoader
.
LoadFromFileAsync
(
"MasterDuel/"
+
Program
.
items
.
GetAssetPath
(
Config
.
Get
(
condition
.
ToString
()
+
"Grave1"
,
Program
.
items
.
graves
[
0
].
id
.
ToString
()),
Items
.
ItemType
.
Grave
,
1
)
+
"_far"
Program
.
items
.
GetAssetPath
(
grave1Config
,
Items
.
ItemType
.
Grave
,
1
)
+
"_far"
,
false
,
true
);
grave1
.
transform
.
SetParent
(
pos_Grave_far
,
false
);
grave1Manager
=
grave1
.
GetComponent
<
BgEffectManager
>();
...
...
@@ -211,10 +225,12 @@ namespace MDPro3.Duel
#
region
Stand
var
standConfig
=
Config
.
Get
(
condition
.
ToString
()
+
"Stand0"
,
Program
.
items
.
stands
[
0
].
id
.
ToString
());
if
(
condition
==
Condition
.
Watch
&&
hasSide0Appearance
)
standConfig
=
side0Appearance
.
Stand
.
ToString
();
if
(
standConfig
!=
Items
.
CODE_NONE
.
ToString
()
||
deck
!=
null
)
{
path
=
Program
.
items
.
GetAssetPath
(
standConfig
,
Items
.
ItemType
.
Stand
);
if
(
deck
!=
null
&&
!
Config
.
GetBool
(
"OverrideDeckAppearance"
,
false
)
)
if
(
deck
!=
null
&&
!
overrideDeckAppearance
)
path
=
Program
.
items
.
GetAssetPath
(
deck
.
Stand
.
ToString
(),
Items
.
ItemType
.
Stand
);
path
=
"MasterDuel/"
+
path
;
var
stand0
=
await
ABLoader
.
LoadFromFileAsync
(
path
+
"_near"
,
false
,
true
);
...
...
@@ -226,6 +242,8 @@ namespace MDPro3.Duel
}
standConfig
=
Config
.
Get
(
condition
.
ToString
()
+
"Stand1"
,
Program
.
items
.
stands
[
0
].
id
.
ToString
());
if
(
hasSide1Appearance
)
standConfig
=
side1Appearance
.
Stand
.
ToString
();
if
(
standConfig
!=
Items
.
CODE_NONE
.
ToString
())
{
var
stand1
=
await
ABLoader
.
LoadFromFileAsync
(
"MasterDuel/"
+
...
...
@@ -243,27 +261,25 @@ namespace MDPro3.Duel
#
region
Mate
var
mateConfig
=
Config
.
Get
(
condition
.
ToString
()
+
"Mate0"
,
Program
.
items
.
mates
[
0
].
id
.
ToString
());
var
overrideDeckAppearance
=
Config
.
GetBool
(
"OverrideDeckAppearance"
,
false
);
var
mateConfigIsNone
=
mateConfig
==
Items
.
CODE_NONE
.
ToString
();
i
f
(!
mateConfigIsNone
||
(
deck
!=
null
&&
!
overrideDeckAppearance
))
{
int
mateCode
=
int
.
Parse
(
mateConfig
)
;
if
(
deck
!=
null
&&
!
overrideDeckAppearance
&&
!
mateConfigIsNone
)
mateCode
=
deck
.
Mate
;
if
(
mate
Code
!=
Items
.
CODE_NONE
)
if
(
condition
==
Condition
.
Watch
&&
hasSide0Appearance
)
mateConfig
=
side0Appearance
.
Mate
.
ToString
();
i
nt
mateCode
=
int
.
Parse
(
mateConfig
);
if
(
deck
!=
null
&&
!
overrideDeckAppearance
)
mateCode
=
deck
.
Mate
;
if
(
mateCode
!=
Items
.
CODE_NONE
)
{
var
mate
=
await
ABLoader
.
LoadMateAsync
(
mateCode
);
if
(
mate
!=
null
)
{
var
mate
=
await
ABLoader
.
LoadMateAsync
(
mateCode
);
if
(
mate
!=
null
)
{
mate0
=
mate
;
mate0
.
parent
=
pos_Avatar_near
;
mate0
.
gameObject
.
SetActive
(
false
);
}
mate0
=
mate
;
mate0
.
parent
=
pos_Avatar_near
;
mate0
.
gameObject
.
SetActive
(
false
);
}
}
mateConfig
=
Config
.
Get
(
condition
.
ToString
()
+
"Mate1"
,
Program
.
items
.
mates
[
0
].
id
.
ToString
());
if
(
hasSide1Appearance
)
mateConfig
=
side1Appearance
.
Mate
.
ToString
();
if
(
mateConfig
!=
Items
.
CODE_NONE
.
ToString
())
{
var
mate
=
await
ABLoader
.
LoadMateAsync
(
int
.
Parse
(
mateConfig
));
...
...
@@ -343,20 +359,44 @@ namespace MDPro3.Duel
#
region
Deck
Model
var
deckMat
=
Appearance
.
duelProtector0
;
if
(
deck
!=
null
&&
!
Config
.
GetBool
(
"OverrideDeckAppearance"
,
false
)
)
if
(
deck
!=
null
&&
!
overrideDeckAppearance
)
deckMat
=
await
ABLoader
.
LoadProtectorMaterial
(
deck
.
Protector
.
ToString
(),
Application
.
exitCancellationToken
);
if
(
condition
==
Condition
.
Duel
)
myProtector
=
deckMat
;
else
if
(
condition
==
Condition
.
Watch
)
{
myProtector
=
Appearance
.
watchProtector0
;
if
(
hasSide0Appearance
)
{
var
mat
=
await
ABLoader
.
LoadProtectorMaterial
(
side0Appearance
.
Protector
.
ToString
(),
Application
.
exitCancellationToken
);
if
(
mat
!=
null
)
myProtector
=
mat
;
}
}
else
if
(
condition
==
Condition
.
Replay
)
myProtector
=
Appearance
.
replayProtector0
;
if
(
condition
==
Condition
.
Duel
)
{
opProtector
=
Appearance
.
duelProtector1
;
if
(
hasSide1Appearance
)
{
var
mat
=
await
ABLoader
.
LoadProtectorMaterial
(
side1Appearance
.
Protector
.
ToString
(),
Application
.
exitCancellationToken
);
if
(
mat
!=
null
)
opProtector
=
mat
;
}
}
else
if
(
condition
==
Condition
.
Watch
)
{
opProtector
=
Appearance
.
watchProtector1
;
if
(
hasSide1Appearance
)
{
var
mat
=
await
ABLoader
.
LoadProtectorMaterial
(
side1Appearance
.
Protector
.
ToString
(),
Application
.
exitCancellationToken
);
if
(
mat
!=
null
)
opProtector
=
mat
;
}
}
else
if
(
condition
==
Condition
.
Replay
)
opProtector
=
Appearance
.
replayProtector1
;
...
...
Assets/Scripts/MDPro3/Duel/GameCard.cs
View file @
4f20c828
...
...
@@ -523,15 +523,14 @@ namespace MDPro3
handsCount
=
Program
.
instance
.
ocgcore
.
GetOpHandCount
();
float
x
=
p
.
sequence
*
4
-
(
handsCount
-
1
)
*
2
;
if
(
p
.
controller
==
0
)
{
var
z
=
-
28
+
(
30
-
Program
.
instance
.
camera_
.
cameraMain
.
fieldOfView
)
*
0.7f
;
var
z
=
GetMyHandBaseZ
()
;
return
new
Vector3
(
x
+
handOffset
*
UIManager
.
ScreenLengthWithoutScalerX
(
0.038f
),
15
,
z
);
}
else
{
var
z
=
17
-
(
30
-
Program
.
instance
.
camera_
.
cameraMain
.
fieldOfView
)
*
0.7f
;
var
z
=
GetOpHandBaseZ
()
;
return
new
Vector3
(-
x
,
15
,
z
);
}
}
...
...
@@ -713,6 +712,35 @@ namespace MDPro3
return
returnValue
;
}
private
static
float
GetMyHandBaseZ
()
{
return
-
28f
+
GetHandDepthOffsetByFov
();
}
private
static
float
GetOpHandBaseZ
()
{
return
17f
-
GetHandDepthOffsetByFov
();
}
private
static
float
GetHandDepthOffsetByFov
()
{
var
camera
=
Program
.
instance
?.
camera_
?.
cameraMain
;
if
(
camera
==
null
)
return
0f
;
var
fovDelta
=
Mathf
.
Clamp
(
30f
-
camera
.
fieldOfView
,
0f
,
6f
);
var
fovCompensation
=
fovDelta
*
0.7f
;
// After widening duel camera framing, retract hand outward on ultrawide displays.
var
aspect
=
Tools
.
GetScreenAspectRatio
();
var
ultraWide21x9T
=
Mathf
.
InverseLerp
(
16f
/
9f
,
21f
/
9f
,
aspect
);
var
ultraWide32x9T
=
Mathf
.
InverseLerp
(
21f
/
9f
,
32f
/
9f
,
aspect
);
// Strong ultrawide push so hand cards sit lower while keeping a little more text visible.
var
ultraWideOutward
=
Mathf
.
Lerp
(
0f
,
1.60f
,
ultraWide21x9T
)
+
Mathf
.
Lerp
(
0f
,
1.10f
,
ultraWide32x9T
);
return
fovCompensation
-
ultraWideOutward
;
}
public
static
Vector3
GetCardRotation
(
GPS
p
,
int
code
=
0
)
{
var
condition
=
CardRuleCondition
.
MeUpAtk
;
...
...
@@ -1915,9 +1943,9 @@ namespace MDPro3
var
targetPosition
=
GetCardPosition
(
p
,
this
);
var
x
=
targetPosition
.
x
;
if
(
HideMyHandCard
&&
p
.
InMyControl
())
targetPosition
.
z
=
-
28f
;
targetPosition
.
z
=
GetMyHandBaseZ
()
;
if
(
HideOpHandCard
&&
!
p
.
InMyControl
())
targetPosition
.
z
=
17f
;
targetPosition
.
z
=
GetOpHandBaseZ
()
;
model
.
transform
.
DOLocalMove
(
targetPosition
,
time
);
}
...
...
Assets/Scripts/MDPro3/Duel/OnlineAppearanceSync.cs
0 → 100644
View file @
4f20c828
This diff is collapsed.
Click to expand it.
Assets/Scripts/MDPro3/Duel/OnlineAppearanceSync.cs.meta
0 → 100644
View file @
4f20c828
fileFormatVersion: 2
guid: 2cbd8637a7f820c4caacc6106ddc0dbb
\ No newline at end of file
Assets/Scripts/MDPro3/Duel/TcpHelper.cs
View file @
4f20c828
...
...
@@ -270,6 +270,8 @@ namespace MDPro3
}
onDisConnected
=
false
;
tcpClient
=
null
;
deck
=
null
;
deckStrings
.
Clear
();
canJoin
=
true
;
if
(
Program
.
instance
.
ocgcore
.
showing
)
{
...
...
@@ -375,6 +377,7 @@ namespace MDPro3
for
(
var
i
=
0
;
i
<
deckFor
.
Extra
.
Count
;
i
++)
message
.
Data
.
writer
.
Write
(
deckFor
.
Extra
[
i
]);
for
(
var
i
=
0
;
i
<
deckFor
.
Side
.
Count
;
i
++)
message
.
Data
.
writer
.
Write
(
deckFor
.
Side
[
i
]);
Send
(
message
);
CtosMessage_UpdateAppearance
(
deckFor
);
}
public
static
void
CtosMessage_HandResult
(
int
res
)
...
...
@@ -420,6 +423,7 @@ namespace MDPro3
public
static
void
CtosMessage_JoinGame
(
string
psw
)
{
deckStrings
.
Clear
();
deck
=
null
;
var
message
=
new
Package
();
message
.
Function
=
(
int
)
CtosMessage
.
JoinGame
;
message
.
Data
.
writer
.
Write
((
short
)
Config
.
ClientVersion
);
...
...
@@ -432,6 +436,8 @@ namespace MDPro3
public
static
void
CtosMessage_LeaveGame
()
{
deck
=
null
;
deckStrings
.
Clear
();
var
message
=
new
Package
();
message
.
Function
=
(
int
)
CtosMessage
.
LeaveGame
;
Send
(
message
);
...
...
@@ -459,6 +465,30 @@ namespace MDPro3
Send
(
message
);
}
public
static
void
CtosMessage_UpdateAppearance
(
Deck
deckFor
)
{
if
(
deckFor
==
null
)
return
;
var
syncMessage
=
OnlineAppearanceSync
.
BuildMessageForLocalPlayer
(
deckFor
);
CtosMessage_Chat
(
syncMessage
);
Debug
.
Log
(
$"[OnlineAppearance] Sent sync payload:
{
syncMessage
}
"
);
}
public
static
void
CtosMessage_UpdateAppearanceFromCurrentDeck
()
{
if
(
deck
!=
null
)
{
CtosMessage_UpdateAppearance
(
deck
);
return
;
}
var
deckPath
=
Program
.
PATH_DECK
+
Config
.
GetConfigDeckName
()
+
Program
.
EXPANSION_YDK
;
if
(!
File
.
Exists
(
deckPath
))
return
;
CtosMessage_UpdateAppearance
(
new
Deck
(
deckPath
));
}
public
static
void
CtosMessage_HsToDuelist
()
{
var
message
=
new
Package
();
...
...
Assets/Scripts/MDPro3/Managers/CameraManager.cs
View file @
4f20c828
...
...
@@ -56,16 +56,28 @@ namespace MDPro3
public
static
void
ChangeCameraFOV
()
{
float
aspect
=
(
float
)
Screen
.
width
*
9
/
Screen
.
height
;
if
(
aspect
>
16
)
{
Program
.
instance
.
camera_
.
cameraMain
.
fieldOfView
=
30
+
16
-
aspect
;
Program
.
instance
.
camera_
.
cameraDuelOverlay3D
.
fieldOfView
=
Program
.
instance
.
camera_
.
cameraMain
.
fieldOfView
;
}
else
var
camera
=
Program
.
instance
.
camera_
;
if
(
camera
==
null
||
camera
.
cameraMain
==
null
||
camera
.
cameraDuelOverlay3D
==
null
)
return
;
var
aspect
=
Tools
.
GetScreenAspectRatio
();
var
ultraWideT
=
Mathf
.
InverseLerp
(
16f
/
9f
,
32f
/
9f
,
aspect
);
// Keep 16:9 unchanged while widening ultrawide framing to match MD-style composition.
var
duelFov
=
Mathf
.
Lerp
(
30f
,
33f
,
ultraWideT
);
camera
.
cameraMain
.
fieldOfView
=
duelFov
;
camera
.
cameraDuelOverlay3D
.
fieldOfView
=
duelFov
;
mainCameraDefaultPosition
=
new
Vector3
(
0f
,
95f
+
Mathf
.
Lerp
(
0f
,
4f
,
ultraWideT
),
-
37f
-
Mathf
.
Lerp
(
0f
,
5f
,
ultraWideT
));
if
(
Program
.
instance
.
ocgcore
!=
null
&&
Program
.
instance
.
ocgcore
.
showing
)
{
Program
.
instance
.
camera_
.
cameraMain
.
fieldOfView
=
30
;
Program
.
instance
.
camera_
.
cameraDuelOverlay3D
.
fieldOfView
=
30
;
camera
.
cameraMain
.
transform
.
localPosition
=
mainCameraDefaultPosition
;
if
(!
overlaySticking
)
camera
.
cameraDuelOverlay3D
.
transform
.
localPosition
=
mainCameraDefaultPosition
;
}
}
...
...
@@ -89,7 +101,7 @@ namespace MDPro3
public
static
void
Overlay3DReset
()
{
Program
.
instance
.
camera_
.
cameraDuelOverlay3D
.
transform
.
localPosition
=
new
Vector3
(
0
,
95
,
-
37
)
;
Program
.
instance
.
camera_
.
cameraDuelOverlay3D
.
transform
.
localPosition
=
mainCameraDefaultPosition
;
Program
.
instance
.
camera_
.
cameraDuelOverlay3D
.
transform
.
localEulerAngles
=
new
Vector3
(
70
,
0
,
0
);
}
...
...
Assets/Scripts/MDPro3/Servant/OcgCore.cs
View file @
4f20c828
...
...
@@ -1498,6 +1498,8 @@ namespace MDPro3.Servant
GetUI
<
OcgCoreUI
>().
AvatarPlayer1
.
material
=
Appearance
.
duelFrameMat1Tag
;
SetFaceWhenCharaOff
(
Appearance
.
duelFace1Tag
,
1
);
}
_
=
ApplyOnlineOpponentFaceAsync
();
}
else
if
(
condition
==
Condition
.
Watch
)
{
...
...
@@ -1549,6 +1551,49 @@ namespace MDPro3.Servant
_
=
SetMyCardFace
();
}
private
async
UniTask
ApplyOnlineOpponentFaceAsync
()
{
if
(
condition
!=
Condition
.
Duel
)
return
;
var
useTagOpponent
=
isTag
&&
GetUI
<
OcgCoreUI
>().
TextPlayer1Name
.
text
!=
name_1
;
if
(!
RoomServant
.
TryGetOnlineAppearanceForOpponent
(
useTagOpponent
,
out
var
appearance
))
{
if
(!
useTagOpponent
||
!
RoomServant
.
TryGetOnlineAppearanceForOpponent
(
false
,
out
appearance
))
return
;
}
var
iconPlayer
=
useTagOpponent
?
3
:
1
;
var
frameCode
=
appearance
.
Frame
.
ToString
();
var
frameSprite
=
await
Program
.
items
.
LoadConcreteItemIconAsync
(
frameCode
,
Items
.
ItemType
.
Frame
,
iconPlayer
);
Material
frameMaterial
;
if
(
appearance
.
Frame
==
Items
.
CODE_DIY
)
frameMaterial
=
Appearance
.
matForFace
==
null
?
null
:
new
Material
(
Appearance
.
matForFace
);
else
frameMaterial
=
await
ABLoader
.
LoadFrameMaterial
(
frameCode
);
if
(
frameMaterial
!=
null
&&
frameSprite
!=
null
)
frameMaterial
.
SetTexture
(
"_ProfileFrameTex"
,
frameSprite
.
texture
);
var
faceSprite
=
await
Program
.
items
.
LoadConcreteItemIconAsync
(
appearance
.
Face
.
ToString
(),
Items
.
ItemType
.
Face
,
iconPlayer
);
var
latestUseTagOpponent
=
isTag
&&
GetUI
<
OcgCoreUI
>().
TextPlayer1Name
.
text
!=
name_1
;
if
(
latestUseTagOpponent
!=
useTagOpponent
)
return
;
if
(!
RoomServant
.
TryGetOnlineAppearanceForOpponent
(
useTagOpponent
,
out
var
latest
))
{
if
(!
useTagOpponent
||
!
RoomServant
.
TryGetOnlineAppearanceForOpponent
(
false
,
out
latest
))
return
;
}
if
(
latest
.
Face
!=
appearance
.
Face
||
latest
.
Frame
!=
appearance
.
Frame
)
return
;
if
(
frameMaterial
!=
null
)
GetUI
<
OcgCoreUI
>().
AvatarPlayer1
.
material
=
frameMaterial
;
if
(
faceSprite
!=
null
)
SetFaceWhenCharaOff
(
faceSprite
,
1
);
}
private
async
UniTask
SetMyCardFace
()
{
if
(
MyCard
.
account
==
null
||
!
mycardDuel
)
...
...
Assets/Scripts/MDPro3/Servant/RoomServant.cs
View file @
4f20c828
...
...
@@ -47,6 +47,7 @@ namespace MDPro3.Servant
public
bool
ready
;
}
public
static
Player
[]
players
=
new
Player
[
32
];
private
static
readonly
Dictionary
<
int
,
OnlineAppearanceData
>
onlineAppearances
=
new
();
private
Deck
deck
;
...
...
@@ -88,6 +89,7 @@ namespace MDPro3.Servant
if
(
FromLocalHost
)
YgoServer
.
StopServer
();
}
onlineAppearances
.
Clear
();
base
.
OnExit
();
Program
.
instance
.
ocgcore
.
CloseConnection
();
}
...
...
@@ -136,6 +138,77 @@ namespace MDPro3.Servant
return
true
;
}
public
static
bool
TryGetOnlineAppearanceForSide
(
int
side
,
out
OnlineAppearanceData
appearance
)
{
appearance
=
default
;
if
(!
TryGetTeamPlayer
(
side
,
false
,
out
var
player
))
return
false
;
return
onlineAppearances
.
TryGetValue
(
player
,
out
appearance
);
}
public
static
bool
TryGetOnlineAppearanceForOpponent
(
bool
tag
,
out
OnlineAppearanceData
appearance
)
{
appearance
=
default
;
if
(!
TryGetTeamPlayer
(
1
,
tag
,
out
var
player
))
return
false
;
return
onlineAppearances
.
TryGetValue
(
player
,
out
appearance
);
}
public
static
bool
TryGetOnlineAppearanceForPlayer
(
int
player
,
out
OnlineAppearanceData
appearance
)
{
appearance
=
default
;
if
(
player
<
0
||
player
>=
4
)
return
false
;
return
onlineAppearances
.
TryGetValue
(
player
,
out
appearance
);
}
private
static
bool
TryGetTeamPlayer
(
int
side
,
bool
tag
,
out
int
player
)
{
player
=
-
1
;
if
(
side
!=
0
&&
side
!=
1
)
return
false
;
if
(
Mode
!=
2
)
{
if
(
tag
)
return
false
;
if
(
SelfType
==
7
)
player
=
side
;
else
player
=
side
==
0
?
SelfType
:
1
-
SelfType
;
return
player
>=
0
&&
player
<
4
;
}
var
hostTeamAsSide0
=
SelfType
==
7
||
SelfType
<
2
;
var
useHostTeam
=
hostTeamAsSide0
?
side
==
0
:
side
==
1
;
if
(
useHostTeam
)
player
=
tag
?
1
:
0
;
else
player
=
tag
?
3
:
2
;
return
true
;
}
private
static
void
MoveOnlineAppearance
(
int
from
,
int
to
)
{
if
(
onlineAppearances
.
TryGetValue
(
from
,
out
var
appearance
))
{
onlineAppearances
[
to
]
=
appearance
;
onlineAppearances
.
Remove
(
from
);
}
else
{
onlineAppearances
.
Remove
(
to
);
}
}
private
static
void
RemoveOnlineAppearance
(
int
player
)
{
onlineAppearances
.
Remove
(
player
);
}
private
void
ShowOcgCore
()
{
if
(
CoreShowing
==
0
)
...
...
@@ -415,6 +488,7 @@ namespace MDPro3.Servant
for
(
int
i
=
0
;
i
<
4
;
i
++)
players
[
i
]
=
null
;
onlineAppearances
.
Clear
();
if
(!
FromHandTest
)
Program
.
instance
.
ShiftToServant
(
Program
.
instance
.
room
);
...
...
@@ -427,6 +501,8 @@ namespace MDPro3.Servant
IsHost
=
((
type
>>
4
)
&
0xF
)
!=
0
;
if
(
SelfType
<
4
&&
players
[
SelfType
]
!=
null
)
players
[
SelfType
].
ready
=
false
;
if
(
SelfType
<
4
)
TcpHelper
.
CtosMessage_UpdateAppearanceFromCurrentDeck
();
Realize
();
}
...
...
@@ -469,8 +545,23 @@ namespace MDPro3.Servant
public
void
StocMessage_Chat
(
BinaryReader
r
)
{
int
player
=
r
.
ReadInt16
();
var
length
=
r
.
BaseStream
.
Length
-
3
;
var
length
=
(
int
)((
r
.
BaseStream
.
Length
-
r
.
BaseStream
.
Position
)
/
2
)
;
var
content
=
r
.
ReadUnicode
((
int
)
length
);
if
(
OnlineAppearanceSync
.
IsSyncMessage
(
content
))
{
if
(
player
>=
0
&&
player
<
4
&&
OnlineAppearanceSync
.
TryParse
(
content
,
out
var
appearance
))
{
onlineAppearances
[
player
]
=
appearance
;
if
(
showing
)
Realize
();
Debug
.
Log
(
$"[OnlineAppearance] Received sync from seat
{
player
}
:
{
appearance
.
Case
}
,
{
appearance
.
Protector
}
,
{
appearance
.
Field
}
,
{
appearance
.
Grave
}
,
{
appearance
.
Stand
}
,
{
appearance
.
Mate
}
,
{
appearance
.
Face
}
,
{
appearance
.
Frame
}
"
);
}
else
{
Debug
.
LogWarning
(
$"[OnlineAppearance] Ignored sync chat. seat=
{
player
}
, content='
{
content
}
'"
);
}
return
;
}
//Debug.Log($"{player}: {content} {OcgCore.isFirst} {RoomServant.SelfType}");
Program
.
instance
.
ui_
.
chatPanel
.
AddChatItem
(
player
,
content
);
}
...
...
@@ -485,6 +576,9 @@ namespace MDPro3.Servant
player
.
name
=
name
;
player
.
ready
=
false
;
players
[
pos
]
=
player
;
RemoveOnlineAppearance
(
pos
);
if
(
SelfType
<
4
&&
players
[
SelfType
]
!=
null
&&
pos
!=
SelfType
)
TcpHelper
.
CtosMessage_UpdateAppearanceFromCurrentDeck
();
Realize
();
}
...
...
@@ -499,16 +593,21 @@ namespace MDPro3.Servant
{
players
[
state
]
=
players
[
pos
];
players
[
pos
]
=
null
;
MoveOnlineAppearance
(
pos
,
state
);
}
if
(
state
==
0x9
)
players
[
pos
].
ready
=
true
;
if
(
state
==
0xA
)
players
[
pos
].
ready
=
false
;
if
(
state
==
0xB
)
{
players
[
pos
]
=
null
;
RemoveOnlineAppearance
(
pos
);
}
if
(
state
==
0x8
)
{
players
[
pos
]
=
null
;
RemoveOnlineAppearance
(
pos
);
ObserverCount
++;
}
Realize
();
...
...
Assets/Scripts/MDPro3/UI/SelectionButton/SelectionToggle_AppearanceItem.cs
View file @
4f20c828
using
System
;
using
System.Collections
;
using
System.Collections.Generic
;
using
System.Threading
;
using
TMPro
;
using
UnityEngine
;
using
UnityEngine.EventSystems
;
...
...
@@ -62,63 +63,82 @@ namespace MDPro3.UI
public
void
Refresh
()
{
_
=
RefreshAsync
();
_
=
RefreshAsync
(
this
.
GetCancellationTokenOnDestroy
()
);
}
private
async
UniTask
RefreshAsync
()
private
async
UniTask
RefreshAsync
(
CancellationToken
cancellationToken
)
{
for
(
int
i
=
0
;
i
<
index
;
i
++)
await
UniTask
.
Yield
();
if
(
path
.
StartsWith
(
"Protector"
))
{
protectorMaterial
=
await
ABLoader
.
LoadProtectorMaterial
(
itemID
.
ToString
(),
destroyCancellationToken
);
if
(
protectorMaterial
!=
null
)
protectorMaterial
.
renderQueue
=
3000
;
// Use default UI material for list rendering so viewport/mask clipping works while scrolling.
Protector
.
texture
=
protectorMaterial
==
null
?
null
:
protectorMaterial
.
mainTexture
;
Protector
.
material
=
null
;
Protector
.
color
=
Color
.
white
;
Icon
.
gameObject
.
SetActive
(
false
);
}
else
if
(
path
.
Length
>
0
)
try
{
Icon
.
sprite
=
await
Program
.
items
.
LoadItemIconAsync
(
itemID
.
ToString
(),
Items
.
ItemType
.
Unknown
);
if
(
Manager
==
null
)
for
(
int
i
=
0
;
i
<
index
;
i
++)
await
UniTask
.
Yield
(
PlayerLoopTiming
.
Update
,
cancellationToken
);
if
(
cancellationToken
.
IsCancellationRequested
||
this
==
null
)
return
;
Icon
.
color
=
Color
.
white
;
if
(
path
.
StartsWith
(
"Pro
fileFrame
"
))
if
(
path
.
StartsWith
(
"Pro
tector
"
))
{
Icon
.
rectTransform
.
localScale
=
Vector3
.
one
*
0.8f
;
Icon
.
material
=
await
ABLoader
.
LoadFrameMaterial
(
itemID
.
ToString
());
Icon
.
material
.
SetTexture
(
"_ProfileFrameTex"
,
Icon
.
sprite
.
texture
);
Icon
.
sprite
=
TextureManager
.
container
.
black
;
Icon
.
color
=
Color
.
white
;
protectorMaterial
=
await
ABLoader
.
LoadProtectorMaterial
(
itemID
.
ToString
(),
cancellationToken
);
if
(
protectorMaterial
!=
null
)
protectorMaterial
.
renderQueue
=
3000
;
if
(
cancellationToken
.
IsCancellationRequested
||
this
==
null
)
return
;
// Use default UI material for list rendering so viewport/mask clipping works while scrolling.
Protector
.
texture
=
protectorMaterial
==
null
?
null
:
protectorMaterial
.
mainTexture
;
Protector
.
material
=
null
;
Protector
.
color
=
Color
.
white
;
Icon
.
gameObject
.
SetActive
(
false
);
}
else
if
(
path
.
StartsWith
(
"DeckCase"
)
)
else
if
(
path
.
Length
>
0
)
{
Icon
.
transform
.
localPosition
=
new
Vector3
(
0f
,
15f
,
0f
);
Icon
.
sprite
=
await
Program
.
items
.
LoadItemIconAsync
(
itemID
.
ToString
(),
Items
.
ItemType
.
Unknown
);
if
(
cancellationToken
.
IsCancellationRequested
||
this
==
null
||
Manager
==
null
)
return
;
Icon
.
color
=
Color
.
white
;
if
(
path
.
StartsWith
(
"ProfileFrame"
))
{
Icon
.
rectTransform
.
localScale
=
Vector3
.
one
*
0.8f
;
Icon
.
material
=
await
ABLoader
.
LoadFrameMaterial
(
itemID
.
ToString
());
if
(
cancellationToken
.
IsCancellationRequested
||
this
==
null
)
return
;
Icon
.
material
.
SetTexture
(
"_ProfileFrameTex"
,
Icon
.
sprite
.
texture
);
Icon
.
sprite
=
TextureManager
.
container
.
black
;
Icon
.
color
=
Color
.
white
;
}
else
if
(
path
.
StartsWith
(
"DeckCase"
))
{
Icon
.
transform
.
localPosition
=
new
Vector3
(
0f
,
15f
,
0f
);
}
else
if
(
path
.
StartsWith
(
"WallPaperIcon"
))
{
WallpaperBG
.
gameObject
.
SetActive
(
true
);
}
Protector
.
gameObject
.
SetActive
(
false
);
}
else
if
(
path
.
StartsWith
(
"WallPaperIcon"
))
else
//CrossDuel Mate
{
WallpaperBG
.
gameObject
.
SetActive
(
true
);
var
art
=
await
CardImageLoader
.
LoadArtAsync
(
itemID
,
true
,
cancellationToken
);
if
(
cancellationToken
.
IsCancellationRequested
||
this
==
null
)
return
;
Icon
.
color
=
Color
.
white
;
Icon
.
sprite
=
TextureManager
.
Texture2Sprite
(
art
);
Protector
.
gameObject
.
SetActive
(
false
);
}
Protector
.
gameObject
.
SetActive
(
false
);
if
(
path
.
StartsWith
(
"ProfileIcon"
)
&&
!
cancellationToken
.
IsCancellationRequested
&&
this
!=
null
)
Icon
.
material
=
Appearance
.
matForFace
;
loaded
=
true
;
}
else
//CrossDuel Mate
catch
(
OperationCanceledException
)
{
var
art
=
await
CardImageLoader
.
LoadArtAsync
(
itemID
,
true
,
destroyCancellationToken
);
Icon
.
color
=
Color
.
white
;
Icon
.
sprite
=
TextureManager
.
Texture2Sprite
(
art
);
Protector
.
gameObject
.
SetActive
(
false
);
}
if
(
path
.
StartsWith
(
"ProfileIcon"
))
Icon
.
material
=
Appearance
.
matForFace
;
loaded
=
true
;
refreshCoroutine
=
null
;
finally
{
refreshCoroutine
=
null
;
}
}
protected
override
void
CallHoverOnEvent
()
...
...
@@ -202,6 +222,14 @@ namespace MDPro3.UI
Config
.
Set
(
"Wallpaper"
,
itemID
.
ToString
());
else
Config
.
Set
(
Appearance
.
condition
.
ToString
()
+
AppearanceUI
.
currentContent
+
Appearance
.
player
,
itemID
.
ToString
());
if
(
Appearance
.
condition
==
Appearance
.
Condition
.
Duel
&&
Appearance
.
player
==
"0"
&&
Config
.
GetBool
(
"OverrideDeckAppearance"
,
false
)
&&
Program
.
instance
.
room
!=
null
&&
Program
.
instance
.
room
.
showing
&&
RoomServant
.
SelfType
<
4
)
TcpHelper
.
CtosMessage_UpdateAppearanceFromCurrentDeck
();
}
StartCoroutine
(
ConfigSetAsync
());
...
...
Assets/Scripts/MDPro3/UI/ServantUI/RoomServantUI.cs
View file @
4f20c828
...
...
@@ -3,8 +3,10 @@ using MDPro3.Servant;
using
MDPro3.Utility
;
using
System.Collections.Generic
;
using
System.IO
;
using
Cysharp.Threading.Tasks
;
using
TMPro
;
using
UnityEngine
;
using
UnityEngine.UI
;
using
static
MDPro3
.
UI
.
ChatPanel
;
namespace
MDPro3.UI.ServantUI
...
...
@@ -83,6 +85,10 @@ namespace MDPro3.UI.ServantUI
#
endregion
private
List
<
SelectionButton_RoomPlayer
>
roomPlayers
;
private
readonly
Dictionary
<
int
,
Sprite
>
syncedFaces
=
new
();
private
readonly
Dictionary
<
int
,
Material
>
syncedFrames
=
new
();
private
readonly
Dictionary
<
int
,
int
>
syncedFaceIds
=
new
();
private
readonly
Dictionary
<
int
,
int
>
syncedFrameIds
=
new
();
private
void
Awake
()
{
...
...
@@ -197,6 +203,7 @@ namespace MDPro3.UI.ServantUI
roomPlayers
[
i
].
GetAvatar
().
sprite
=
Appearance
.
watchFace1Tag
;
break
;
}
TryApplyOnlineAvatar
(
i
);
}
}
if
(
RoomServant
.
IsHost
)
...
...
@@ -285,5 +292,79 @@ namespace MDPro3.UI.ServantUI
Program
.
instance
.
ShiftToServant
(
Program
.
instance
.
deckSelector
);
}
private
void
TryApplyOnlineAvatar
(
int
player
)
{
if
(!
RoomServant
.
TryGetOnlineAppearanceForPlayer
(
player
,
out
var
appearance
))
return
;
var
iconPlayer
=
GetIconPlayerIndex
(
GetPlayerPosition
(
player
));
if
(
syncedFaceIds
.
TryGetValue
(
player
,
out
var
cachedFaceId
)
&&
syncedFrameIds
.
TryGetValue
(
player
,
out
var
cachedFrameId
)
&&
cachedFaceId
==
appearance
.
Face
&&
cachedFrameId
==
appearance
.
Frame
&&
syncedFaces
.
TryGetValue
(
player
,
out
var
cachedFace
)
&&
syncedFrames
.
TryGetValue
(
player
,
out
var
cachedFrame
)
&&
cachedFace
!=
null
&&
cachedFrame
!=
null
)
{
roomPlayers
[
player
].
GetAvatar
().
sprite
=
cachedFace
;
roomPlayers
[
player
].
GetAvatar
().
material
=
cachedFrame
;
return
;
}
_
=
ApplyOnlineAvatarAsync
(
player
,
appearance
,
iconPlayer
);
}
private
async
UniTask
ApplyOnlineAvatarAsync
(
int
player
,
OnlineAppearanceData
appearance
,
int
iconPlayer
)
{
var
frameCode
=
appearance
.
Frame
.
ToString
();
var
frameSprite
=
await
Program
.
items
.
LoadConcreteItemIconAsync
(
frameCode
,
Items
.
ItemType
.
Frame
,
iconPlayer
);
Material
frameMaterial
;
if
(
appearance
.
Frame
==
Items
.
CODE_DIY
)
frameMaterial
=
Appearance
.
matForFace
==
null
?
null
:
new
Material
(
Appearance
.
matForFace
);
else
frameMaterial
=
await
ABLoader
.
LoadFrameMaterial
(
frameCode
);
if
(
frameMaterial
!=
null
&&
frameSprite
!=
null
)
frameMaterial
.
SetTexture
(
"_ProfileFrameTex"
,
frameSprite
.
texture
);
var
faceSprite
=
await
Program
.
items
.
LoadConcreteItemIconAsync
(
appearance
.
Face
.
ToString
(),
Items
.
ItemType
.
Face
,
iconPlayer
);
if
(!
RoomServant
.
TryGetOnlineAppearanceForPlayer
(
player
,
out
var
latest
))
return
;
if
(
latest
.
Face
!=
appearance
.
Face
||
latest
.
Frame
!=
appearance
.
Frame
)
return
;
if
(
player
<
0
||
player
>=
roomPlayers
.
Count
)
return
;
if
(!
roomPlayers
[
player
].
gameObject
.
activeInHierarchy
)
return
;
if
(
frameMaterial
!=
null
)
roomPlayers
[
player
].
GetAvatar
().
material
=
frameMaterial
;
if
(
faceSprite
!=
null
)
roomPlayers
[
player
].
GetAvatar
().
sprite
=
faceSprite
;
syncedFaceIds
[
player
]
=
appearance
.
Face
;
syncedFrameIds
[
player
]
=
appearance
.
Frame
;
syncedFaces
[
player
]
=
faceSprite
;
syncedFrames
[
player
]
=
frameMaterial
;
}
private
static
int
GetIconPlayerIndex
(
PlayerPosition
position
)
{
switch
(
position
)
{
case
PlayerPosition
.
Op
:
case
PlayerPosition
.
WatchOp
:
return
1
;
case
PlayerPosition
.
MyTag
:
case
PlayerPosition
.
WatchMyTag
:
return
2
;
case
PlayerPosition
.
OpTag
:
case
PlayerPosition
.
WatchOpTag
:
return
3
;
default
:
return
0
;
}
}
}
}
\ No newline at end of file
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment