44import top .ellan .mahjong .render .TableRenderSubject ;
55import top .ellan .mahjong .render .snapshot .TableRenderSnapshot ;
66import top .ellan .mahjong .render .snapshot .TableSeatRenderSnapshot ;
7+ import java .util .Collections ;
78import java .util .Comparator ;
89import java .util .EnumMap ;
910import java .util .HashMap ;
10- import java .util .HashSet ;
1111import java .util .List ;
1212import java .util .Map ;
1313import java .util .Objects ;
14- import java .util .Set ;
1514import java .util .UUID ;
1615import org .bukkit .Location ;
1716import org .bukkit .entity .Player ;
1817
1918public final class TableRenderSnapshotFactory {
19+ private static final Comparator <SerializedViewerId > SERIALIZED_VIEWER_ID_COMPARATOR =
20+ Comparator .comparing (SerializedViewerId ::serializedId );
21+
2022 public TableRenderSnapshot create (TableRenderSubject session , long version , long cancellationNonce ) {
2123 Location tableCenter = session .center ();
2224 boolean started = session .isStarted ();
2325 List <SerializedViewerId > serializedOnlineViewerIds = session .viewers ().stream ()
2426 .map (Player ::getUniqueId )
2527 .distinct ()
2628 .map (viewerId -> new SerializedViewerId (viewerId , viewerId .toString ()))
27- .sorted (Comparator . comparing ( SerializedViewerId :: serializedId ) )
29+ .sorted (SERIALIZED_VIEWER_ID_COMPARATOR )
2830 .toList ();
2931 List <UUID > onlineViewerIds = serializedOnlineViewerIds .stream ()
3032 .map (SerializedViewerId ::id )
3133 .toList ();
32- Set <UUID > onlineViewerIdSet = new HashSet <>(onlineViewerIds );
34+ Map <UUID , SerializedViewerId > serializedOnlineViewersById = new HashMap <>(
35+ Math .max (16 , (int ) (serializedOnlineViewerIds .size () / 0.75F ) + 1 )
36+ );
37+ for (SerializedViewerId viewer : serializedOnlineViewerIds ) {
38+ serializedOnlineViewersById .put (viewer .id (), viewer );
39+ }
40+ StringBuilder viewerMembershipBuffer = this .viewerMembershipBuffer (serializedOnlineViewerIds );
3341 SeatWind [] seatWinds = SeatWind .values ();
3442 EnumMap <SeatWind , UUID > seatPlayerIds = new EnumMap <>(SeatWind .class );
3543 for (SeatWind wind : seatWinds ) {
@@ -38,13 +46,28 @@ public TableRenderSnapshot create(TableRenderSubject session, long version, long
3846 Map <UUID , String > viewerMembershipSignatures = new HashMap <>();
3947 Map <UUID , List <UUID >> viewerIdsExcluding = new HashMap <>();
4048 for (UUID playerId : seatPlayerIds .values ()) {
41- if (viewerMembershipSignatures .containsKey (playerId )
42- || playerId != null && !onlineViewerIdSet .contains (playerId )) {
49+ if (viewerMembershipSignatures .containsKey (playerId )) {
50+ continue ;
51+ }
52+ SerializedViewerId excludedViewer = playerId == null
53+ ? null
54+ : serializedOnlineViewersById .get (playerId );
55+ if (playerId != null && excludedViewer == null ) {
4356 continue ;
4457 }
4558 viewerMembershipSignatures .put (
4659 playerId ,
47- this .viewerMembershipSignature (serializedOnlineViewerIds , playerId )
60+ excludedViewer == null
61+ ? viewerMembershipBuffer .toString ()
62+ : this .viewerMembershipSignature (
63+ viewerMembershipBuffer ,
64+ excludedViewer ,
65+ Collections .binarySearch (
66+ serializedOnlineViewerIds ,
67+ excludedViewer ,
68+ SERIALIZED_VIEWER_ID_COMPARATOR
69+ )
70+ )
4871 );
4972 viewerIdsExcluding .put (
5073 playerId ,
@@ -59,7 +82,7 @@ public TableRenderSnapshot create(TableRenderSubject session, long version, long
5982 session ,
6083 wind ,
6184 seatPlayerIds .get (wind ),
62- onlineViewerIdSet ,
85+ serializedOnlineViewersById ,
6386 viewerMembershipSignatures ,
6487 viewerIdsExcluding
6588 )
@@ -131,7 +154,7 @@ private TableSeatRenderSnapshot captureSeatSnapshot(
131154 TableRenderSubject session ,
132155 SeatWind wind ,
133156 UUID playerId ,
134- Set <UUID > onlineViewerIdSet ,
157+ Map <UUID , SerializedViewerId > serializedOnlineViewersById ,
135158 Map <UUID , String > viewerMembershipSignatures ,
136159 Map <UUID , List <UUID >> viewerIdsExcluding
137160 ) {
@@ -145,7 +168,7 @@ private TableSeatRenderSnapshot captureSeatSnapshot(
145168 occupied && session .isRiichi (playerId ),
146169 occupied && session .isReady (playerId ),
147170 occupied && session .isQueuedToLeave (playerId ),
148- occupied && onlineViewerIdSet . contains (playerId ),
171+ occupied && serializedOnlineViewersById . containsKey (playerId ),
149172 viewerMembershipSignatures .getOrDefault (playerId , "" ),
150173 occupied ? session .selectedHandTileIndex (playerId ) : -1 ,
151174 occupied ? session .selectedHandTileIndices (playerId ) : List .of (),
@@ -160,14 +183,25 @@ private TableSeatRenderSnapshot captureSeatSnapshot(
160183 );
161184 }
162185
163- private String viewerMembershipSignature (List <SerializedViewerId > onlineViewerIds , UUID excludedPlayerId ) {
186+ private StringBuilder viewerMembershipBuffer (List <SerializedViewerId > onlineViewerIds ) {
164187 StringBuilder builder = new StringBuilder (onlineViewerIds .size () * 36 );
165188 for (SerializedViewerId viewer : onlineViewerIds ) {
166- if (!viewer .id ().equals (excludedPlayerId )) {
167- builder .append (viewer .serializedId ());
168- }
189+ builder .append (viewer .serializedId ());
169190 }
170- return builder .toString ();
191+ return builder ;
192+ }
193+
194+ private String viewerMembershipSignature (
195+ StringBuilder viewerMembershipBuffer ,
196+ SerializedViewerId excludedViewer ,
197+ int excludedViewerIndex
198+ ) {
199+ String serializedId = excludedViewer .serializedId ();
200+ int start = excludedViewerIndex * serializedId .length ();
201+ viewerMembershipBuffer .delete (start , start + serializedId .length ());
202+ String signature = viewerMembershipBuffer .toString ();
203+ viewerMembershipBuffer .insert (start , serializedId );
204+ return signature ;
171205 }
172206
173207 private List <UUID > viewerIdsExcluding (List <UUID > onlineViewerIds , UUID excludedPlayerId ) {
0 commit comments