16 Commits

Author SHA1 Message Date
Benjamin Feyer
c907967126 adjusted the clientprperties, so it is not started in singleplayer 2024-10-13 14:19:31 +02:00
Benjamin Feyer
fe6ad576eb edited the fire, adjusted the rocket_size,added the models in j3o files, adjusted the Gamesound, added the artefacts 2024-10-13 14:18:03 +02:00
Benjamin Feyer
3755cca62e Solution for exercise 13:
edited another state in the server and client, added the rocket, added the 'Shell.java' and 'ShellControl.java'
edited the logic for the states and 3 messages for the server client comunication, edited the 'SeaSynchronizer' and ShipMapSynchronizer', so that the animations will be displayed, added the sound for the rocket
2024-10-12 00:41:24 +02:00
Benjamin Feyer
30a735bd6e added 'Shell' and 'ShellControl' and editet the two visitors 'Visitor' and 'VoidVisitor' 2024-10-10 22:23:55 +02:00
Benjamin Feyer
dffb5b4d63 corrected the server based validation in 'WaitState' and 'ServerGameLogic' and 'battleship.properties' and 'battleship_de.properties' and reformatted 'SeaSynchronizer'
corrected the 'ServerGameLogic' so it will send new GameLogic and will be still in EditorState, when presented with an invalid map
and added in the properties the keys writen in 'WaitState' and added the 'ReceivedGameLogic', to receive new GameDetails
2024-10-08 23:05:51 +02:00
Benjamin Feyer
d53e8577d8 edited 'SeaSynchronizer' and 'ShipControl' for Nr. 12
so now the fire on the ship will be displayed, the seasynchronizer handels it,
in the 'ShipControl' the sinking of a sunken ship is implemented
2024-10-08 21:20:51 +02:00
Benjamin Feyer
54d8ad57cb added the 'SeaSynchronizer'
so if the shot hits or misses, a particle is shown, hereby I modified the visit(Shot shot) handleHit
and added the 'createMissParticle' and 'createHitParticle' methods
2024-10-08 17:16:09 +02:00
Benjamin Feyer
387bda04b9 edited the 'networkDialog' and added 'battleShipLocalServer' and 'ReceivedMessage' and 'README'
edited the networkDialog so the client can decide, whether he want, to connect to a derver or create and host a new one, added the 'BattleshipLocalServer', the class responcible for creating a new server and added 'Receivedmessage'
and added a README for the Background-music licence
2024-10-05 15:33:27 +02:00
Benjamin Feyer
2110555bbc corrected the code for nr. 8 +10
now the backgroundmusic-settings will be stored correctly and when a invalid map is submitted,the error will be displayed correctly
2024-10-05 14:12:23 +02:00
Benjamin Feyer
34a0fa2304 Solution for Nr. 10, added 'BackgroundSound.java' and edited 'battleshipApp' and 'Menu'
the 'BackgroundMusic' class defines the background music and the function used to control it, in the 'BattleshipApp' is an attribute of BackgrounMusic and a return function and in the Menu the Checkbox and the slider for the backgroundMusic and the update function were implemented
2024-10-03 23:34:15 +02:00
Benjamin Feyer
6355b98441 Nr.10 edited 'Menu','Sound','battlship.properties' and 'battleship_de.properties'
edited the property files to ensure, that in the menu the background music on/off and the background volume slider are named in eng and german, edited the childnotes for
the menu, so the checkbox and slider are visible, edited the enum Suonds, for another entry 'BACKGROUNDMUSIC'
2024-10-03 13:46:18 +02:00
Benjamin Feyer
b96a3dd270 Number 9'
added README.txt for all models
2024-10-02 22:46:58 +02:00
Benjamin Feyer
b6f105202d corrected 'Editorstate' and 'GameServerLogic' and edited 'SeaSynchronizer' and added assets 2024-10-02 22:23:10 +02:00
Benjamin Feyer
175059a6e1 corrected 'EditorState' and 'ServerGameLogic' 2024-10-02 17:41:06 +02:00
Benjamin Feyer
3ab6b44638 Nr. 8, edited 'EditorState', 'ServerGameLogic' and 'ShipMapDTO' classes 2024-10-02 16:46:44 +02:00
Benjamin Feyer
237bf15992 Nr.7: edited the 'Battlestate' and 'ShipMap' class 2024-10-02 01:19:19 +02:00
115 changed files with 639586 additions and 711899 deletions

View File

@@ -0,0 +1,528 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="2409" dy="1838" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="LkLulIeU9eejG4ewMiHC-0" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Config&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from Common)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="205" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-1" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Abstract Message&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from JME)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="60" y="200" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-2" value="«interface»&lt;br&gt;&lt;b&gt;ServerSender&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="630" y="200" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-3" value="«interface»&lt;br&gt;&lt;b&gt;ClientInterpreter&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="800" y="200" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-4" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-260" y="370" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-8" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ServerMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="410" y="585" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-9" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-4" target="LkLulIeU9eejG4ewMiHC-1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="500" y="535" as="sourcePoint" />
<mxPoint x="660" y="535" as="targetPoint" />
<Array as="points">
<mxPoint x="-190" y="310" />
<mxPoint x="130" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-10" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="500" y="535" as="sourcePoint" />
<mxPoint x="130" y="240" as="targetPoint" />
<Array as="points">
<mxPoint x="480" y="310" />
<mxPoint x="130" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-11" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;MapMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-430" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-13" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShootMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-260" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-14" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationEndMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-90" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-16" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-13" target="LkLulIeU9eejG4ewMiHC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="195" y="390" as="sourcePoint" />
<mxPoint y="230" as="targetPoint" />
<Array as="points">
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-17" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-11" target="LkLulIeU9eejG4ewMiHC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="205" y="400" as="sourcePoint" />
<mxPoint x="10" y="240" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="420" />
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-18" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ServerGameLogic&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="785" y="300" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-20" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-3">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="480" y="310" as="sourcePoint" />
<mxPoint x="640" y="310" as="targetPoint" />
<Array as="points">
<mxPoint x="855" y="220" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-21" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.445;entryY=1.008;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-2">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="720" y="320" as="sourcePoint" />
<mxPoint x="880" y="320" as="targetPoint" />
<Array as="points">
<mxPoint x="680" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-22" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-23">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1226" y="340" as="sourcePoint" />
<mxPoint x="1070" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-23" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BallteshipConfig&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="300" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-24" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-23" target="LkLulIeU9eejG4ewMiHC-0">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1009" y="355" as="sourcePoint" />
<mxPoint x="1009" y="200" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-25" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BallteshipClientConfig&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="400" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-26" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-25" target="LkLulIeU9eejG4ewMiHC-23">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="904" y="520" as="sourcePoint" />
<mxPoint x="709" y="360" as="targetPoint" />
<Array as="points">
<mxPoint x="1030" y="370" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-27" value="«enum»&lt;br&gt;&lt;b&gt;ServerState&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="660" y="450" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-28" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-27">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="746" y="370" as="sourcePoint" />
<mxPoint x="560" y="200" as="targetPoint" />
<Array as="points">
<mxPoint x="820" y="390" />
<mxPoint x="743" y="390" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-29" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Player&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="810" y="465" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-31" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-29">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="830" y="330" as="sourcePoint" />
<mxPoint x="870" y="460" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-32" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShipMap&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="810" y="550" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-33" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-29" target="LkLulIeU9eejG4ewMiHC-32">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="865" y="280" as="sourcePoint" />
<mxPoint x="865" y="425" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-34" value="«interface»&lt;br&gt;&lt;b&gt;GameEventBroker&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="535" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-35" value="«interface»&lt;br&gt;&lt;b&gt;ServerInterpreter&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1110" y="535" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-36" value="«interface»&lt;br&gt;&lt;b&gt;ClientSender&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1112" y="735" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-37" value="«interface»&lt;br&gt;&lt;b&gt;gameEventListener&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1112" y="805" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-38" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientGameLogic&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="800" y="750" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-39" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-44">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="865" y="445" as="sourcePoint" />
<mxPoint x="865" y="560" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-40" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-36">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="867" y="755" as="sourcePoint" />
<mxPoint x="867" y="625" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-41" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-37">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="877" y="765" as="sourcePoint" />
<mxPoint x="877" y="635" as="targetPoint" />
<Array as="points">
<mxPoint x="883" y="830" />
<mxPoint x="1062" y="830" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-42" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="LkLulIeU9eejG4ewMiHC-34">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1015" y="550" as="targetPoint" />
<Array as="points">
<mxPoint x="880" y="660" />
<mxPoint x="1020" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-43" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="LkLulIeU9eejG4ewMiHC-35">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1190" y="640" as="targetPoint" />
<Array as="points">
<mxPoint x="880" y="660" />
<mxPoint x="1020" y="660" />
<mxPoint x="1176" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-44" value="3" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="840" y="570" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-45" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="827" y="435" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-47" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="800" y="848" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-48" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="830" y="790" as="sourcePoint" />
<mxPoint x="830" y="820" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-49" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-47" target="LkLulIeU9eejG4ewMiHC-38">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="892" y="865" as="sourcePoint" />
<mxPoint x="852" y="815" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-50" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;GameDetails&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="580" y="750" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-51" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-50">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="740" y="835" as="sourcePoint" />
<mxPoint x="740" y="715" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-52" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;StartBattleMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="420" y="750" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-54" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationStartMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="250" y="750" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-55" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BackToBattleStateMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="45" y="750" width="170" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-56" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-52" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="827" y="470" as="sourcePoint" />
<mxPoint x="477" y="310" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-57" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-54" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="510" y="710" as="sourcePoint" />
<mxPoint x="488" y="285" as="targetPoint" />
<Array as="points">
<mxPoint x="320" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-58" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-55" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="360" y="710" as="sourcePoint" />
<mxPoint x="490" y="280" as="targetPoint" />
<Array as="points">
<mxPoint x="130" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-59" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-50" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="510" y="710" as="sourcePoint" />
<mxPoint x="488" y="285" as="targetPoint" />
<Array as="points">
<mxPoint x="640" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-60" value="«interface»&lt;br&gt;&lt;b&gt;Item&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-220" y="535" width="140" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-61" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;EffectMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-140" y="750" width="170" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-62" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="30" y="680" as="sourcePoint" />
<mxPoint x="384" y="250" as="targetPoint" />
<Array as="points">
<mxPoint x="-55" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-63" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Shot&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-170" y="650" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-64" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleShip&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-390" y="650" width="113" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-65" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Shell&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-260" y="650" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-66" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-32" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="270" y="485" as="sourcePoint" />
<mxPoint x="270" y="365" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-67" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-85" y="528" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-68" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-20" y="470" as="sourcePoint" />
<mxPoint x="-190" y="390" as="targetPoint" />
<Array as="points">
<mxPoint x="-20" y="420" />
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-69" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-63" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-70.42000000000007" y="750" as="sourcePoint" />
<mxPoint x="-70.42000000000007" y="590" as="targetPoint" />
<Array as="points">
<mxPoint x="-125" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-70" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-64" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-115" y="660" as="sourcePoint" />
<mxPoint x="-150" y="590" as="targetPoint" />
<Array as="points">
<mxPoint x="-333" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-71" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-65" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-233" y="660" as="sourcePoint" />
<mxPoint x="-175" y="595" as="targetPoint" />
<Array as="points">
<mxPoint x="-225" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-72" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.088;exitY=0.02;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-63">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="370" y="690" as="sourcePoint" />
<mxPoint x="-70" y="570" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-73" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-64">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-115" y="760" as="sourcePoint" />
<mxPoint x="-115" y="680" as="targetPoint" />
<Array as="points">
<mxPoint x="-305" y="760" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-74" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-335" y="668" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-75" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-11" target="LkLulIeU9eejG4ewMiHC-64">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-393.5" y="535" as="sourcePoint" />
<mxPoint x="-586.5" y="445" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="560" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-76" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-390" y="620" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-79" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;WaitState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="540" y="930" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-80" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="660" y="930" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-81" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;InitialState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="795" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-82" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="930" y="930" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-83" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;GameOverState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1060" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-84" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;EditorState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="400" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-85" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-81" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="820" y="1020" as="sourcePoint" />
<mxPoint x="940" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-86" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-80" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="860" y="940" as="sourcePoint" />
<mxPoint x="940" y="860" as="targetPoint" />
<Array as="points">
<mxPoint x="715" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-87" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-79" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="628" y="925" as="sourcePoint" />
<mxPoint x="890" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="590" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-89" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-82" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="877" y="950" as="sourcePoint" />
<mxPoint x="920" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="985" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-90" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-83" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1120" y="920" as="sourcePoint" />
<mxPoint x="840" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="1120" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-91" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-84" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="503" y="910" as="sourcePoint" />
<mxPoint x="800" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="460" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-92" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-84" target="LkLulIeU9eejG4ewMiHC-64">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="380" y="830" as="sourcePoint" />
<mxPoint x="40" y="870" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="940" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-93" value="2" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-390" y="680" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-94" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1085" y="838" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-95" value="«enum»&lt;br&gt;&lt;b&gt;Rotation&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-550" y="635" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-96" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleShipDTO&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-550" y="735" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-97" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShipMaoDTO&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-550" y="800" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-98" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-96" target="LkLulIeU9eejG4ewMiHC-95">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-420.8" y="778" as="sourcePoint" />
<mxPoint x="-420.8" y="698" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-99" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-97" target="LkLulIeU9eejG4ewMiHC-96">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-485" y="745" as="sourcePoint" />
<mxPoint x="-485" y="695" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-100" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-495" y="760" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-101" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-64" target="LkLulIeU9eejG4ewMiHC-95">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-485" y="745" as="sourcePoint" />
<mxPoint x="-485" y="695" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@@ -0,0 +1,527 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="1192" dy="424" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="LkLulIeU9eejG4ewMiHC-0" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Config&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from Common)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="205" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-1" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Abstract Message&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from JME)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="60" y="200" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-2" value="«interface»&lt;br&gt;&lt;b&gt;ServerSender&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="630" y="200" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-3" value="«interface»&lt;br&gt;&lt;b&gt;ClientInterpreter&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="800" y="200" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-4" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-260" y="370" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-8" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ServerMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="410" y="585" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-9" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-4" target="LkLulIeU9eejG4ewMiHC-1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="500" y="535" as="sourcePoint" />
<mxPoint x="660" y="535" as="targetPoint" />
<Array as="points">
<mxPoint x="-190" y="310" />
<mxPoint x="130" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-10" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="500" y="535" as="sourcePoint" />
<mxPoint x="130" y="240" as="targetPoint" />
<Array as="points">
<mxPoint x="480" y="310" />
<mxPoint x="130" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-11" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;MapMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-430" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-13" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShootMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-260" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-14" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationEndMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;strokeColor=#FF0000;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-90" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-16" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-13" target="LkLulIeU9eejG4ewMiHC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="195" y="390" as="sourcePoint" />
<mxPoint y="230" as="targetPoint" />
<Array as="points">
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-17" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-11" target="LkLulIeU9eejG4ewMiHC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="205" y="400" as="sourcePoint" />
<mxPoint x="10" y="240" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="420" />
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-18" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ServerGameLogic&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="785" y="300" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-20" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-3">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="480" y="310" as="sourcePoint" />
<mxPoint x="640" y="310" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-21" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.445;entryY=1.008;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-2">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="720" y="320" as="sourcePoint" />
<mxPoint x="880" y="320" as="targetPoint" />
<Array as="points">
<mxPoint x="680" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-22" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-23">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1226" y="340" as="sourcePoint" />
<mxPoint x="1070" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-23" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BallteshipConfig&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="300" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-24" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-23" target="LkLulIeU9eejG4ewMiHC-0">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1009" y="355" as="sourcePoint" />
<mxPoint x="1009" y="200" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-25" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BallteshipClientConfig&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="400" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-26" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-25" target="LkLulIeU9eejG4ewMiHC-23">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="904" y="520" as="sourcePoint" />
<mxPoint x="709" y="360" as="targetPoint" />
<Array as="points">
<mxPoint x="1030" y="370" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-27" value="«enum»&lt;br&gt;&lt;b&gt;ServerState&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="660" y="450" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-28" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=0.75;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-27">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="746" y="370" as="sourcePoint" />
<mxPoint x="560" y="200" as="targetPoint" />
<Array as="points">
<mxPoint x="820" y="390" />
<mxPoint x="743" y="390" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-29" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Player&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="810" y="465" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-31" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-29">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="830" y="330" as="sourcePoint" />
<mxPoint x="870" y="460" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-32" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShipMap&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="810" y="550" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-33" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-29" target="LkLulIeU9eejG4ewMiHC-32">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="865" y="280" as="sourcePoint" />
<mxPoint x="865" y="425" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-34" value="«interface»&lt;br&gt;&lt;b&gt;GameEventBroker&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="960" y="535" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-35" value="«interface»&lt;br&gt;&lt;b&gt;ServerInterpreter&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1110" y="535" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-36" value="«interface»&lt;br&gt;&lt;b&gt;ClientSender&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1112" y="735" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-37" value="«interface»&lt;br&gt;&lt;b&gt;gameEventListener&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1112" y="805" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-38" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientGameLogic&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="800" y="750" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-39" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-44">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="865" y="445" as="sourcePoint" />
<mxPoint x="865" y="560" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-40" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-36">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="867" y="755" as="sourcePoint" />
<mxPoint x="867" y="625" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-41" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-37">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="877" y="765" as="sourcePoint" />
<mxPoint x="877" y="635" as="targetPoint" />
<Array as="points">
<mxPoint x="883" y="830" />
<mxPoint x="1062" y="830" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-42" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="LkLulIeU9eejG4ewMiHC-34">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1015" y="550" as="targetPoint" />
<Array as="points">
<mxPoint x="880" y="660" />
<mxPoint x="1020" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-43" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="LkLulIeU9eejG4ewMiHC-35">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1190" y="640" as="targetPoint" />
<Array as="points">
<mxPoint x="880" y="660" />
<mxPoint x="1020" y="660" />
<mxPoint x="1176" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-44" value="3" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="840" y="570" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-45" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="827" y="435" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-47" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="800" y="848" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-48" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="830" y="790" as="sourcePoint" />
<mxPoint x="830" y="820" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-49" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-47" target="LkLulIeU9eejG4ewMiHC-38">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="892" y="865" as="sourcePoint" />
<mxPoint x="852" y="815" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-50" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;GameDetails&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="580" y="750" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-51" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-50">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="740" y="835" as="sourcePoint" />
<mxPoint x="740" y="715" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-52" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;StartBattleMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="420" y="750" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-54" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationStartMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="250" y="750" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-55" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BackToBattleStateMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="45" y="750" width="170" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-56" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-52" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="827" y="470" as="sourcePoint" />
<mxPoint x="477" y="310" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-57" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fillColor=#FF0000;exitX=0.5;exitY=0;exitDx=0;exitDy=0;strokeColor=#FF0000;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-54" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="280" y="700" as="sourcePoint" />
<mxPoint x="488" y="285" as="targetPoint" />
<Array as="points">
<mxPoint x="320" y="690" />
<mxPoint x="320" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-58" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#FF0000;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-55" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="360" y="710" as="sourcePoint" />
<mxPoint x="490" y="280" as="targetPoint" />
<Array as="points">
<mxPoint x="130" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-59" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-50" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="510" y="710" as="sourcePoint" />
<mxPoint x="488" y="285" as="targetPoint" />
<Array as="points">
<mxPoint x="640" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-60" value="«interface»&lt;br&gt;&lt;b&gt;Item&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-220" y="535" width="140" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-61" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;EffectMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-140" y="750" width="170" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-62" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-8">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="30" y="680" as="sourcePoint" />
<mxPoint x="384" y="250" as="targetPoint" />
<Array as="points">
<mxPoint x="-55" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-63" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Shot&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-170" y="650" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-64" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleShip&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-390" y="650" width="113" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-65" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Shell&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-260" y="650" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-66" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-32" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="270" y="485" as="sourcePoint" />
<mxPoint x="270" y="365" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-67" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-85" y="528" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-68" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#FF0000;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-20" y="470" as="sourcePoint" />
<mxPoint x="-190" y="390" as="targetPoint" />
<Array as="points">
<mxPoint x="-20" y="420" />
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-69" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-63" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-70.42000000000007" y="750" as="sourcePoint" />
<mxPoint x="-70.42000000000007" y="590" as="targetPoint" />
<Array as="points">
<mxPoint x="-125" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-70" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-64" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-115" y="660" as="sourcePoint" />
<mxPoint x="-150" y="590" as="targetPoint" />
<Array as="points">
<mxPoint x="-333" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-71" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#FF0000;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-65" target="LkLulIeU9eejG4ewMiHC-60">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-233" y="660" as="sourcePoint" />
<mxPoint x="-175" y="595" as="targetPoint" />
<Array as="points">
<mxPoint x="-225" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-72" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.088;exitY=0.02;exitDx=0;exitDy=0;exitPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-63">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="370" y="690" as="sourcePoint" />
<mxPoint x="-70" y="570" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-73" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-64">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-115" y="760" as="sourcePoint" />
<mxPoint x="-115" y="680" as="targetPoint" />
<Array as="points">
<mxPoint x="-305" y="760" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-74" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-335" y="668" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-75" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-11" target="LkLulIeU9eejG4ewMiHC-64">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-393.5" y="535" as="sourcePoint" />
<mxPoint x="-586.5" y="445" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="560" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-76" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-390" y="620" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-79" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;WaitState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="540" y="930" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-80" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="660" y="930" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-81" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;InitialState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="795" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-82" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="930" y="930" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-83" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;GameOverState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1060" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-84" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;EditorState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="400" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-85" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-81" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="820" y="1020" as="sourcePoint" />
<mxPoint x="940" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-86" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-80" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="860" y="940" as="sourcePoint" />
<mxPoint x="940" y="860" as="targetPoint" />
<Array as="points">
<mxPoint x="715" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-87" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-79" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="628" y="925" as="sourcePoint" />
<mxPoint x="890" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="590" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-89" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fillColor=#FF0000;strokeColor=#FF0000;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-82" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="877" y="950" as="sourcePoint" />
<mxPoint x="920" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="985" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-90" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-83" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1120" y="920" as="sourcePoint" />
<mxPoint x="840" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="1120" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-91" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-84" target="LkLulIeU9eejG4ewMiHC-47">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="503" y="910" as="sourcePoint" />
<mxPoint x="800" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="460" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-92" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-84" target="LkLulIeU9eejG4ewMiHC-64">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="380" y="830" as="sourcePoint" />
<mxPoint x="40" y="870" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="940" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-93" value="2" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-390" y="680" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-94" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1085" y="838" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-95" value="«enum»&lt;br&gt;&lt;b&gt;Rotation&lt;/b&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-550" y="635" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-96" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleShipDTO&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-550" y="735" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-97" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShipMaoDTO&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-550" y="800" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-98" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-96" target="LkLulIeU9eejG4ewMiHC-95">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-420.8" y="778" as="sourcePoint" />
<mxPoint x="-420.8" y="698" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-99" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-97" target="LkLulIeU9eejG4ewMiHC-96">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-485" y="745" as="sourcePoint" />
<mxPoint x="-485" y="695" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-100" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="-495" y="760" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-101" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-64" target="LkLulIeU9eejG4ewMiHC-95">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-485" y="745" as="sourcePoint" />
<mxPoint x="-485" y="695" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@@ -0,0 +1,174 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram name="Seite-1" id="CSCMTvoyx8GfkIWIgrj5">
<mxGraphModel dx="2171" dy="1811" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="8jlTEtXbO0kP9G_WUDS2-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-2" target="8jlTEtXbO0kP9G_WUDS2-8">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-2" target="8jlTEtXbO0kP9G_WUDS2-12">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-2" value="" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="70" y="320" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-6" value="addPlayer(id)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="130" y="290" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-7" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="-10" y="358" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-8" target="8jlTEtXbO0kP9G_WUDS2-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-8" target="8jlTEtXbO0kP9G_WUDS2-16">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-8" value="Set up" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="72.5" y="450" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-11" value="[players.size()=2]/send GameDetail messages" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="125" y="360" width="270" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-12" target="8jlTEtXbO0kP9G_WUDS2-2">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-12" value="" style="ellipse;fillColor=strokeColor;html=1;" vertex="1" parent="1">
<mxGeometry x="15" y="260" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-16" target="8jlTEtXbO0kP9G_WUDS2-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-16" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="170" y="520" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-19" value="received MapMessage&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="220" y="470" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-20" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="50" y="588" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-21" target="8jlTEtXbO0kP9G_WUDS2-24">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-21" value="Battle" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="172.5" y="640" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-23" value="[readyPlayers.size() = 2]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="220" y="585" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-24">
<mxGeometry relative="1" as="geometry">
<mxPoint x="342.3548387096773" y="830" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-24" value="Animation wait" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="285" y="680" width="115" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-29" target="8jlTEtXbO0kP9G_WUDS2-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-29" target="8jlTEtXbO0kP9G_WUDS2-31">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-29" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="302.5" y="830" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-31" value="Game over" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="285" y="960" width="115" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-33" value="[game over]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="345" y="888" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-34" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="205" y="860" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-35" target="8jlTEtXbO0kP9G_WUDS2-38">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-35" value="" style="ellipse;fillColor=strokeColor;html=1;" vertex="1" parent="1">
<mxGeometry x="550" y="260" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-41" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-38" target="8jlTEtXbO0kP9G_WUDS2-40">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-38" value="Initial State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="670" y="265" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-44" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-40" target="8jlTEtXbO0kP9G_WUDS2-43">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-40" value="Editor State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="670" y="358" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-42" value="receivedGameDetails(details)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="720" y="298" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-45" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-43" target="8jlTEtXbO0kP9G_WUDS2-40">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-51" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-43" target="8jlTEtXbO0kP9G_WUDS2-50">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-43" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="780" y="470" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-46" value="mapFinished" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="815" y="368" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-47" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="680" y="498" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-65" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-50" target="8jlTEtXbO0kP9G_WUDS2-52">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-50" value="Wait Stata" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="782.5" y="575" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-54" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-52" target="8jlTEtXbO0kP9G_WUDS2-53">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-52" value="Battle State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="782.5" y="690" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-53" target="8jlTEtXbO0kP9G_WUDS2-56">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-53" value="Animation State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="940" y="760" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-55" value="receivedAnimationMessage(msg)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="900" y="660" width="200" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-59" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-56" target="8jlTEtXbO0kP9G_WUDS2-52">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="8jlTEtXbO0kP9G_WUDS2-56" target="8jlTEtXbO0kP9G_WUDS2-61">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-56" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="955" y="878" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-60" value="receivedBackToBattleStateMessage(msg)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1030" y="810" width="250" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-61" value="game over" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="940" y="970" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-63" value="[game over]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1005" y="930" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-64" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="832" y="918" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-66" value="[horbor&amp;nbsp; empty] / send MapMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="832" y="525" width="220" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-67" value="receivedStartBattle(msg)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="827" y="610" width="160" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

View File

@@ -0,0 +1,654 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram name="Page-1" id="2a216829-ef6e-dabb-86c1-c78162f3ba2b">
<mxGraphModel dx="2009" dy="2329" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" background="none" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="Sf4z-aHPgcdhoojVuiNO-13" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="300" y="280" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="7a84cebc1def654-34" value="" style="shape=message;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="310" y="295" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-29" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-1" target="Sf4z-aHPgcdhoojVuiNO-27">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-1" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="100" y="180" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-2" value="start client 1" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="110" y="260" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-3" target="Sf4z-aHPgcdhoojVuiNO-10">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-3" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="100" y="340" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-4" value="start server" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="110" y="420" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-5" target="Sf4z-aHPgcdhoojVuiNO-23">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-5" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="100" y="500" width="80" height="80" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-8" value="start cleint 2" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
<mxGeometry x="110" y="580" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-10" target="Sf4z-aHPgcdhoojVuiNO-14">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-10" target="Sf4z-aHPgcdhoojVuiNO-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-10" value="" style="shape=mxgraph.bpmn.shape;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=parallelGw;" vertex="1" parent="1">
<mxGeometry x="240" y="355" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-13" target="Sf4z-aHPgcdhoojVuiNO-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-14" target="Sf4z-aHPgcdhoojVuiNO-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-14" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="300" y="420" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-37" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-17" target="Sf4z-aHPgcdhoojVuiNO-31">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-17" value="" style="shape=mxgraph.bpmn.shape;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=parallelGw;" vertex="1" parent="1">
<mxGeometry x="390" y="355" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-22" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="310" y="435" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-48" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-23" target="Sf4z-aHPgcdhoojVuiNO-42">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-23" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="300" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-24" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="310" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-46" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-27" target="Sf4z-aHPgcdhoojVuiNO-44">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-27" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="300" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-28" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="310" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-38" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-31" target="Sf4z-aHPgcdhoojVuiNO-33">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-31" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="470" y="350" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-32" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="480" y="365" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-39" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-33" target="Sf4z-aHPgcdhoojVuiNO-35">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-33" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="600" y="350" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-34" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="610" y="365" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-55" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-35" target="Sf4z-aHPgcdhoojVuiNO-52">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-57" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-35" target="Sf4z-aHPgcdhoojVuiNO-50">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-35" value="" style="shape=mxgraph.bpmn.shape;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=parallelGw;" vertex="1" parent="1">
<mxGeometry x="730" y="355" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-62" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-40" target="Sf4z-aHPgcdhoojVuiNO-60">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-40" value="edit ship map" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="600" y="190" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-63" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-41" target="Sf4z-aHPgcdhoojVuiNO-58">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-41" value="edit ship map" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="730" y="510" width="90" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-49" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-42" target="Sf4z-aHPgcdhoojVuiNO-41">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-42" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="600" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-43" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="610" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-47" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-44" target="Sf4z-aHPgcdhoojVuiNO-40">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-44" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="470" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-45" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="480" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-67" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-50" target="Sf4z-aHPgcdhoojVuiNO-64">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-50" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="865" y="280" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-51" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="875" y="295" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-66" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-52" target="Sf4z-aHPgcdhoojVuiNO-65">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-52" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="865" y="420" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-53" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="875" y="435" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-89" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-58" target="Sf4z-aHPgcdhoojVuiNO-87">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-58" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="865" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-59" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="875" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-90" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-60" target="Sf4z-aHPgcdhoojVuiNO-85">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-60" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="865" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-61" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="875" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-69" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-64" target="Sf4z-aHPgcdhoojVuiNO-68">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-64" value="save player 1 map" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="980" y="280" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-70" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-65" target="Sf4z-aHPgcdhoojVuiNO-68">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-65" value="save player 2 map" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="980" y="420" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-81" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-68" target="Sf4z-aHPgcdhoojVuiNO-77">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-68" value="" style="shape=mxgraph.bpmn.shape;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=parallelGw;" vertex="1" parent="1">
<mxGeometry x="1160" y="355" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-76" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-77" target="Sf4z-aHPgcdhoojVuiNO-79">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-77" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1260" y="350" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-78" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1270" y="365" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-108" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-79" target="Sf4z-aHPgcdhoojVuiNO-103">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-79" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1390" y="350" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-80" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1400" y="365" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-107" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-85" target="Sf4z-aHPgcdhoojVuiNO-105">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-85" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1260" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-86" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1270" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-156" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-87" target="Sf4z-aHPgcdhoojVuiNO-147">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-87" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1390" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-88" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1400" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-145" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-91" target="Sf4z-aHPgcdhoojVuiNO-141">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-91" value="process shot" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1650" y="350" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-92" value="connect" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="300" y="570" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-93" value="connect" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="300" y="160" width="70" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-94" value="send GameDetails" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="440" y="410" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-95" value="send GameDetails" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="570" y="320" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-96" value="send MapMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="835" y="570" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-97" value="send MapMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="835" y="160" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-100" value="send StartBattleMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1210" y="410" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-101" value="send StartBattleMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1340" y="320" width="160" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-109" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-103" target="Sf4z-aHPgcdhoojVuiNO-91">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-103" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1520" y="350" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-104" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1530" y="365" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-155" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-105" target="Sf4z-aHPgcdhoojVuiNO-149">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-105" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1520" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-106" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1530" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-110" value="send ShotMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1485" y="160" width="130" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-112" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="325" y="500" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-116" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-112" target="Sf4z-aHPgcdhoojVuiNO-14">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="350" y="490" as="sourcePoint" />
<mxPoint x="510" y="490" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-119" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="495" y="340" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-120" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-119">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="520" y="330" as="sourcePoint" />
<mxPoint x="500" y="250" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-121" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="890" y="500" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-122" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-121">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="915" y="490" as="sourcePoint" />
<mxPoint x="895" y="480" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-127" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="625" y="410" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-129" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-127" target="Sf4z-aHPgcdhoojVuiNO-42">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="410" y="400" as="sourcePoint" />
<mxPoint x="570" y="400" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-131" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="325" y="250" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-132" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-131">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="110" y="240" as="sourcePoint" />
<mxPoint x="330" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-133" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="890" y="250" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-134" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-133">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="675" y="240" as="sourcePoint" />
<mxPoint x="895" y="280" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-135" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1415" y="410" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-136" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-135">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1200" y="400" as="sourcePoint" />
<mxPoint x="1420" y="510" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-137" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1545" y="250" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-138" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-137">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1330" y="240" as="sourcePoint" />
<mxPoint x="1550" y="350" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-139" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1285" y="340" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-140" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-139" target="Sf4z-aHPgcdhoojVuiNO-85">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1070" y="330" as="sourcePoint" />
<mxPoint x="1290" y="440" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-146" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-141" target="Sf4z-aHPgcdhoojVuiNO-143">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-141" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1830" y="350" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-142" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1840" y="365" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-188" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-143" target="Sf4z-aHPgcdhoojVuiNO-178">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-143" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1970" y="350" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-144" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1980" y="365" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-163" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-147" target="Sf4z-aHPgcdhoojVuiNO-161">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-147" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1970" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-148" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1980" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-162" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-149" target="Sf4z-aHPgcdhoojVuiNO-160">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-149" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1830" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-150" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1840" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-151" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1995" y="410" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-152" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-151">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1780" y="400" as="sourcePoint" />
<mxPoint x="2000" y="510" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-154" value="send AnimationStartMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1910" y="320" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-157" value="" style="ellipse;whiteSpace=wrap;html=1;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="1855" y="340" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-158" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-157">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1865" y="336.07000000000016" as="sourcePoint" />
<mxPoint x="1859.88" y="250" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-159" value="send AnimationStartMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="1770" y="428" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-196" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-160" target="Sf4z-aHPgcdhoojVuiNO-194">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-160" value="Animate the shot" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="1960" y="190" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-199" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-161">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2260" y="539.8947368421054" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-161" value="Animate the shot" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2090" y="510" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-176" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-178" target="Sf4z-aHPgcdhoojVuiNO-182">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-191" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-178" target="Sf4z-aHPgcdhoojVuiNO-189">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-178" value="" style="shape=mxgraph.bpmn.shape;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=parallelGw;" vertex="1" parent="1">
<mxGeometry x="2130" y="355" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-179" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2325" y="310" as="sourcePoint" />
<mxPoint x="2380" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-181" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-182">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2380" y="450" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-182" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2265" y="420" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-183" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2275" y="435" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-189" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2265" y="280" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-190" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2275" y="295" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-210" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-194" target="Sf4z-aHPgcdhoojVuiNO-206">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-194" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2265" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-195" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2275" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-211" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-197" target="Sf4z-aHPgcdhoojVuiNO-208">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-197" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2265" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-198" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2275" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-225" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-202" target="Sf4z-aHPgcdhoojVuiNO-215">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-202" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2380" y="420" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-203" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2390" y="435" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-224" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-204" target="Sf4z-aHPgcdhoojVuiNO-217">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-204" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2380" y="280" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-205" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2390" y="295" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-223" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-206" target="Sf4z-aHPgcdhoojVuiNO-219">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-206" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2380" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-207" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2390" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-226" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-208" target="Sf4z-aHPgcdhoojVuiNO-221">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-208" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2380" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-209" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2390" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-229" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-215" target="Sf4z-aHPgcdhoojVuiNO-227">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-215" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2540" y="420" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-216" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2550" y="435" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-228" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-217" target="Sf4z-aHPgcdhoojVuiNO-227">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-217" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2540" y="280" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-218" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2550" y="295" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-219" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2540" y="190" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-220" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2550" y="205" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-221" value="" style="ellipse;shape=doubleEllipse;html=1;dashed=0;whiteSpace=wrap;aspect=fixed;" vertex="1" parent="1">
<mxGeometry x="2540" y="510" width="60" height="60" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-222" value="" style="shape=message;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2550" y="525" width="40" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-227" value="" style="shape=mxgraph.bpmn.shape;html=1;verticalLabelPosition=bottom;labelBackgroundColor=#ffffff;verticalAlign=top;perimeter=rhombusPerimeter;background=gateway;outline=none;symbol=parallelGw;" vertex="1" parent="1">
<mxGeometry x="2720" y="345" width="50" height="50" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-230" value="send animationEndMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="2200" y="160" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-231" value="send animationEndMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="2210" y="570" width="170" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-232" value="send Effect Message" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="2340" y="340" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-234" value="send Effect Message" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="2340" y="390" width="140" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-235" value="send BackToBattleStateMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="2480" y="340" width="200" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-236" value="send BackToBattleStateMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="1">
<mxGeometry x="2490" y="390" width="200" height="30" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-244" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2290" y="500" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-245" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-244">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="2315" y="490" as="sourcePoint" />
<mxPoint x="2295" y="480" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-248" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="2409.71" y="269.9999999999998" as="sourcePoint" />
<mxPoint x="2409.71" y="250" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-250" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2565" y="270" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-251" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-250">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="2590" y="260" as="sourcePoint" />
<mxPoint x="2570" y="250" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-253" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-247">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="2294.71" y="260" as="sourcePoint" />
<mxPoint x="2294.71" y="279.9999999999998" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-254" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2405" y="270" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-256" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" target="Sf4z-aHPgcdhoojVuiNO-247">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="2294.71" y="260" as="sourcePoint" />
<mxPoint x="2294.71" y="279.9999999999998" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-247" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2290" y="250" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-257" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-258">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="2409.71" y="490" as="sourcePoint" />
<mxPoint x="2409.71" y="509.9999999999998" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-258" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2405" y="480" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-259" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-260">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="2569.71" y="490" as="sourcePoint" />
<mxPoint x="2569.71" y="509.9999999999998" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-260" value="" style="ellipse;whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2565" y="480" width="10" height="10" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-261" value="Game Play" style="whiteSpace=wrap;html=1;" vertex="1" parent="1">
<mxGeometry x="2870" y="110" width="120" height="490" as="geometry" />
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-265" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-227">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2870" y="370" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-267" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-219">
<mxGeometry relative="1" as="geometry">
<mxPoint x="2870" y="220" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="Sf4z-aHPgcdhoojVuiNO-268" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=-0.018;entryY=0.878;entryDx=0;entryDy=0;entryPerimeter=0;" edge="1" parent="1" source="Sf4z-aHPgcdhoojVuiNO-221" target="Sf4z-aHPgcdhoojVuiNO-261">
<mxGeometry relative="1" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

View File

@@ -0,0 +1,475 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="1538" dy="866" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="TwrB0rHwIU3CN8L-tBzC-1" value="«interface»&lt;br&gt;&lt;b&gt;GameEventBroker&lt;/b&gt;&lt;div&gt;&lt;b&gt;(from model)&lt;/b&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1140" y="535" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-2" value="«interface»&lt;br&gt;&lt;b&gt;ServerInterpreter&lt;/b&gt;&lt;div&gt;&lt;b&gt;(from model)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="954.5" y="535" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-3" value="«interface»&lt;br&gt;&lt;b&gt;ClientSender&lt;/b&gt;&lt;div&gt;&lt;b&gt;(from model)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="320" y="720" width="150" height="50" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-4" value="«interface»&lt;br&gt;&lt;b&gt;gameEventListener&lt;/b&gt;&lt;div&gt;&lt;b&gt;(from model)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="790" y="800" width="131" height="60" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-5" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientGameLogic&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from Model)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="965" y="730" width="110" height="40" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-6" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-5" target="TwrB0rHwIU3CN8L-tBzC-16">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="865" y="445" as="sourcePoint" />
<mxPoint x="865" y="560" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-7" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-5" target="TwrB0rHwIU3CN8L-tBzC-3">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="867" y="755" as="sourcePoint" />
<mxPoint x="690" y="750" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-8" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-5" target="TwrB0rHwIU3CN8L-tBzC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="877" y="765" as="sourcePoint" />
<mxPoint x="877" y="635" as="targetPoint" />
<Array as="points">
<mxPoint x="993" y="830" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-9" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-5" target="TwrB0rHwIU3CN8L-tBzC-1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1015" y="550" as="targetPoint" />
<Array as="points">
<mxPoint x="1020" y="660" />
<mxPoint x="1200" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-10" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-5" target="TwrB0rHwIU3CN8L-tBzC-2">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1190" y="640" as="targetPoint" />
<Array as="points">
<mxPoint x="1020" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-11" value="3" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1594" y="720" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-15" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="921" y="830" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-16" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b style=&quot;background-color: initial;&quot;&gt;ShipMap&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b style=&quot;background-color: initial;&quot;&gt;(from Model)&lt;/b&gt;&lt;br&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1660" y="730" width="110" height="40" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-20" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-16" target="TwrB0rHwIU3CN8L-tBzC-1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1300" y="630" as="sourcePoint" />
<mxPoint x="1585" y="630" as="targetPoint" />
<Array as="points">
<mxPoint x="1715" y="560" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-21" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleshipAppState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="600" y="920" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-22" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleshipApp&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="930" y="920" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-23" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;GameSound&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="740" y="920" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-24" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleshipAppConfig&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1170" y="920" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-25" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;SeaSynchronizer&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1400" y="1020" width="130" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-26" value="«interface»&lt;br&gt;&lt;b&gt;BattleshipClient&lt;/b&gt;&lt;div&gt;&lt;b&gt;(from model)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1180" y="800" width="131" height="60" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-27" value="«interface»&lt;br&gt;&lt;div&gt;&lt;b&gt;Visitor &amp;lt;Spatial&amp;gt;&lt;/b&gt;&lt;/div&gt;&lt;div&gt;&lt;b&gt;(from model)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1329" y="800" width="131" height="60" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-28" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ModelViewSynchronizer&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&amp;lt;Item&amp;gt;&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from JME-Common)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1494" y="800" width="160" height="60" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-29" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;SimpleApplication&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b style=&quot;background-color: initial;&quot;&gt;(from JME)&lt;/b&gt;&lt;br&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1040" y="800" width="121" height="60" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-31" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShipMapSynchronizer&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1464" y="920" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-32" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;MapViewSynchronizer&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1530" y="1020" width="160" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-33" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;EditorAppState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="560" y="1020" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-34" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleAppState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="670" y="1020" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-35" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;SeaAppState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="790" y="1020" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-36" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;MapView&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="727" y="1120" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-37" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;DialogManager&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from LME-Common)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1080" y="1100" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-38" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Dialog&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from LME-Common)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1257.5" y="1100" width="125" height="40" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-39" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;NetworkDialog&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1250" y="1300" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-41" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;SimpleDialog&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from LME-Common)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1260" y="1200" width="120" height="40" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-42" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Menu&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1120" y="1200" width="117.5" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-43" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;NetworkSupport&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="240" y="1349" width="130" height="20" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-44" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Abstract&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AppState&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from JME)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="600" y="800" width="120" height="60" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-45" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-22" target="TwrB0rHwIU3CN8L-tBzC-29">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1080" y="970" as="sourcePoint" />
<mxPoint x="1240" y="970" as="targetPoint" />
<Array as="points">
<mxPoint x="1101" y="890" />
</Array>
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-49" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-21" target="TwrB0rHwIU3CN8L-tBzC-44">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1070" y="990" as="sourcePoint" />
<mxPoint x="1230" y="990" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-50" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-41" target="TwrB0rHwIU3CN8L-tBzC-38">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1080" y="1000" as="sourcePoint" />
<mxPoint x="1240" y="1000" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-51" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-42" target="TwrB0rHwIU3CN8L-tBzC-38">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1090" y="1010" as="sourcePoint" />
<mxPoint x="1250" y="1010" as="targetPoint" />
<Array as="points">
<mxPoint x="1290" y="1180" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-52" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-39" target="TwrB0rHwIU3CN8L-tBzC-41">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1100" y="1020" as="sourcePoint" />
<mxPoint x="1260" y="1020" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-53" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-31" target="TwrB0rHwIU3CN8L-tBzC-28">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1110" y="1030" as="sourcePoint" />
<mxPoint x="1270" y="1030" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-54" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-33" target="TwrB0rHwIU3CN8L-tBzC-21">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1120" y="1040" as="sourcePoint" />
<mxPoint x="1280" y="1040" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-55" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-34" target="TwrB0rHwIU3CN8L-tBzC-21">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1130" y="1050" as="sourcePoint" />
<mxPoint x="1290" y="1050" as="targetPoint" />
<Array as="points">
<mxPoint x="660" y="990" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-56" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-35" target="TwrB0rHwIU3CN8L-tBzC-21">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1140" y="1060" as="sourcePoint" />
<mxPoint x="1300" y="1060" as="targetPoint" />
<Array as="points">
<mxPoint x="690" y="990" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-57" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-32" target="TwrB0rHwIU3CN8L-tBzC-31">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1520" y="1055" as="sourcePoint" />
<mxPoint x="1560" y="955" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-58" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-25" target="TwrB0rHwIU3CN8L-tBzC-31">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1470" y="995" as="sourcePoint" />
<mxPoint x="1480" y="955" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-59" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-23" target="TwrB0rHwIU3CN8L-tBzC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1075" y="1010" as="sourcePoint" />
<mxPoint x="1235" y="1010" as="targetPoint" />
<Array as="points">
<mxPoint x="856" y="900" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-61" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-22" target="TwrB0rHwIU3CN8L-tBzC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1085" y="1020" as="sourcePoint" />
<mxPoint x="1245" y="1020" as="targetPoint" />
<Array as="points">
<mxPoint x="890" y="900" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-62" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-22" target="TwrB0rHwIU3CN8L-tBzC-26">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1095" y="1030" as="sourcePoint" />
<mxPoint x="1255" y="1030" as="targetPoint" />
<Array as="points">
<mxPoint x="1246" y="880" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-63" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-31" target="TwrB0rHwIU3CN8L-tBzC-4">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1105" y="1040" as="sourcePoint" />
<mxPoint x="1265" y="1040" as="targetPoint" />
<Array as="points">
<mxPoint x="1370" y="930" />
<mxPoint x="1370" y="910" />
<mxPoint x="1240" y="910" />
<mxPoint x="960" y="860" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-64" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-31" target="TwrB0rHwIU3CN8L-tBzC-27">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1115" y="1050" as="sourcePoint" />
<mxPoint x="1275" y="1050" as="targetPoint" />
<Array as="points">
<mxPoint x="1395" y="880" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-65" value="«interface»&lt;br&gt;&lt;b&gt;ServerConnection&lt;/b&gt;&lt;div&gt;&lt;b&gt;(from JME)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="312" y="1237" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-66" value="«interface»&lt;br&gt;&lt;b&gt;ClientStateListener&lt;/b&gt;&lt;div&gt;&lt;b&gt;(from JME)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="270" y="1169" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-67" value="«interface»&lt;br&gt;&lt;div&gt;&lt;b&gt;MessageListener &amp;lt;Client&amp;gt; (from JME)&lt;/b&gt;&lt;/div&gt;" style="html=1;whiteSpace=wrap;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="130" y="1247" width="171" height="50" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-69" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-65" target="TwrB0rHwIU3CN8L-tBzC-3">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="480" y="850" as="sourcePoint" />
<mxPoint x="546" y="790" as="targetPoint" />
<Array as="points">
<mxPoint x="430" y="1230" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-72" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-22" target="TwrB0rHwIU3CN8L-tBzC-5">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="940" y="990" as="sourcePoint" />
<mxPoint x="1100" y="990" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-73" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-22" target="TwrB0rHwIU3CN8L-tBzC-24">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="950" y="1000" as="sourcePoint" />
<mxPoint x="1110" y="1000" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-74" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-22" target="TwrB0rHwIU3CN8L-tBzC-65">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="960" y="1010" as="sourcePoint" />
<mxPoint x="570" y="1130" as="targetPoint" />
<Array as="points">
<mxPoint x="960" y="1260" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-75" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-22" target="TwrB0rHwIU3CN8L-tBzC-37">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="970" y="1020" as="sourcePoint" />
<mxPoint x="1130" y="1020" as="targetPoint" />
<Array as="points">
<mxPoint x="1050" y="1120" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-76" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-37" target="TwrB0rHwIU3CN8L-tBzC-38">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="980" y="1030" as="sourcePoint" />
<mxPoint x="1140" y="1030" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-77" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1215" y="1118" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-78" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-35" target="TwrB0rHwIU3CN8L-tBzC-25">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="990" y="1040" as="sourcePoint" />
<mxPoint x="1150" y="1040" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-79" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0;exitDx=0;exitDy=0;entryX=1;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-25" target="TwrB0rHwIU3CN8L-tBzC-22">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1000" y="1050" as="sourcePoint" />
<mxPoint x="1090" y="960" as="targetPoint" />
<Array as="points">
<mxPoint x="1330" y="1020" />
<mxPoint x="1120" y="940" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-80" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-36" target="TwrB0rHwIU3CN8L-tBzC-22">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1010" y="1060" as="sourcePoint" />
<mxPoint x="1170" y="1060" as="targetPoint" />
<Array as="points">
<mxPoint x="930" y="1130" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-81" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-43" target="TwrB0rHwIU3CN8L-tBzC-22">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1020" y="1070" as="sourcePoint" />
<mxPoint x="1180" y="1070" as="targetPoint" />
<Array as="points">
<mxPoint x="990" y="1360" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-82" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-42" target="TwrB0rHwIU3CN8L-tBzC-22">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1030" y="1080" as="sourcePoint" />
<mxPoint x="1190" y="1080" as="targetPoint" />
<Array as="points">
<mxPoint x="1020" y="1210" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-83" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-33" target="TwrB0rHwIU3CN8L-tBzC-36">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="630" y="1070" as="sourcePoint" />
<mxPoint x="790" y="1070" as="targetPoint" />
<Array as="points">
<mxPoint x="605" y="1130" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-84" value="2" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="695" y="1128" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-85" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-34" target="TwrB0rHwIU3CN8L-tBzC-36">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1050" y="1100" as="sourcePoint" />
<mxPoint x="1210" y="1100" as="targetPoint" />
<Array as="points">
<mxPoint x="720" y="1100" />
<mxPoint x="777" y="1100" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-87" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-39" target="TwrB0rHwIU3CN8L-tBzC-43">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1070" y="1120" as="sourcePoint" />
<mxPoint x="1230" y="1120" as="targetPoint" />
<Array as="points">
<mxPoint x="1320" y="1390" />
<mxPoint x="305" y="1390" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-88" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.75;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-43">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="379" y="1329" as="sourcePoint" />
<mxPoint x="340" y="1287" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-89" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-43" target="TwrB0rHwIU3CN8L-tBzC-66">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="399" y="1359" as="sourcePoint" />
<mxPoint x="406" y="1134" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-90" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.25;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-43" target="TwrB0rHwIU3CN8L-tBzC-67">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="409" y="1369" as="sourcePoint" />
<mxPoint x="416" y="1144" as="targetPoint" />
<Array as="points">
<mxPoint x="258" y="1339" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-92" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.53;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitPerimeter=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-36" target="TwrB0rHwIU3CN8L-tBzC-16">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="837" y="1140" as="sourcePoint" />
<mxPoint x="1740" y="820" as="targetPoint" />
<Array as="points">
<mxPoint x="780" y="1440" />
<mxPoint x="1715" y="1440" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-93" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-31" target="TwrB0rHwIU3CN8L-tBzC-16">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1620" y="940" as="sourcePoint" />
<mxPoint x="1730" y="940" as="targetPoint" />
<Array as="points">
<mxPoint x="1688" y="930" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-94" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="TwrB0rHwIU3CN8L-tBzC-23" target="TwrB0rHwIU3CN8L-tBzC-44">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="670" y="930" as="sourcePoint" />
<mxPoint x="670" y="870" as="targetPoint" />
<Array as="points">
<mxPoint x="690" y="900" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-96" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="TwrB0rHwIU3CN8L-tBzC-36">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1610" y="1150" as="sourcePoint" />
<mxPoint x="1220" y="1631" as="targetPoint" />
<Array as="points">
<mxPoint x="1610" y="1420" />
<mxPoint x="802" y="1420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="TwrB0rHwIU3CN8L-tBzC-97" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" target="TwrB0rHwIU3CN8L-tBzC-32">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1610" y="1150" as="sourcePoint" />
<mxPoint x="1540" y="1068" as="targetPoint" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 193 KiB

View File

@@ -0,0 +1,527 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="2288" dy="823" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="LkLulIeU9eejG4ewMiHC-0" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Config&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from Common)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="960" y="205" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-1" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Abstract Message&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;(from JME)&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="60" y="200" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-2" value="«interface»&lt;br&gt;&lt;b&gt;ServerSender&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="630" y="200" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-3" value="«interface»&lt;br&gt;&lt;b&gt;ClientInterpreter&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="800" y="200" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-4" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-260" y="370" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-8" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ServerMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="410" y="585" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-9" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-4" target="LkLulIeU9eejG4ewMiHC-1" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="500" y="535" as="sourcePoint" />
<mxPoint x="660" y="535" as="targetPoint" />
<Array as="points">
<mxPoint x="-190" y="310" />
<mxPoint x="130" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-10" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-8" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="500" y="535" as="sourcePoint" />
<mxPoint x="130" y="240" as="targetPoint" />
<Array as="points">
<mxPoint x="480" y="310" />
<mxPoint x="130" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-11" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;MapMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-430" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-13" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShootMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-260" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-14" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationEndMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-90" y="470" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-16" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-13" target="LkLulIeU9eejG4ewMiHC-4" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="195" y="390" as="sourcePoint" />
<mxPoint y="230" as="targetPoint" />
<Array as="points">
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-17" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-11" target="LkLulIeU9eejG4ewMiHC-4" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="205" y="400" as="sourcePoint" />
<mxPoint x="10" y="240" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="420" />
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-18" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ServerGameLogic&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="785" y="300" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-20" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-3" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="480" y="310" as="sourcePoint" />
<mxPoint x="640" y="310" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-21" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.445;entryY=1.008;entryDx=0;entryDy=0;entryPerimeter=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-2" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="720" y="320" as="sourcePoint" />
<mxPoint x="880" y="320" as="targetPoint" />
<Array as="points">
<mxPoint x="680" y="310" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-22" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-23" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1226" y="340" as="sourcePoint" />
<mxPoint x="1070" y="310" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-23" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BallteshipConfig&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="960" y="300" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-24" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-23" target="LkLulIeU9eejG4ewMiHC-0" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1009" y="355" as="sourcePoint" />
<mxPoint x="1009" y="200" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-25" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BallteshipClientConfig&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="960" y="400" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-26" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-25" target="LkLulIeU9eejG4ewMiHC-23" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="904" y="520" as="sourcePoint" />
<mxPoint x="709" y="360" as="targetPoint" />
<Array as="points">
<mxPoint x="1030" y="370" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-27" value="«enum»&lt;br&gt;&lt;b&gt;ServerState&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="610" y="370" width="110" height="40" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-28" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-27" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="746" y="370" as="sourcePoint" />
<mxPoint x="680" y="390" as="targetPoint" />
<Array as="points">
<mxPoint x="820" y="390" />
<mxPoint x="743" y="390" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-29" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Player&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="810" y="465" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-31" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-18" target="LkLulIeU9eejG4ewMiHC-29" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="830" y="330" as="sourcePoint" />
<mxPoint x="870" y="460" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-32" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShipMap&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="810" y="550" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-33" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-29" target="LkLulIeU9eejG4ewMiHC-32" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="865" y="280" as="sourcePoint" />
<mxPoint x="865" y="425" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-34" value="«interface»&lt;br&gt;&lt;b&gt;GameEventBroker&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="960" y="535" width="120" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-35" value="«interface»&lt;br&gt;&lt;b&gt;ServerInterpreter&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1110" y="535" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-36" value="«interface»&lt;br&gt;&lt;b&gt;ClientSender&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1112" y="735" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-37" value="«interface»&lt;br&gt;&lt;b&gt;gameEventListener&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1112" y="805" width="131" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-38" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientGameLogic&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="800" y="750" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-39" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-44" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="865" y="445" as="sourcePoint" />
<mxPoint x="865" y="560" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-40" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-36" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="867" y="755" as="sourcePoint" />
<mxPoint x="867" y="625" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-41" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.75;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-37" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="877" y="765" as="sourcePoint" />
<mxPoint x="877" y="635" as="targetPoint" />
<Array as="points">
<mxPoint x="883" y="830" />
<mxPoint x="1062" y="830" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-42" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" target="LkLulIeU9eejG4ewMiHC-34" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1015" y="550" as="targetPoint" />
<Array as="points">
<mxPoint x="880" y="660" />
<mxPoint x="1020" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-43" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=1;exitY=0;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" target="LkLulIeU9eejG4ewMiHC-35" edge="1" source="LkLulIeU9eejG4ewMiHC-38">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="880" y="750" as="sourcePoint" />
<mxPoint x="1190" y="640" as="targetPoint" />
<Array as="points">
<mxPoint x="910" y="710" />
<mxPoint x="1176" y="710" />
<mxPoint x="1176" y="660" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-44" value="3" style="text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="840" y="570" width="60" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-45" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="827" y="435" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-47" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ClientState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="800" y="848" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-48" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.25;exitY=1;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-47" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="830" y="790" as="sourcePoint" />
<mxPoint x="830" y="820" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-49" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-47" target="LkLulIeU9eejG4ewMiHC-38" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="892" y="865" as="sourcePoint" />
<mxPoint x="852" y="815" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-50" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;GameDetails&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="580" y="750" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-51" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-38" target="LkLulIeU9eejG4ewMiHC-50" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="740" y="835" as="sourcePoint" />
<mxPoint x="740" y="715" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-52" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;StartBattleMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="420" y="750" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-54" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationStartMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="250" y="750" width="140" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-55" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BackToBattleStateMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="45" y="750" width="170" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-56" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-52" target="LkLulIeU9eejG4ewMiHC-8" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="827" y="470" as="sourcePoint" />
<mxPoint x="477" y="310" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-57" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fillColor=#FF0000;exitX=0.5;exitY=0;exitDx=0;exitDy=0;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-54" target="LkLulIeU9eejG4ewMiHC-8" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="280" y="700" as="sourcePoint" />
<mxPoint x="488" y="285" as="targetPoint" />
<Array as="points">
<mxPoint x="320" y="690" />
<mxPoint x="320" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-58" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-55" target="LkLulIeU9eejG4ewMiHC-8" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="360" y="710" as="sourcePoint" />
<mxPoint x="490" y="280" as="targetPoint" />
<Array as="points">
<mxPoint x="130" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-59" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-50" target="LkLulIeU9eejG4ewMiHC-8" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="510" y="710" as="sourcePoint" />
<mxPoint x="488" y="285" as="targetPoint" />
<Array as="points">
<mxPoint x="640" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-60" value="«interface»&lt;br&gt;&lt;b&gt;Item&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-220" y="535" width="140" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-61" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;EffectMessage&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-140" y="750" width="170" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-62" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-8" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="30" y="680" as="sourcePoint" />
<mxPoint x="384" y="250" as="targetPoint" />
<Array as="points">
<mxPoint x="-55" y="640" />
<mxPoint x="480" y="640" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-63" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Shot&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-170" y="650" width="90" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-64" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleShip&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-390" y="650" width="113" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-65" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;Shell&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-260" y="650" width="70" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-66" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-32" target="LkLulIeU9eejG4ewMiHC-60" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="270" y="485" as="sourcePoint" />
<mxPoint x="270" y="365" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-67" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-85" y="528" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-68" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-20" y="470" as="sourcePoint" />
<mxPoint x="-190" y="390" as="targetPoint" />
<Array as="points">
<mxPoint x="-20" y="420" />
<mxPoint x="-190" y="420" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-69" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-63" target="LkLulIeU9eejG4ewMiHC-60" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-70.42000000000007" y="750" as="sourcePoint" />
<mxPoint x="-70.42000000000007" y="590" as="targetPoint" />
<Array as="points">
<mxPoint x="-125" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-70" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-64" target="LkLulIeU9eejG4ewMiHC-60" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-115" y="660" as="sourcePoint" />
<mxPoint x="-150" y="590" as="targetPoint" />
<Array as="points">
<mxPoint x="-333" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-71" value="" style="endArrow=block;dashed=1;endFill=0;endSize=12;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-65" target="LkLulIeU9eejG4ewMiHC-60" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-233" y="660" as="sourcePoint" />
<mxPoint x="-175" y="595" as="targetPoint" />
<Array as="points">
<mxPoint x="-225" y="630" />
<mxPoint x="-150" y="630" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-72" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.088;exitY=0.02;exitDx=0;exitDy=0;exitPerimeter=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-63" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="370" y="690" as="sourcePoint" />
<mxPoint x="-70" y="570" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-73" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.75;entryY=1;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-61" target="LkLulIeU9eejG4ewMiHC-64" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-115" y="760" as="sourcePoint" />
<mxPoint x="-115" y="680" as="targetPoint" />
<Array as="points">
<mxPoint x="-305" y="760" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-74" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-335" y="668" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-75" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.25;entryY=0;entryDx=0;entryDy=0;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-11" target="LkLulIeU9eejG4ewMiHC-64" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-393.5" y="535" as="sourcePoint" />
<mxPoint x="-586.5" y="445" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="560" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-76" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-390" y="620" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-79" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;WaitState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="540" y="930" width="100" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-80" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="660" y="930" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-81" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;InitialState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="795" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-82" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;AnimationState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;fillColor=default;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="930" y="930" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-83" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;GameOverState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1060" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-84" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;EditorState&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="400" y="930" width="120" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-85" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-81" target="LkLulIeU9eejG4ewMiHC-47" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="820" y="1020" as="sourcePoint" />
<mxPoint x="940" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-86" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-80" target="LkLulIeU9eejG4ewMiHC-47" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="860" y="940" as="sourcePoint" />
<mxPoint x="940" y="860" as="targetPoint" />
<Array as="points">
<mxPoint x="715" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-87" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-79" target="LkLulIeU9eejG4ewMiHC-47" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="628" y="925" as="sourcePoint" />
<mxPoint x="890" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="590" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-89" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;fillColor=#FF0000;strokeColor=#FF0000;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-82" target="LkLulIeU9eejG4ewMiHC-47" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="877" y="950" as="sourcePoint" />
<mxPoint x="920" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="985" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-90" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-83" target="LkLulIeU9eejG4ewMiHC-47" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="1120" y="920" as="sourcePoint" />
<mxPoint x="840" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="1120" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-91" value="" style="endArrow=block;endSize=16;endFill=0;html=1;rounded=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-84" target="LkLulIeU9eejG4ewMiHC-47" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="503" y="910" as="sourcePoint" />
<mxPoint x="800" y="890" as="targetPoint" />
<Array as="points">
<mxPoint x="460" y="910" />
<mxPoint x="855" y="910" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-92" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.25;entryY=1;entryDx=0;entryDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-84" target="LkLulIeU9eejG4ewMiHC-64" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="380" y="830" as="sourcePoint" />
<mxPoint x="40" y="870" as="targetPoint" />
<Array as="points">
<mxPoint x="-360" y="940" />
</Array>
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-93" value="2" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-390" y="680" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-94" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="1085" y="838" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-95" value="«enum»&lt;br&gt;&lt;b&gt;Rotation&lt;/b&gt;" style="html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-550" y="635" width="110" height="50" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-96" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;BattleShipDTO&lt;/b&gt;&lt;/p&gt;&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;&lt;br&gt;&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-550" y="735" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-97" value="&lt;p style=&quot;margin:0px;margin-top:4px;text-align:center;&quot;&gt;&lt;b&gt;ShipMaoDTO&lt;/b&gt;&lt;/p&gt;" style="verticalAlign=top;align=left;overflow=fill;html=1;whiteSpace=wrap;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-550" y="800" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-98" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-96" target="LkLulIeU9eejG4ewMiHC-95" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-420.8" y="778" as="sourcePoint" />
<mxPoint x="-420.8" y="698" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-99" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-97" target="LkLulIeU9eejG4ewMiHC-96" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-485" y="745" as="sourcePoint" />
<mxPoint x="-485" y="695" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-100" value="*" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="WIyWlLk6GJQsqaUBKTNV-1" vertex="1">
<mxGeometry x="-495" y="760" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="LkLulIeU9eejG4ewMiHC-101" value="" style="endArrow=open;endFill=1;endSize=12;html=1;rounded=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" parent="WIyWlLk6GJQsqaUBKTNV-1" source="LkLulIeU9eejG4ewMiHC-64" target="LkLulIeU9eejG4ewMiHC-95" edge="1">
<mxGeometry width="160" relative="1" as="geometry">
<mxPoint x="-485" y="745" as="sourcePoint" />
<mxPoint x="-485" y="695" as="targetPoint" />
<Array as="points" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 167 KiB

View File

@@ -0,0 +1,96 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram name="Seite-1" id="CSCMTvoyx8GfkIWIgrj5">
<mxGraphModel dx="2914" dy="1176" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="8jlTEtXbO0kP9G_WUDS2-10" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-2" target="8jlTEtXbO0kP9G_WUDS2-8" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-15" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-2" target="8jlTEtXbO0kP9G_WUDS2-12" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-2" value="" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="70" y="320" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-6" value="addPlayer(id)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="130" y="290" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-7" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="-10" y="358" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-17" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-8" target="8jlTEtXbO0kP9G_WUDS2-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-18" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-8" target="8jlTEtXbO0kP9G_WUDS2-16" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-8" value="Set up" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="72.5" y="450" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-11" value="[players.size()=2]/send GameDetail messages" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="125" y="360" width="270" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-12" target="8jlTEtXbO0kP9G_WUDS2-2" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-12" value="" style="ellipse;fillColor=strokeColor;html=1;" parent="1" vertex="1">
<mxGeometry x="15" y="260" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-22" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-16" target="8jlTEtXbO0kP9G_WUDS2-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-16" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="170" y="520" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-19" value="received MapMessage&lt;div&gt;&lt;br&gt;&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="220" y="470" width="140" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-20" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="50" y="588" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-26" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#FF0000;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-21" target="8jlTEtXbO0kP9G_WUDS2-24" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-21" value="Battle" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="172.5" y="640" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-23" value="[readyPlayers.size() = 2]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="220" y="585" width="150" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-28" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-24" edge="1">
<mxGeometry relative="1" as="geometry">
<mxPoint x="342.3548387096773" y="830" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-24" value="Animation wait" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#FF0000;" parent="1" vertex="1">
<mxGeometry x="285" y="680" width="115" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-30" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-29" target="8jlTEtXbO0kP9G_WUDS2-21" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-32" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;" parent="1" source="8jlTEtXbO0kP9G_WUDS2-29" target="8jlTEtXbO0kP9G_WUDS2-31" edge="1">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-29" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="302.5" y="830" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-31" value="Game over" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
<mxGeometry x="285" y="960" width="115" height="20" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-33" value="[game over]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="345" y="888" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="8jlTEtXbO0kP9G_WUDS2-34" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="205" y="860" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="EPEOK_vwsi3Ha1gNdRhl-1" value="sendAnimationStartMessage(pos)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=#FF0000;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="350" y="615" width="200" height="30" as="geometry" />
</mxCell>
<mxCell id="EPEOK_vwsi3Ha1gNdRhl-2" value="shoot(pos)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" parent="1" vertex="1">
<mxGeometry x="340" y="758" width="80" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View File

@@ -0,0 +1,94 @@
<mxfile host="Electron" agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/24.7.8 Chrome/128.0.6613.36 Electron/32.0.1 Safari/537.36" version="24.7.8">
<diagram id="C5RBs43oDa-KdzZeNtuy" name="Page-1">
<mxGraphModel dx="1461" dy="823" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
<root>
<mxCell id="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="WIyWlLk6GJQsqaUBKTNV-1" parent="WIyWlLk6GJQsqaUBKTNV-0" />
<mxCell id="ec3Q6cWicWv9khViEyFp-0" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-1" target="ec3Q6cWicWv9khViEyFp-3">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-1" value="" style="ellipse;fillColor=strokeColor;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="550" y="260" width="30" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-2" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-3" target="ec3Q6cWicWv9khViEyFp-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-3" value="Initial State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="670" y="265" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-4" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-5" target="ec3Q6cWicWv9khViEyFp-9">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-5" value="Editor State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="670" y="358" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-6" value="receivedGameDetails(details)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="720" y="298" width="180" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-7" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-9" target="ec3Q6cWicWv9khViEyFp-5">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-8" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-9" target="ec3Q6cWicWv9khViEyFp-13">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-9" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="780" y="470" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-10" value="mapFinished" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="815" y="368" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-11" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="680" y="498" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-12" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-13" target="ec3Q6cWicWv9khViEyFp-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-13" value="Wait State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="782.5" y="575" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-14" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;strokeColor=#FF0000;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-15" target="ec3Q6cWicWv9khViEyFp-17">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-15" value="Battle State" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="782.5" y="690" width="75" height="20" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-16" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-17" target="ec3Q6cWicWv9khViEyFp-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-17" value="Animation State" style="rounded=1;whiteSpace=wrap;html=1;strokeColor=#FF0000;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="940" y="760" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-18" value="receivedAnimationStartMessage(msg)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=#FF0000;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="885" y="660" width="230" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-19" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-21" target="ec3Q6cWicWv9khViEyFp-15">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-20" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" edge="1" parent="WIyWlLk6GJQsqaUBKTNV-1" source="ec3Q6cWicWv9khViEyFp-21" target="ec3Q6cWicWv9khViEyFp-23">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-21" value="&lt;span style=&quot;color: rgba(0, 0, 0, 0); font-family: monospace; font-size: 0px; text-align: start; text-wrap: nowrap;&quot;&gt;%3CmxGraphModel%3E%3Croot%3E%3CmxCell%20id%3D%220%22%2F%3E%3CmxCell%20id%3D%221%22%20parent%3D%220%22%2F%3E%3CmxCell%20id%3D%222%22%20value%3D%22%22%20style%3D%22rhombus%3BwhiteSpace%3Dwrap%3Bhtml%3D1%3B%22%20vertex%3D%221%22%20parent%3D%221%22%3E%3CmxGeometry%20x%3D%22170%22%20y%3D%22530%22%20width%3D%2280%22%20height%3D%2240%22%20as%3D%22geometry%22%2F%3E%3C%2FmxCell%3E%3C%2Froot%3E%3C%2FmxGraphModel%3E&lt;/span&gt;" style="rhombus;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="955" y="878" width="80" height="40" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-22" value="sendAnimationEndMessage(pos)&lt;div&gt;receivedEffectMessage(msg)&lt;/div&gt;" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1060" y="805" width="200" height="40" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-23" value="game over" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="940" y="970" width="110" height="20" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-24" value="[game over]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="1005" y="930" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-25" value="[otherwise]" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="832" y="918" width="80" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-26" value="[horbor&amp;nbsp; empty] / send MapMessage" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="832" y="525" width="220" height="30" as="geometry" />
</mxCell>
<mxCell id="ec3Q6cWicWv9khViEyFp-27" value="receivedStartBattle(msg)" style="text;html=1;align=center;verticalAlign=middle;resizable=0;points=[];autosize=1;strokeColor=none;fillColor=none;" vertex="1" parent="WIyWlLk6GJQsqaUBKTNV-1">
<mxGeometry x="827" y="610" width="160" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

View File

@@ -1,12 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="BattleshipApp (Mac)" type="Application" factoryName="Application" singleton="false">
<configuration default="false" name="BattleshipApp (Mac)" type="Application" factoryName="Application"
singleton="false">
<option name="MAIN_CLASS_NAME" value="pp.battleship.client.BattleshipApp"/>
<module name="Projekte.battleship.client.main"/>
<option name="VM_PARAMETERS" value="-XstartOnFirstThread"/>
<option name="WORKING_DIRECTORY" value="$MODULE_WORKING_DIR$"/>
<extension name="coverage">
<pattern>
<option name="PATTERN" value="pp.battleship.client.server.*" />
<option name="PATTERN" value="pp.battleship.client.*"/>
<option name="ENABLED" value="true"/>
</pattern>
</extension>

View File

@@ -1,14 +1,13 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="BattleshipApp" type="Application" factoryName="Application" singleton="false" nameIsGenerated="true">
<option name="ALTERNATIVE_JRE_PATH" value="temurin-20" />
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="true" />
<configuration default="false" name="BattleshipApp" type="Application" factoryName="Application" singleton="false"
nameIsGenerated="true">
<option name="MAIN_CLASS_NAME" value="pp.battleship.client.BattleshipApp"/>
<module name="Gruppe-01" />
<module name="Projekte.battleship.client.main"/>
<option name="VM_PARAMETERS" value="-Djava.util.logging.config.file=logging.properties"/>
<option name="WORKING_DIRECTORY" value="$MODULE_WORKING_DIR$"/>
<extension name="coverage">
<pattern>
<option name="PATTERN" value="pp.battleship.client.server.*" />
<option name="PATTERN" value="pp.battleship.client.*"/>
<option name="ENABLED" value="true"/>
</pattern>
</extension>

View File

@@ -9,7 +9,6 @@ implementation project(":jme-common")
implementation project(":battleship:model")
implementation libs.jme3.desktop
implementation libs.jme3.effects
runtimeOnly libs.jme3.awt.dialogs
runtimeOnly libs.jme3.plugins

View File

@@ -9,7 +9,7 @@
#
# Specifies the map used by the opponent in single mode.
# Single mode is activated if this property is set.
#map.opponent=maps/map2.json
#git map.opponent=maps/map2.json
#
# Specifies the map used by the player in single mode.
# The player must define their own map if this property is not set.

View File

@@ -1,66 +0,0 @@
{
"width": 10,
"height": 10,
"ships": [
{
"length": 4,
"x": 2,
"y": 8,
"rot": "RIGHT"
},
{
"length": 3,
"x": 2,
"y": 5,
"rot": "DOWN"
},
{
"length": 3,
"x": 5,
"y": 6,
"rot": "RIGHT"
},
{
"length": 2,
"x": 4,
"y": 4,
"rot": "RIGHT"
},
{
"length": 2,
"x": 7,
"y": 4,
"rot": "RIGHT"
},
{
"length": 2,
"x": 7,
"y": 4,
"rot": "RIGHT"
},
{
"length": 1,
"x": 6,
"y": 2,
"rot": "RIGHT"
},
{
"length": 1,
"x": 8,
"y": 2,
"rot": "RIGHT"
},
{
"length": 1,
"x": 6,
"y": 0,
"rot": "RIGHT"
},
{
"length": 1,
"x": 8,
"y": 0,
"rot": "RIGHT"
}
]
}

View File

@@ -1,66 +0,0 @@
{
"width": 10,
"height": 10,
"ships": [
{
"length": 1,
"x": 9,
"y": 0,
"rot": "RIGHT"
},
{
"length": 1,
"x": 9,
"y": 1,
"rot": "RIGHT"
},
{
"length": 1,
"x": 8,
"y": 0,
"rot": "RIGHT"
},
{
"length": 1,
"x": 8,
"y": 1,
"rot": "RIGHT"
},
{
"length": 2,
"x": 8,
"y": 2,
"rot": "RIGHT"
},
{
"length": 2,
"x": 6,
"y": 0,
"rot": "RIGHT"
},
{
"length": 2,
"x": 6,
"y": 1,
"rot": "RIGHT"
},
{
"length": 3,
"x": 5,
"y": 2,
"rot": "RIGHT"
},
{
"length": 3,
"x": 7,
"y": 3,
"rot": "RIGHT"
},
{
"length": 4,
"x": 6,
"y": 4,
"rot": "RIGHT"
}
]
}

View File

@@ -7,89 +7,117 @@
import java.util.prefs.Preferences;
/**
* this class is used to control the background-music in the game
*/
public class BackgroundMusic {
private static final String VOLUME_PREF = "volume";
private static final String MUSIC_ENABLED_PREF = "musicEnabled";
private Preferences prefs = Preferences.userNodeForPackage(BackgroundMusic.class);
private final AudioNode backgroundMusic;
private boolean musicEnabled;
private float volume;
/**
* this attribute ist the keyword to save the last volume, that was set
*/
private static final String VOLUME_PREV = "BackgroundVolume";
/**
* Constuctor for the BackgroundMusic
* @param app for synchronising and saving data with the application
* @param musicFilePath the filepath for the BackgroundMusic
* this attribute ist the keyword to save the state, whether the music was on or off in the last session
*/
public BackgroundMusic(Application app, String musicFilePath) {
this.volume = prefs.getFloat(VOLUME_PREF, 1.0f);
this.musicEnabled = prefs.getBoolean(MUSIC_ENABLED_PREF, true);
private static final String BACKGROUND_MUSIC_ENABLED_PREV = "BackgroundMusicEnabled";
backgroundMusic = new AudioNode(app.getAssetManager(), musicFilePath, DataType.Stream);
backgroundMusic.setLooping(true);
/**
* this attribute holds the last set values for on/off and the volume, with the keywords "BackgroundVolume" and "BackgroundMusicEnabled"
*/
private Preferences prefs = Preferences.userNodeForPackage(BackgroundMusic.class);
/**
* this attribute holds the Music-node, which is used to play the music
*/
private final AudioNode backgroundMusic;
/**
* this boolean holds, whether the music is enabled or not at this state
*/
private boolean backgroundMusicEnabled;
/**
* this attribute holds the current volume
*/
private float backgroundVolume;
/**
* this is the constructor of this class, is used to set the current values to the values stored in the preferences
*
* @param app the application the Background-music uis used in
* @param backGroundMusicPath the path, where the Background-music is stored in
*/
public BackgroundMusic(Application app, String backGroundMusicPath) {
this.backgroundVolume = prefs.getFloat(VOLUME_PREV, 1.0f); // sets the volume to the value stored in pref,or 1.0f if it is not accessible
this.backgroundMusicEnabled = prefs.getBoolean(BACKGROUND_MUSIC_ENABLED_PREV, true); // sets the enabled to the value stored in pref,or true if it is not accessible
backgroundMusic = new AudioNode(app.getAssetManager(), backGroundMusicPath, DataType.Stream); // initialize the Audio-node
backgroundMusic.setLooping(true); // sets looping true, so it is played always, when enabled
backgroundMusic.setPositional(false);
backgroundMusic.setVolume(1.0f);
backgroundMusic.setVolume(backgroundVolume);
if (musicEnabled) {
if (backgroundMusicEnabled) { //starts playing, when enabled
play();
}
}
/**
* Checks if the condition is met to play BackgroundMusic
* this method plays the background sound, if it is enabled
*/
public void play() {
if (musicEnabled && (backgroundMusic.getStatus() == Status.Stopped || backgroundMusic.getStatus() == Status.Paused)) {
if (backgroundMusicEnabled && (backgroundMusic.getStatus() == Status.Stopped || backgroundMusic.getStatus() == Status.Paused)) { //checks, if it is enabled and stopped or paused
backgroundMusic.play();
}
}
/**
* function to stop the BackgroundMusic
* this method stops the background-music
*/
public void stop() {
if (backgroundMusic.getStatus() == Status.Playing) {
backgroundMusic.stop();
}
public void stop() { //stops the music, when it is playing
if (backgroundMusic.getStatus() == Status.Playing) backgroundMusic.stop();
}
/**
* function to toggle the Backgroundmusic also sets the volume to the previous session
* function to toggle the Background-music ,so if it was disabled it is now enabled and other way around
*/
public void toogleMusic() {
this.musicEnabled = !this.musicEnabled;
if (musicEnabled) {
public void toggleMusic() {
this.backgroundMusicEnabled = !this.backgroundMusicEnabled;
if (backgroundMusicEnabled) {
play();
} else {
}
else {
stop();
}
prefs.putFloat(VOLUME_PREF, volume);
prefs.putBoolean(BACKGROUND_MUSIC_ENABLED_PREV, backgroundMusicEnabled); //puts in new enabled to the pref
}
/**
* Setter for the Volume also safes the volume from the previous session
* @param volume variable for the volume of the BackgroundMusic
* this method sets the
*
* @param volume is the volume the music is set to
*/
public void setVolume(float volume) {
this.volume = volume;
backgroundMusic.setVolume(volume);
prefs.putFloat(VOLUME_PREF, volume);
public void setBackgroundVolume(float volume) {
this.backgroundVolume = volume;
backgroundMusic.setVolume(backgroundVolume);
prefs.putFloat(VOLUME_PREV, volume);
}
/**
* Getter for Volume
* @return a float value of the volume
* this method returns the BackgroundVolume
*
* @return backgroundVolume
*/
public float getVolume() {
return volume;
public float getBackgroundVolume() {
return backgroundVolume;
}
/**
* Getter for musicEnabled
* @return if the music is enabled return true, false otherwise
* return, if the background-music is enabled
*
* @return true if the music is enabled
*/
public boolean isMusicEnabled() {
return musicEnabled;
public boolean isBackgroundMusicEnabled() {
return backgroundMusicEnabled;
}
}

View File

@@ -121,8 +121,9 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient
* Listener for handling actions triggered by the Escape key.
*/
private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed);
/**
*
* this is the object, responsible for the background-music and to control it
*/
private BackgroundMusic backgroundMusic;
@@ -145,7 +146,6 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient
*/
public static void main(String[] args) {
new BattleshipApp().start();
}
/**
@@ -230,7 +230,7 @@ public void simpleInitApp() {
setupStates();
setupGui();
serverConnection.connect();
backgroundMusic = new BackgroundMusic(this, "Sound/Effects/BackgroundMusic/boss_battle_#2_metal_opening.wav");
backgroundMusic = new BackgroundMusic(this, "Sound/Background/backgroundMusic.ogg"); //initialise backgroundMusic and sets the backgroundMusic-path
}
/**
@@ -434,8 +434,8 @@ void errorDialog(String errorMessage) {
}
/**
* Getter for the BackgroundMusic
* @return the BackgroundMusic
* this method returns Background-Music
* @return background-music
*/
public BackgroundMusic getBackgroundMusic(){
return backgroundMusic;

View File

@@ -30,11 +30,10 @@ public class GameSound extends AbstractAppState implements GameEventListener {
private static final Logger LOGGER = System.getLogger(GameSound.class.getName());
private static final Preferences PREFERENCES = getPreferences(GameSound.class);
private static final String ENABLED_PREF = "enabled"; //NON-NLS
private AudioNode splashSound;
private AudioNode shipDestroyedSound;
private AudioNode explosionSound;
private AudioNode missileLaunch;
private AudioNode rocketSound;
/**
* Checks if sound is enabled in the preferences.
@@ -45,6 +44,13 @@ public static boolean enabledInPreferences() {
return PREFERENCES.getBoolean(ENABLED_PREF, true);
}
/**
* Toggles the game sound on or off.
*/
public void toggleSound() {
setEnabled(!isEnabled());
}
/**
* Sets the enabled state of this AppState.
* Overrides {@link com.jme3.app.state.AbstractAppState#setEnabled(boolean)}
@@ -72,7 +78,7 @@ public void initialize(AppStateManager stateManager, Application app) {
shipDestroyedSound = loadSound(app, "Sound/Effects/sunken.wav"); //NON-NLS
splashSound = loadSound(app, "Sound/Effects/splash.wav"); //NON-NLS
explosionSound = loadSound(app, "Sound/Effects/explosion.wav"); //NON-NLS
missileLaunch = loadSound(app, "Sound/Effects/missileLaunch.wav");
rocketSound = loadSound(app, "Sound/Effects/rocket-loop-99748.wav");
}
/**
@@ -94,13 +100,6 @@ private AudioNode loadSound(Application app, String name) {
return null;
}
/**
* Plays the missile launch sound effect.
*/
public void missileLaunch() {
missileLaunch.playInstance();
}
/**
* Plays the splash sound effect.
*/
@@ -126,7 +125,8 @@ public void shipDestroyed() {
}
/**
* Checks the according case for the soundeffect
* when triggered, though a sound-event,it decides, which sound should be played
*
* @param event the received event
*/
@Override
@@ -135,7 +135,25 @@ public void receivedEvent(SoundEvent event) {
case EXPLOSION -> explosion();
case SPLASH -> splash();
case DESTROYED_SHIP -> shipDestroyed();
case MISSILE_LAUNCH -> missileLaunch();
case ROCKET -> rocket();
case ROCKET_STOP -> rocketStopped();
}
}
/**
* this method plays the sound of the rocket
*/
private void rocket() {
if (isEnabled() && splashSound != null)
rocketSound.play();
}
/**
* this method stops the sound of the rocket
*/
private void rocketStopped() {
rocketSound.stop();
}
}

View File

@@ -9,15 +9,14 @@
import com.simsilica.lemur.Button;
import com.simsilica.lemur.Checkbox;
import com.simsilica.lemur.DefaultRangedValueModel;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.Slider;
import com.simsilica.lemur.core.VersionedReference;
import com.simsilica.lemur.style.ElementId;
import pp.dialog.Dialog;
import pp.dialog.StateCheckboxModel;
import pp.dialog.TextInputDialog;
import com.simsilica.lemur.DefaultRangedValueModel;
import com.simsilica.lemur.Slider;
import com.simsilica.lemur.core.VersionedReference;
import java.io.File;
import java.io.IOException;
@@ -51,17 +50,17 @@ public Menu(BattleshipApp app) {
addChild(new Checkbox(lookup("menu.sound-enabled"),
new StateCheckboxModel(app, GameSound.class)));
Checkbox musicToggle = new Checkbox(lookup("menu.music.toggle"));
musicToggle.setChecked(app.getBackgroundMusic().isMusicEnabled());
musicToggle.addClickCommands(s -> toggleMusic());
//this sets the checkbox,to disable/enable the background-music
Checkbox backgroundMusicEnabled = new Checkbox(lookup("background.music.checkbox"));
backgroundMusicEnabled.setChecked(app.getBackgroundMusic().isBackgroundMusicEnabled());
backgroundMusicEnabled.addClickCommands(s -> app.getBackgroundMusic().toggleMusic());
addChild(backgroundMusicEnabled);
addChild(musicToggle);
Slider volumeSlider = new Slider();
volumeSlider.setModel(new DefaultRangedValueModel(0.0 , 2.0, app.getBackgroundMusic().getVolume()));
//this sets the volume-slider for the volume of the background-music
Slider volumeSlider = new Slider(lookup("background.music.volume"));
volumeSlider.setModel(new DefaultRangedValueModel(0.0, 2.0, app.getBackgroundMusic().getBackgroundVolume()));
volumeSlider.setDelta(0.1);
addChild(volumeSlider);
volumeRef = volumeSlider.getModel().createReference();
addChild(loadButton)
@@ -72,36 +71,22 @@ public Menu(BattleshipApp app) {
.addClickCommands(s -> ifTopDialog(this::close));
addChild(new Button(lookup("menu.quit")))
.addClickCommands(s -> ifTopDialog(app::closeApp));
update();
}
/**
* Updates the volume if there is a change and adjusts it accordingly.
* @param tmp unused time parameter
* updates the background-volume
*
* @param tmp
*/
@Override
public void update(float tmp) {
if (volumeRef.update()) {
double newVolume = volumeRef.get();
adjustVolume(newVolume);
app.getBackgroundMusic().setBackgroundVolume((float) (double) volumeRef.get()); //sets new background-volume
}
}
/**
* Adjusts the background music volume to the specified value.
* @param newVolume the new volume level
*/
private void adjustVolume(double newVolume) {
app.getBackgroundMusic().setVolume((float) newVolume);
}
/**
* Toggles the background music on or off.
*/
private void toggleMusic(){
app.getBackgroundMusic().toogleMusic();
}
/**
* Updates the state of the load and save buttons based on the game logic.
*/

View File

@@ -7,9 +7,13 @@
package pp.battleship.client;
import com.simsilica.lemur.*;
import com.simsilica.lemur.Checkbox;
import com.simsilica.lemur.Container;
import com.simsilica.lemur.Label;
import com.simsilica.lemur.TextField;
import com.simsilica.lemur.component.SpringGridLayout;
import pp.battleship.client.server.BattleshipServer;
import pp.battleship.client.server.BattleshipLocalServer;
import pp.battleship.client.server.BattleshipLocalServer;
import pp.dialog.Dialog;
import pp.dialog.DialogBuilder;
import pp.dialog.SimpleDialog;
@@ -36,10 +40,7 @@ class NetworkDialog extends SimpleDialog {
private int portNumber;
private Future<Object> connectionFuture;
private Dialog progressDialog;
private BattleshipServer battleshipServer;
private boolean GUI = true;
private Container menu;
private boolean serverToggle = false;
private boolean localServer = false;
/**
* Constructs a new NetworkDialog.
@@ -53,64 +54,29 @@ class NetworkDialog extends SimpleDialog {
host.setPreferredWidth(400f);
port.setSingleLine(true);
this.menu = new Container();
menu();
addChild(menu);
}
/**
* Main Menu creation
*/
private void menu() {
Button connectGame = new Button("Multiplayer");
connectGame.addClickCommands(source -> serverConnectGUI());
Checkbox serverHost = new Checkbox("Host own Game");
serverHost.addClickCommands(source -> toggleServer());
menu.addChild(serverHost);
menu.addChild(connectGame);
}
/**
* Logic for the ServerGUI
*/
private void serverConnectGUI() {
LOGGER.log(Level.INFO, "Hosting Server...");
if (GUI) {
host.setSingleLine(true);
host.setPreferredWidth(400f);
port.setSingleLine(true);
final BattleshipApp app = network.getApp();
final Container input = new Container(new SpringGridLayout());
input.addChild(new Label(lookup("host.name") + ": "));
input.addChild(host, 1);
input.addChild(new Label(lookup("port.number") + ": "));
input.addChild(port, 1);
/*
* this checkbox controls, whether it will connect to an existing server or create a separate server
*/
Checkbox localServerCb = new Checkbox(lookup("local.server"));
localServerCb.setChecked(false);
localServerCb.addClickCommands(s -> localServer = !localServer);
DialogBuilder.simple(app.getDialogManager())
.setTitle(lookup("server.dialog"))
.setExtension(d -> d.addChild(input))
.setOkButton(lookup("button.connect"), d -> connect())
.setNoButton(lookup("button.cancel"), app::closeApp)
.setOkClose(false)
.setNoClose(false)
.build(this);
GUI = false;
}
}
/**
* Connect to server if serverToggle is false hosts otherwise
*/
private void connect(){
if (serverToggle) {
hostServer();
} else {
connectServer();
}
addChild(localServerCb); // adds the checkbox to the network dialog at the bottom
}
/**
@@ -124,47 +90,44 @@ private void connectServer() {
portNumber = Integer.parseInt(port.getText());
openProgressDialog();
connectionFuture = network.getApp().getExecutor().submit(this::initNetwork);
} catch (NumberFormatException e) {
}
catch (NumberFormatException e) {
network.getApp().errorDialog(lookup("port.must.be.integer"));
}
}
/**
* Checks if the Server is running or starts the Server and handles Exceptions *
* connects to the server, creates one, if no server is up
*/
private void hostServer() {
if (battleshipServer == null) {
startServer(); // Starts the server in a new thread
public void connect() {
if (localServer) {
startLocalServer(); //starts a local server
try {
Thread.sleep(1000); // Wait for the server to start
} catch (InterruptedException e) {
Thread.sleep(1000); // waits, to ensure, that the server in the separate Thread has enough time to start properly
}
catch (Exception e) {
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
connectServer(); // connects to the server, that was just created
}
else {
connectServer(); // connects to existing server, when the server si not running, or not started by one of the clients
}
// Proceed with connecting to the server
connectServer();
}
/**
* Toggle Method for Boolean
*starts a local server, in another thread
*/
private void toggleServer(){
serverToggle = !serverToggle;
}
/**
* Allows Client to Start a Server in a new Thread
*/
private void startServer() {
new Thread(() -> {
private void startLocalServer() {
new Thread(() -> { //creates new Thread
try {
// Initialize and run the server
battleshipServer = new BattleshipServer();
battleshipServer.run(Integer.parseInt(port.getText()));
} catch (Exception e) {
LOGGER.log(Level.ERROR, e);
BattleshipLocalServer battleshipLocalServer = new BattleshipLocalServer(Integer.parseInt(port.getText())); // creates local server, with the given port numbers
battleshipLocalServer.run(); // runs the local server
}
}).start();
catch (Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
}
}).start(); // starts the thread
}
/**
@@ -186,7 +149,8 @@ private Object initNetwork() {
try {
network.initNetwork(hostname, portNumber);
return null;
} catch (Exception e) {
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
@@ -201,9 +165,11 @@ public void update(float delta) {
try {
connectionFuture.get();
success();
} catch (ExecutionException e) {
}
catch (ExecutionException e) {
failure(e.getCause());
} catch (InterruptedException e) {
}
catch (InterruptedException e) {
LOGGER.log(Level.WARNING, "Interrupted!", e); //NON-NLS
Thread.currentThread().interrupt();
}

View File

@@ -1,155 +0,0 @@
package pp.battleship.client.gui;
import com.jme3.asset.AssetManager;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.material.Material;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.scene.Node;
import com.jme3.scene.control.AbstractControl;
import pp.battleship.client.BattleshipApp;
import pp.battleship.model.Shot;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
/**
* Manages the visual effects for impact events such as hits and misses.
*/
public class ImpactEffectManager {
private final AssetManager assetManager;
private static final Logger LOGGER = System.getLogger(ImpactEffectManager.class.getName());
private Material particleMaterial;
private BattleshipApp app;
/**
* Constructor to initialize the asset manager via the main application.
*
* @param app The main application instance.
*/
public ImpactEffectManager(BattleshipApp app) {
this.app = app;
this.assetManager = app.getAssetManager();
this.particleMaterial = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
}
/**
* Generates a visual effect for a hit at the specified position.
*
* @param battleshipNode The node where the effect should be attached.
* @param shot The details of the shot where the hit occurred.
*/
public void triggerHitEffect(Node battleshipNode, Shot shot) {
ParticleEmitter hitEffect = createParticleEmitter("HitEffect", 50, ColorRGBA.Orange, ColorRGBA.Red, 0.45f, 0.1f, 1f, 2f);
hitEffect.setLocalTranslation(shot.getY() + 0.5f, 0, shot.getX() + 0.5f);
LOGGER.log(Level.DEBUG, "Hit effect created at position: {0}", hitEffect.getLocalTranslation().toString());
// hitEffect.emitAllParticles();
hitEffect.addControl(new EffectCleanupControl(hitEffect));
app.getRootNode().attachChild(hitEffect);
}
/**
* Creates a visual effect for a missed shot at the specified location.
*
* @param shot The details of the missed shot.
* @return The particle emitter representing the miss effect.
*/
public ParticleEmitter triggerMissEffect(Shot shot) {
ParticleEmitter missEffect = createParticleEmitter("MissEffect", 50, ColorRGBA.Blue, ColorRGBA.Cyan, 0.3f, 0.05f, 0.5f, 1.5f);
missEffect.setLocalTranslation(shot.getY() + 0.5f, 0, shot.getX() + 0.5f);
missEffect.addControl(new EffectCleanupControl(missEffect));
return missEffect;
}
/**
* Helper method to create a particle emitter with predefined parameters.
*
* @param name The name of the particle emitter.
* @param count The number of particles to emit.
* @param startColor The initial color of the particles.
* @param endColor The final color of the particles.
* @param startSize The initial size of the particles.
* @param endSize The final size of the particles.
* @param lowLife The minimum lifetime of the particles.
* @param highLife The maximum lifetime of the particles.
* @return The configured ParticleEmitter instance.
*/
private ParticleEmitter createParticleEmitter(String name, int count, ColorRGBA startColor, ColorRGBA endColor, float startSize, float endSize, float lowLife, float highLife) {
ParticleEmitter emitter = new ParticleEmitter(name, Type.Triangle, count);
emitter.setNumParticles(0);
emitter.setMaterial(particleMaterial);
emitter.setImagesX(2);
emitter.setImagesY(2);
emitter.setStartColor(startColor);
emitter.setEndColor(endColor);
emitter.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 1, 0));
emitter.setStartSize(startSize);
emitter.setEndSize(endSize);
emitter.setGravity(0, -0.5f, 0);
emitter.setLowLife(lowLife);
emitter.setHighLife(highLife);
return emitter;
}
/**
* Custom control class to handle the cleanup of particle effects once they are no longer visible.
*/
private static class EffectCleanupControl extends AbstractControl {
private final ParticleEmitter emitter;
private float currentTime = 0;
private final float duration = 3.5f;
/**
* Constructor for managing cleanup of a standalone particle emitter.
*
* @param emitter The particle emitter to manage.
*/
public EffectCleanupControl(ParticleEmitter emitter) {
this.emitter = emitter;
}
/**
* Removes the emitter when all particles are no longer visible.
*
* @param tpf Time per frame.
*/
@Override
protected void controlUpdate(float tpf) {
currentTime += tpf;
if (currentTime <= duration) {
}
if (currentTime >= 1f && currentTime <= 1.1) {
//Start
emitter.setNumParticles(50);
emitter.setParticlesPerSec(50);
}
if (currentTime >= duration){
emitter.setParticlesPerSec(0);
}
if (currentTime >= duration+1f) {
//Ende
spatial.removeFromParent();
emitter.emitAllParticles();
}
}
/**
* No custom rendering needed; particle behavior is handled in controlUpdate.
* @param rm handles rendering, and ViewPort
* @param vp defines the view where the scene is displayed.
*/
@Override
protected void controlRender(com.jme3.renderer.RenderManager rm, com.jme3.renderer.ViewPort vp) {
// No rendering-specific behavior needed for this control.
}
}
}

View File

@@ -15,6 +15,7 @@
import pp.battleship.model.Shell;
import pp.battleship.model.Shot;
import pp.util.Position;
import java.lang.System.Logger;
/**
@@ -23,13 +24,14 @@
* whenever changes occur in the model.
*/
class MapViewSynchronizer extends ShipMapSynchronizer {
private static final Logger LOGGER = System.getLogger(MapViewSynchronizer.class.getName());
// Constants for rendering properties
private static final float SHIP_LINE_WIDTH = 6f;
private static final float SHOT_DEPTH = -2f;
private static final float SHIP_DEPTH = 0f;
private static final float INDENT = 4f;
private static final float SHELL_DEPTH = 8f;
private static final float SHELL_IN_GRID = 0.1f;
// Colors used for different visual elements
private static final ColorRGBA HIT_COLOR = ColorRGBA.Red;
@@ -114,23 +116,34 @@ public Spatial visit(Battleship ship) {
}
/**
* Creates a visual representation (Spatial) for the given shell, attaching a control for its behavior.
* @param shell the shell to visit and visualize
* @return the constructed shell node (Spatial)
* this method will create a representation of a shell in the map
*
* @param shell the Shell element to visit
* @return the node the representation is attached to
*/
@Override
public Spatial visit(Shell shell) {
LOGGER.log(Logger.Level.DEBUG, "Visiting {0}", shell);
final Node shellNode = new Node("shell");
final Position startPosition = view.modelToView(shell.getCurrentPosition().x,shell.getCurrentPosition().z);
shellNode.attachChild(view.getApp().getDraw().makeRectangle(startPosition.getX(),startPosition.getY(), SHELL_DEPTH, 30, 30, ColorRGBA.Black));
shellNode.addControl(new ShellControl(shell, this.view, shell.getLogic()));
final Position target = view.modelToView(shell.getX(), shell.getY());
final Position startPosition = view.modelToView(SHELL_IN_GRID, SHELL_IN_GRID);
shellNode.attachChild(createShell());
shellNode.setLocalTranslation(startPosition.getX(), startPosition.getY(), SHELL_DEPTH);
shellNode.scale(18f);
shellNode.addControl(new ShellMapControl(view.getApp(), target, shell));
return shellNode;
}
/**
* returns the red dot for the shell in the MapViewSynchronizer
*
* @return Spatial
*/
private Spatial createShell() {
return view.getApp().getDraw().makeFilledCircle(ColorRGBA.Red);
}
/**
* Creates a line geometry representing part of the ship's border.
*

View File

@@ -7,17 +7,26 @@
package pp.battleship.client.gui;
import com.jme3.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.material.Material;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.math.Vector3f;
import com.jme3.renderer.queue.RenderQueue.ShadowMode;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.shape.Box;
import com.jme3.scene.shape.Cylinder;
import pp.battleship.client.BattleshipApp;
import pp.battleship.model.*;
import pp.battleship.model.Battleship;
import pp.battleship.model.Rotation;
import pp.battleship.model.Shell;
import pp.battleship.model.ShipMap;
import pp.battleship.model.Shot;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import static java.util.Objects.requireNonNull;
import static pp.util.FloatMath.HALF_PI;
@@ -30,22 +39,21 @@
* logic for the sea map.
*/
class SeaSynchronizer extends ShipMapSynchronizer {
private static final Logger LOGGER = System.getLogger(SeaSynchronizer.class.getName());
private static final String UNSHADED = "Common/MatDefs/Misc/Unshaded.j3md"; //NON-NLS
private static final String KING_GEORGE_V_MODEL = "Models/KingGeorgeV/KingGeorgeV.j3o"; //NON-NLS
private static final String DESTROYER = "Models/Destroyer/Destroyer.j3o";
private static final String FERRY = "Models/Ferry/13922_Staten_Island_Ferry_V1_l1.obj";
private static final String SMALL = "Models/Small/10634_SpeedBoat_v01_LOD3.obj";
private static final String BOMB = "Models/Bomb/BombGBU.j3o";
private static final String SUBMARINE = "Models/Submarine/submarine.j3o";
private static final String DESTROYER = "Models/Destroyer/10619_Battleship.j3o";
private static final String SMALL_SHIP = "Models/SmallShip/10634_SpeedBoat_v01_LOD3.obj";
private static final String PARTICLE = "Common/MatDefs/Misc/Particle.j3md";
private static final String COLOR = "Color"; //NON-NLS
private static final String SHIP = "ship"; //NON-NLS
private static final String SHOT = "shot"; //NON-NLS
private static final String ROCKET = "Models/Rocket/rocket.j3o";
private static final ColorRGBA BOX_COLOR = ColorRGBA.Gray;
private static final ColorRGBA SPLASH_COLOR = new ColorRGBA(0f, 0f, 1f, 0.4f);
private static final ColorRGBA HIT_COLOR = new ColorRGBA(1f, 0f, 0f, 0.4f);
private final ShipMap map;
private final BattleshipApp app;
private ImpactEffectManager effectHandler;
/**
* Constructs a {@code SeaSynchronizer} object with the specified application, root node, and ship map.
@@ -58,7 +66,6 @@ public SeaSynchronizer(BattleshipApp app, Node root, ShipMap map) {
super(app.getGameLogic().getOwnMap(), root);
this.app = app;
this.map = map;
effectHandler = new ImpactEffectManager(app);
addExisting();
}
@@ -72,7 +79,20 @@ public SeaSynchronizer(BattleshipApp app, Node root, ShipMap map) {
*/
@Override
public Spatial visit(Shot shot) {
return shot.isHit() ? handleHit(shot) : effectHandler.triggerMissEffect(shot);
return shot.isHit() ? handleHit(shot) : handleMiss(shot);
}
/**
* Handles a miss
*
* @param shot a hit
* @return always null to prevent the representation from being attached
* to the items node as well
*/
private Spatial handleMiss(Shot shot) {
final ParticleEmitter emitter = createMissParticle(shot);
return emitter;
}
/**
@@ -86,33 +106,112 @@ public Spatial visit(Shot shot) {
private Spatial handleHit(Shot shot) {
final Battleship ship = requireNonNull(map.findShipAt(shot), "Missing ship");
final Node shipNode = requireNonNull((Node) getSpatial(ship), "Missing ship node");
System.out.println(shot.getX() + " " + shot.getY());
effectHandler.triggerHitEffect(shipNode, shot);
final ParticleEmitter particleEmitter = createHitParticle(shot);
particleEmitter.getLocalTranslation().subtractLocal(shipNode.getLocalTranslation());
shipNode.attachChild(particleEmitter);
final ParticleEmitter fire = createFire(shot);
shipNode.attachChild(fire);
return null;
}
/**
* Creates a cylinder geometry representing the specified shot.
* The appearance of the cylinder depends on whether the shot is a hit or a miss.
* this method attach fire to the ship, if it is hit
*
* @param shot the shot to be represented
* @return the geometry representing the shot
* @param shot the shot, that hit the ship
* @return the Fire
*/
private Geometry createCylinder(Shot shot) {
final ColorRGBA color = shot.isHit() ? HIT_COLOR : SPLASH_COLOR;
final float height = shot.isHit() ? 1.2f : 0.1f;
private ParticleEmitter createFire(Shot shot) {
ParticleEmitter hitEffect = new ParticleEmitter("fire", Type.Triangle, 5000);
hitEffect.setMaterial(new Material(app.getAssetManager(), PARTICLE));
hitEffect.setImagesX(2);
hitEffect.setImagesY(2);
hitEffect.setStartColor(ColorRGBA.Orange);
hitEffect.setEndColor(ColorRGBA.Red);
hitEffect.setStartSize(0.1f);
hitEffect.setEndSize(0.05f);
hitEffect.getParticleInfluencer().setInitialVelocity(new Vector3f(0,1,0));
hitEffect.setParticlesPerSec(5);
hitEffect.setLowLife(1f);
hitEffect.setHighLife(1f);
final Node shipNode = requireNonNull((Node) getSpatial(map.findShipAt(shot.getX(), shot.getY())), "Missing ship node");
hitEffect.setGravity(0, -0.9f, 0);
Vector3f shipNodePos = shipNode.getLocalTranslation();
Vector3f shotWorld = mapToWorldCord(shot.getX(), shot.getY());
Vector3f firePos = shotWorld.subtract(shipNodePos);
if (map.findShipAt(shot.getX(), shot.getY()).getLength() == 2) {
hitEffect.setLocalTranslation(firePos.x, 0.15f, firePos.z);
} else {
hitEffect.setLocalTranslation(firePos.x, 0.3f, firePos.z);
}
return hitEffect;
}
final Cylinder cylinder = new Cylinder(2, 20, 0.45f, height, true);
final Geometry geometry = new Geometry(SHOT, cylinder);
/**
* this method converts 2d to 3d positions
*
* @param x x-Coordinate
* @param y-Coordinate
* @return the Position as a 3d Vector
*/
geometry.setMaterial(createColoredMaterial(color));
geometry.rotate(HALF_PI, 0f, 0f);
private Vector3f mapToWorldCord(int x, int y) {
return new Vector3f(y + 0.5f, 0, x + 0.5f);
}
geometry.setLocalTranslation(shot.getY() + 0.5f, 0f, shot.getX() + 0.5f);
/**
* this method creates the particles, when the shot misses
*
* @param shot is the parameter, where was shot
* @return the particle
*/
return geometry;
private ParticleEmitter createMissParticle(Shot shot) {
ParticleEmitter hitEffect = new ParticleEmitter("HitEffect", Type.Triangle, 30);
hitEffect.setMaterial(new Material(app.getAssetManager(), PARTICLE));
hitEffect.setImagesX(2);
hitEffect.setImagesY(2);
hitEffect.setStartColor(ColorRGBA.Cyan);
hitEffect.setEndColor(ColorRGBA.Blue);
hitEffect.getParticleInfluencer().setInitialVelocity(new Vector3f(0.1f, 0.1f, 0.1f));
hitEffect.move(0, -2, 0);
hitEffect.setStartSize(0.45f);
hitEffect.setEndSize(0.45f);
hitEffect.setGravity(0, -0.5f, 0);
hitEffect.setLowLife(1f);
hitEffect.setHighLife(1f);
hitEffect.setParticlesPerSec(0);
hitEffect.setLocalTranslation(shot.getY() + 0.5f, 0, shot.getX() + 0.5f);
hitEffect.emitAllParticles();
return hitEffect;
}
/**
* this method creates the particles, when a ship is hit
*
* @param shot says, where was shot
* @return the particle
*/
private ParticleEmitter createHitParticle(Shot shot) {
ParticleEmitter hitEffect = new ParticleEmitter("HitEffect", Type.Triangle, 30);
hitEffect.setMaterial(new Material(app.getAssetManager(), PARTICLE));
hitEffect.setImagesX(2);
hitEffect.setImagesY(2);
hitEffect.setStartColor(ColorRGBA.Orange);
hitEffect.setEndColor(ColorRGBA.Red);
hitEffect.getParticleInfluencer().setInitialVelocity(new Vector3f(1, 1, 1));
hitEffect.setStartSize(0.45f);
hitEffect.setEndSize(0.1f);
hitEffect.setGravity(0, -0.5f, 0);
hitEffect.setLowLife(1f);
hitEffect.setHighLife(2f);
hitEffect.setParticlesPerSec(0);
hitEffect.setLocalTranslation(shot.getY() + 0.5f, 0, shot.getX() + 0.5f);
hitEffect.emitAllParticles();
return hitEffect;
}
/**
@@ -131,46 +230,58 @@ public Spatial visit(Battleship ship) {
final float x = 0.5f * (ship.getMinY() + ship.getMaxY() + 1f);
final float z = 0.5f * (ship.getMinX() + ship.getMaxX() + 1f);
node.setLocalTranslation(x, 0f, z);
node.addControl(new ShipControl(ship));
node.addControl(new ShipControl(ship, map));
return node;
}
/**
* Visits a {@link Shell} and creates a graphical representation of it.
* The representation is a 3D model
*
* @param shell the shell to be represented
* @return the node containing the graphical representation of the shell
*/
@Override
public Spatial visit(Shell shell) {
final Spatial bombModel = app.getAssetManager().loadModel(BOMB);
LOGGER.log(Level.INFO, "was visited by SeaSynchronizer");
final Node node = new Node("Shell");
node.attachChild(createShell());
node.setLocalTranslation(shell.getY() + 0.5f, 10, shell.getX() + 0.5f);
node.addControl(new ShellControl(shell, app));
return node;
}
// Apply transformations to the bomb model (scale, rotate, etc. if needed)
bombModel.scale(0.05f);
bombModel.rotate(-HALF_PI, 0f, 0f);
// Set the position of the bomb at the shell's current position
bombModel.setLocalTranslation(shell.getCurrentPosition());
// Add a control to animate the bomb's movement (similar to the previous cylinder animation)
bombModel.addControl(new ShellControl(shell,shell.getLogic()));
return bombModel;
/**
* this method loads the Model
*
* @return model
*/
private Spatial createShell() {
LOGGER.log(Level.INFO, "created Shell");
final Spatial model = app.getAssetManager().loadModel(ROCKET);
model.rotate(PI, PI, 0);
model.scale(0.0002f);
model.move(0, 0, 0);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Creates the appropriate graphical representation of the specified battleship.
* The representation is a detailed model based on the length of the ship.
* The representation is either a detailed model or a simple box based on the length of the ship.
*
* @param ship the battleship to be represented
* @return the spatial representing the battleship
*/
private Spatial createShip(Battleship ship) {
//return ship.getLength() == 4 ? createBattleship(ship) : createBox(ship);
if (ship.getLength() == 4) {
return createBattleship(ship);
} else if (ship.getLength() == 3) {
return createBigShip(ship);
} else if (ship.getLength() == 2) {
return createMediumShip(ship);
} else if (ship.getLength() == 1) {
return createSmallShip(ship);
}
return createBattleship(ship);
return switch (ship.getLength()) {
case (1) -> createSmallShip(ship);
case (2) -> createSubmarine(ship);
case (3) -> createDestroyer(ship);
case (4) -> createBattleship(ship);
default -> createBox(ship);
};
}
/**
@@ -190,6 +301,54 @@ private Spatial createBox(Battleship ship) {
return geometry;
}
/**
* Creates a Destroyer to represent a battleship that has the length of 3.
*
* @param ship the battleship to be represented
* @return the model representing the battleship
*/
private Spatial createDestroyer(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(DESTROYER);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()) - HALF_PI, 0f);
model.scale(0.0001f);
model.move(0, 0.3f, 0);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Creates a Submarine to represent a battleship that has the length 2.
*
* @param ship the battleship to be represented
* @return the model representing the battleship
*/
private Spatial createSubmarine(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(SUBMARINE);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()), 0f);
model.scale(0.25f);
model.move(0, -0.2f, 0);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Creates a SmallShip to represent a battleship that has the length y.
*
* @param ship the battleship to be represented
* @return the model representing the battleship
*/
private Spatial createSmallShip(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(SMALL_SHIP);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()) + HALF_PI, 0f);
model.scale(0.001f);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Creates a new {@link Material} with the specified color.
* If the color includes transparency (i.e., alpha value less than 1),
@@ -225,53 +384,6 @@ private Spatial createBattleship(Battleship ship) {
return model;
}
/**
* Creates a detailed 3D model to represent a "Big Ship"
* @param ship The Battleship object with position and rotation info.
* @return the spatial representing the "Big Ship" battleship
*/
private Spatial createBigShip(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(DESTROYER);
model.move(0,0.4f,0);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()) + HALF_PI, 0f);
model.scale(0.0001f);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Creates a detailed 3D model to represent a "Medium Ship"
* @param ship The Battleship object with position and rotation info.
* @return the spatial representing the "Medium Ship" battleship
*/
private Spatial createMediumShip(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(FERRY);
model.move(0,0.25f,0);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()), 0f);
model.scale(0.00025f);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Creates a detailed 3D model to represent a "Small Ship"
* @param ship The Battleship object with position and rotation info.
* @return the spatial representing the "Small Ship" battleship
*/
private Spatial createSmallShip(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(SMALL);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()) + HALF_PI, 0f);
model.scale(0.0009f);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Calculates the rotation angle for the specified rotation.
*

View File

@@ -1,96 +1,68 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import pp.battleship.game.client.ClientGameLogic;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.client.BattleshipApp;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
import pp.battleship.notification.Sound;
import pp.util.Position;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
/**
* Controls the oscillating pitch motion of a battleship model in the game.
* The ship oscillates to simulate a realistic movement on water, based on its orientation and length.
* this class controls the Shell in the view
*/
class ShellControl extends AbstractControl {
public class ShellControl extends AbstractControl {
private final Shell shell;
private MapView view;
private final ClientGameLogic logic;
private final EffectMessage msg;
private boolean hasPlayedSound = false;
private static final Logger LOGGER = System.getLogger(ShellControl.class.getName());
/**
* Constructs a new ShipControl instance for the specified Battleship.
* The ship's orientation determines the axis of rotation, while its length influences
* the cycle duration and amplitude of the oscillation.
* the shell, that is displayed
*/
private Shell shell;
/**
* the Height, when the shell will despawn
*/
private static final Float HEIGHT = 0f;
/**
* the battleship app
*/
private BattleshipApp app;
/**
* the constructor for this class
*
* @param shell the Battleship object to control
* @param shell the shell it displays
* @param app the BattleshipApp
*/
public ShellControl(Shell shell, ClientGameLogic clientGameLogic) {
public ShellControl(Shell shell, BattleshipApp app) {
LOGGER.log(Level.INFO, "ShellControl has been initialized");
this.shell = shell;
this.logic = clientGameLogic;
this.msg = shell.getMsg();
this.app = app;
}
/**
* Initializes ShellControl with a shell, map view, and game logic.
* @param shell the shell to be controlled
* @param view the map view to display the shell
* @param clientGameLogic the game logic instance
*/
public ShellControl(Shell shell, MapView view, ClientGameLogic clientGameLogic) {
this.shell = shell;
this.view = view;
this.logic = clientGameLogic;
this.msg = shell.getMsg();
}
/**
* Updates the ship's pitch oscillation each frame. The ship's pitch is adjusted
* to create a continuous tilting motion, simulating the effect of waves.
* this method controls the movement of the shell in dependent on fpt
*
* @param tpf time per frame (in seconds), used to calculate the new pitch angle
* @param tpf time per frame (in seconds)
*/
@Override
protected void controlUpdate(float tpf) {
if (spatial == null)
return;
if (shell.isFinished() && !hasPlayedSound) {
if (!msg.getShot().isHit())
logic.playSound(Sound.SPLASH);
else if (msg.getDestroyedShip() == null)
logic.playSound(Sound.EXPLOSION);
else
logic.playSound(Sound.DESTROYED_SHIP);
hasPlayedSound = true;
}
if (view == null) {
shell.updatePosition(tpf);
spatial.setLocalTranslation(shell.getCurrentPosition());
if (spatial == null) return;
if (spatial.getLocalTranslation().getY() <= HEIGHT) {
spatial.getParent().detachChild(spatial);
app.getGameLogic().send(new AnimationEndMessage(new IntPoint(shell.getX(), shell.getY())));
} else {
shell.updatePosition(tpf);
Position pos2d = view.modelToView(shell.getCurrentPosition().x - 0.3f, shell.getCurrentPosition().z - 0.3f);
spatial.setLocalTranslation(pos2d.getY(), pos2d.getX(), 0);
spatial.move(0, -1 * 4f * tpf, 0);
}
}
/**
* Called during rendering, but no operations are needed as this control only affects spatial transformation.
* @param rm the RenderManager rendering the spatial
* @param vp the ViewPort being rendered
*/
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
// No rendering logic is needed for this control
//not in use
}
}

View File

@@ -0,0 +1,77 @@
package pp.battleship.client.gui;
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import pp.battleship.client.BattleshipApp;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
import pp.battleship.notification.Sound;
import pp.util.Position;
/**
* this class controls the behaviour of a shell in a 2d map
*/
public class ShellMapControl extends AbstractControl {
private static final System.Logger LOGGER = System.getLogger(ShellMapControl.class.getName());
/**
* the position in map-coordinates
*/
private final Position position;
/**
* the vector, the shell is going on the 2d screen
*/
private static final Vector3f vector = new Vector3f();
/**
* the battleship app
*/
private final BattleshipApp app;
/**
* the shell displayed
*/
private final Shell shell;
/**
* the constructor for this class
*
* @param app the Battleship app
* @param position the position shot at in map-coordinates
* @param shell the shell shot
*/
public ShellMapControl(BattleshipApp app, Position position, Shell shell) {
super();
this.position = position;
this.app = app;
this.shell = shell;
vector.set(new Vector3f(position.getX(), position.getY(), 0));
}
/**
* the update loop for this shell
*
* @param tpf time per frame (in seconds)
*/
protected void controlUpdate(float tpf) {
if (spatial.getLocalTranslation().getX() >= position.getX() && spatial.getLocalTranslation().getY() >= position.getY()) {
app.getGameLogic().playSound(Sound.ROCKET_STOP);
spatial.getParent().detachChild(spatial);
app.getGameLogic().send(new AnimationEndMessage(new IntPoint(shell.getX(), shell.getY())));
LOGGER.log(System.Logger.Level.DEBUG, "shell has been deleted", spatial.getLocalTranslation());
} else {
spatial.move(vector.mult(tpf));
}
}
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
}
}

View File

@@ -11,13 +11,13 @@
import com.jme3.math.Vector3f;
import com.jme3.renderer.RenderManager;
import com.jme3.renderer.ViewPort;
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import com.jme3.scene.control.AbstractControl;
import pp.battleship.model.Battleship;
import pp.battleship.model.ShipMap;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import static java.util.Objects.requireNonNull;
import static pp.util.FloatMath.DEG_TO_RAD;
import static pp.util.FloatMath.TWO_PI;
import static pp.util.FloatMath.sin;
@@ -51,14 +51,18 @@ class ShipControl extends AbstractControl {
* The current time within the oscillation cycle, used to calculate the ship's pitch angle.
*/
private float time;
/**
* The current Ship
* this attribute is the ship, this ShipControl controls
*/
private final Battleship battleship;
private final Battleship ship;
/**
* Logger for logging messages related to ShipControl operations.
* this CONST represents the sinking height, when the ship will be removed
*/
static final Logger LOGGER = System.getLogger(ShipControl.class.getName());
private static final Float SINKING_HEIGHT = -0.6f;
/**
* Constructs a new ShipControl instance for the specified Battleship.
@@ -67,8 +71,7 @@ class ShipControl extends AbstractControl {
*
* @param ship the Battleship object to control
*/
public ShipControl(Battleship ship) {
battleship = ship;
public ShipControl(Battleship ship, ShipMap map) {
// Determine the axis of rotation based on the ship's orientation
axis = switch (ship.getRot()) {
case LEFT, RIGHT -> Vector3f.UNIT_X;
@@ -76,8 +79,9 @@ public ShipControl(Battleship ship) {
};
// Set the cycle duration and amplitude based on the ship's length
cycle = battleship.getLength() * 2f;
cycle = ship.getLength() * 2f;
amplitude = 5f * DEG_TO_RAD / ship.getLength();
this.ship = ship;
}
/**
@@ -90,26 +94,30 @@ public ShipControl(Battleship ship) {
protected void controlUpdate(float tpf) {
// If spatial is null, do nothing
if (spatial == null) return;
if(ship.isDestroyed()){
if(spatial.getLocalTranslation().getY() < SINKING_HEIGHT) { // removes the ship, if it is completely sunk
spatial.getParent().detachChild(spatial);
}
else // sink the ship, if it's not completely sunk
spatial.move(0, tpf * 0.1f * -1, 0);
}
// Update the time within the oscillation cycle
time = (time + tpf) % cycle;
if (battleship.isDestroyed() && spatial.getLocalTranslation().getY() <= -0.6f) {
LOGGER.log(Level.INFO, "Ship removed {0}", spatial.getName());
spatial.getParent().detachChild(spatial);
} else if (battleship.isDestroyed()) {
spatial.move(0, -0.05f * tpf, 0);
} else {
// Update the time within the oscillation cycle
time = (time + tpf) % cycle;
// Calculate the current angle of the oscillation
final float angle = amplitude * sin(time * TWO_PI / cycle);
// Update the pitch Quaternion with the new angle
pitch.fromAngleAxis(angle, axis);
// Apply the pitch rotation to the spatial
spatial.setLocalRotation(pitch);
}
spatial.setLocalRotation(pitch);
}
/**
* This method is called during the rendering phase, but it does not perform any
* operations in this implementation as the control only influences the spatial's

View File

@@ -84,6 +84,7 @@ public void receivedEvent(ItemRemovedEvent event) {
@Override
public void receivedEvent(ItemAddedEvent event) {
if (shipMap == event.map())
add(event.item());
}
}

View File

@@ -7,19 +7,22 @@
package pp.battleship.client.server;
import com.jme3.network.*;
import com.jme3.network.ConnectionListener;
import com.jme3.network.HostedConnection;
import com.jme3.network.Message;
import com.jme3.network.MessageListener;
import com.jme3.network.Network;
import com.jme3.network.Server;
import com.jme3.network.serializing.Serializer;
import pp.battleship.BattleshipConfig;
import pp.battleship.game.server.Player;
import pp.battleship.game.server.ServerGameLogic;
import pp.battleship.game.server.ServerSender;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.ServerMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.*;
import pp.battleship.model.Battleship;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shot;
@@ -36,11 +39,12 @@
/**
* Server implementing the visitor pattern as MessageReceiver for ClientMessages
*/
public class BattleshipServer implements MessageListener<HostedConnection>, ConnectionListener, ServerSender {
private static final Logger LOGGER = System.getLogger(BattleshipServer.class.getName());
public class BattleshipLocalServer implements MessageListener<HostedConnection>, ConnectionListener, ServerSender {
private static final Logger LOGGER = System.getLogger(BattleshipLocalServer.class.getName());
private static final File CONFIG_FILE = new File("server.properties");
private final BattleshipConfig config = new BattleshipConfig();
private Server myServer;
private static int PORT_NUMBER;
private final ServerGameLogic logic;
private final BlockingQueue<ReceivedMessage> pendingMessages = new LinkedBlockingQueue<>();
@@ -56,35 +60,31 @@ public class BattleshipServer implements MessageListener<HostedConnection>, Conn
}
}
/**
* Creates the server.
* this constructs the local battleship server
*
* @param portNumber the port number, the local-host should be accessed at
*/
public BattleshipServer() {
BattleshipConfig config = new BattleshipConfig();
public BattleshipLocalServer(int portNumber) {
config.readFromIfExists(CONFIG_FILE);
PORT_NUMBER = portNumber;
LOGGER.log(Level.INFO, "Configuration: {0}", config); //NON-NLS
logic = new ServerGameLogic(this, config);
}
/**
* Starts the server on the given port and continuously processes incoming messages.
* @param port the port to start the server on
*/
public void run(int port) {
startServer(port);
public void run() {
startServer();
while (true)
processNextMessage();
}
/**
* Initializes and starts the server on the specified port, handling exceptions if the server fails to start.
* @param port the port to start the server on
* this method is used to start a server
*/
private void startServer(int port) {
private void startServer() {
try {
LOGGER.log(Level.INFO, "Starting server..."); //NON-NLS
myServer = Network.createServer(port);
myServer = Network.createServer(PORT_NUMBER); // creates new server, with the port given before
initializeSerializables();
myServer.start();
registerListeners();
@@ -96,9 +96,6 @@ private void startServer(int port) {
}
}
/**
* Retrieves and processes the next message from the queue, handling interruptions during the wait.
*/
private void processNextMessage() {
try {
pendingMessages.take().process(logic);
@@ -109,9 +106,6 @@ private void processNextMessage() {
}
}
/**
* Processes the next message from the queue, handling interruptions during message retrieval.
*/
private void initializeSerializables() {
Serializer.registerClass(GameDetails.class);
Serializer.registerClass(StartBattleMessage.class);
@@ -121,22 +115,18 @@ private void initializeSerializables() {
Serializer.registerClass(Battleship.class);
Serializer.registerClass(IntPoint.class);
Serializer.registerClass(Shot.class);
Serializer.registerClass(AnimationEndMessage.class);
Serializer.registerClass(AnimationStartMessage.class);
Serializer.registerClass(BackToBattleStateMessage.class);
}
/**
* Registers message and connection listeners for the server.
*/
private void registerListeners() {
myServer.addMessageListener(this, MapMessage.class);
myServer.addMessageListener(this, ShootMessage.class);
myServer.addMessageListener(this, AnimationEndMessage.class);
myServer.addConnectionListener(this);
}
/**
* Handles received messages, logging the source and adding client messages to the pending queue.
* @param source the connection the message was received from
* @param message the received message
*/
@Override
public void messageReceived(HostedConnection source, Message message) {
LOGGER.log(Level.INFO, "message received from {0}: {1}", source.getId(), message); //NON-NLS
@@ -144,22 +134,12 @@ public void messageReceived(HostedConnection source, Message message) {
pendingMessages.add(new ReceivedMessage(clientMessage, source.getId()));
}
/**
* Handles a new connection by logging it and adding a new player to the game logic.
* @param server the server receiving the connection
* @param hostedConnection the newly added connection
*/
@Override
public void connectionAdded(Server server, HostedConnection hostedConnection) {
LOGGER.log(Level.INFO, "new connection {0}", hostedConnection); //NON-NLS
logic.addPlayer(hostedConnection.getId());
}
/**
* Handles the removal of a connection by logging it, checking if it belongs to an active player, and exiting if necessary.
* @param server the server losing the connection
* @param hostedConnection the removed connection
*/
@Override
public void connectionRemoved(Server server, HostedConnection hostedConnection) {
LOGGER.log(Level.INFO, "connection closed: {0}", hostedConnection); //NON-NLS
@@ -172,10 +152,6 @@ public void connectionRemoved(Server server, HostedConnection hostedConnection)
}
}
/**
* Closes all client connections and terminates the server with the given exit value.
* @param exitValue the exit code to terminate the application with
*/
private void exit(int exitValue) { //NON-NLS
LOGGER.log(Level.INFO, "close request"); //NON-NLS
if (myServer != null)

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +0,0 @@
# Blender MTL File: 'untitletttd.blend'
# Material Count: 1
newmtl None
Ns 0
Ka 0.000000 0.000000 0.000000
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2
map_Kd C:\Users\Convidado.Cliente-JMF-PC\Desktop\ghftht.png

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +0,0 @@
based on:
https://free3d.com/3d-model/battleship-v1--611736.html
License: Free Personal Use Only

View File

@@ -0,0 +1,3 @@
This model is from the following website:
https://free3d.com/3d-model/battleship-v1--611736.html
License: Free Personal Use Only

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -1,64 +0,0 @@
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 13.03.2012 15:35:28
newmtl metall
Ns 31.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.2431 0.2431 0.2431
Kd 0.2431 0.2431 0.2431
Ks 0.5850 0.5850 0.5850
Ke 0.0000 0.0000 0.0000
newmtl 13922_StatenIslandFerry
Ns 50.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 1.0000 1.0000 1.0000
Kd 1.0000 1.0000 1.0000
Ks 0.5850 0.5850 0.5850
Ke 0.0000 0.0000 0.0000
map_Ka 13922_StatenIslandFerry_diffuse.jpg
map_Kd 13922_StatenIslandFerry_diffuse.jpg
newmtl metall2
Ns 50.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.2118 0.2824 0.3451
Kd 0.2118 0.2824 0.3451
Ks 0.5850 0.5850 0.5850
Ke 0.0000 0.0000 0.0000
newmtl boat
Ns 34.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.6588 0.3059 0.1294
Kd 0.6588 0.3059 0.1294
Ks 0.3600 0.3600 0.3600
Ke 0.0000 0.0000 0.0000
newmtl white
Ns 10.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.9686 0.9686 0.9686
Kd 0.9686 0.9686 0.9686
Ks 0.0000 0.0000 0.0000
Ke 0.0000 0.0000 0.0000

View File

@@ -1,3 +0,0 @@
based on:
https://free3d.com/3d-model/statenislandferry-v1--603882.html
License: Free Personal Use Only

View File

@@ -0,0 +1,3 @@
Rocket origin:
https://free3d.com/3d-model/proton-rocket-31617.html
Licence: free for personal use

View File

@@ -1,3 +0,0 @@
based on:
https://free3d.com/3d-model/speedboat-v01--840133.html
License: Free Personal Use Only

View File

@@ -0,0 +1,3 @@
This model is from following website:
https://free3d.com/3d-model/speedboat-v01--840133.html
License: Free Personal Use Only

View File

@@ -0,0 +1,3 @@
This model is from the following website:
https://free3d.com/3d-model/wwii-ship-german-type-ii-uboat-v2--700733.html
License: Free Personal Use Only

Binary file not shown.

After

Width:  |  Height:  |  Size: 168 KiB

View File

@@ -0,0 +1,16 @@
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 29.03.2012 14:25:39
newmtl default
Ns 35.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 1.0000 1.0000 1.0000
Kd 1.0000 1.0000 1.0000
Ks 0.5400 0.5400 0.5400
Ke 0.0000 0.0000 0.0000
map_Ka 14084_WWII_ship_German_Type_II_U-boat_diff.jpg
map_Kd 14084_WWII_ship_German_Type_II_U-boat_diff.jpg

View File

@@ -0,0 +1,3 @@
The soundtrack for the background-music is from:
https://pixabay.com/music/future-bass-nightfall-future-bass-music-228100/
the soundtrack is free to use

View File

@@ -0,0 +1,3 @@
RocketSound origin:
https://pixabay.com/sound-effects/rocket-loop-99748/
Licence: free to use

View File

@@ -41,7 +41,7 @@ public static void main(String[] args) {
*/
@Override
public void simpleInitApp() {
export("Models/Destroyer/10619_Battleship.obj", "Destroyer.j3o"); //NON-NLS
export("Models/KingGeorgeV/rocket/proton.obj", "proton.j3o"); //NON-NLS
stop();
}

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +0,0 @@
# Blender MTL File: 'untitletttd.blend'
# Material Count: 1
newmtl None
Ns 0
Ka 0.000000 0.000000 0.000000
Kd 0.8 0.8 0.8
Ks 0.8 0.8 0.8
d 1
illum 2
map_Kd C:\Users\Convidado.Cliente-JMF-PC\Desktop\ghftht.png

File diff suppressed because one or more lines are too long

View File

@@ -1,73 +0,0 @@
newmtl Battleship
illum 4
Kd 0.00 0.00 0.00
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
map_Kd BattleshipC.jpg
Ni 1.00
Ks 0.00 0.00 0.00
Ns 256.00
newmtl blinn1SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.00 0.00 0.00
Ns 256.00
newmtl blinn2SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.00 0.00 0.00
Ns 256.00
newmtl blinn3SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 256.00
newmtl blinn4SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 256.00
newmtl blinn5SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 256.00
newmtl blinn6SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 256.00
newmtl blinn7SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 256.00
newmtl blinn8SG
illum 4
Kd 0.50 0.50 0.50
Ka 0.00 0.00 0.00
Tf 1.00 1.00 1.00
Ni 1.00
Ks 0.50 0.50 0.50
Ns 256.00

Binary file not shown.

Before

Width:  |  Height:  |  Size: 360 KiB

View File

@@ -1,3 +0,0 @@
based on:
https://free3d.com/3d-model/battleship-v1--611736.html
License: Free Personal Use Only

View File

@@ -1,64 +0,0 @@
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 13.03.2012 15:35:28
newmtl metall
Ns 31.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.2431 0.2431 0.2431
Kd 0.2431 0.2431 0.2431
Ks 0.5850 0.5850 0.5850
Ke 0.0000 0.0000 0.0000
newmtl 13922_StatenIslandFerry
Ns 50.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 1.0000 1.0000 1.0000
Kd 1.0000 1.0000 1.0000
Ks 0.5850 0.5850 0.5850
Ke 0.0000 0.0000 0.0000
map_Ka 13922_StatenIslandFerry_diffuse.jpg
map_Kd 13922_StatenIslandFerry_diffuse.jpg
newmtl metall2
Ns 50.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.2118 0.2824 0.3451
Kd 0.2118 0.2824 0.3451
Ks 0.5850 0.5850 0.5850
Ke 0.0000 0.0000 0.0000
newmtl boat
Ns 34.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.6588 0.3059 0.1294
Kd 0.6588 0.3059 0.1294
Ks 0.3600 0.3600 0.3600
Ke 0.0000 0.0000 0.0000
newmtl white
Ns 10.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.9686 0.9686 0.9686
Kd 0.9686 0.9686 0.9686
Ks 0.0000 0.0000 0.0000
Ke 0.0000 0.0000 0.0000

View File

@@ -0,0 +1,116 @@
package pp.battleship.game.client;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.message.server.AnimationStartMessage;
import pp.battleship.message.server.BackToBattleStateMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
import pp.battleship.model.ShipMap;
import pp.battleship.notification.Sound;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
public class AnimationState extends ClientState {
private static final Logger LOGGER = System.getLogger(AnimationState.class.getName());
/**
* Constructs a client state of the specified game logic.
*
* @param logic the game logic
*/
AnimationState(ClientGameLogic logic, boolean myTurn, IntPoint pos) {
super(logic);
if (myTurn) {
logic.getOpponentMap().add(new Shell(pos));
logic.playSound(Sound.ROCKET);
} else {
logic.getOwnMap().add(new Shell(pos));
logic.playSound(Sound.ROCKET);
}
}
@Override
boolean showBattle() {
return true;
}
/**
* Reports the effect of a shot based on the server message.
*
* @param msg the message containing the effect of the shot
*/
@Override
public void receivedEffect(EffectMessage msg) {
logic.playSound(Sound.ROCKET_STOP);
ClientGameLogic.LOGGER.log(Level.INFO, "report effect: {0}", msg); //NON-NLS
playSound(msg);
logic.setInfoText(msg.getInfoTextKey()); //
affectedMap(msg).add(msg.getShot());
if (destroyedOpponentShip(msg)) {
logic.getOpponentMap().add(msg.getDestroyedShip());
}
if (msg.isGameOver()) {
msg.getRemainingOpponentShips().forEach(logic.getOpponentMap()::add);
logic.setState(new GameOverState(logic));
}
}
/**
* Determines which map (own or opponent's) should be affected by the shot based on the message.
*
* @param msg the effect message received from the server
* @return the map (either the opponent's or player's own map) that is affected by the shot
*/
private ShipMap affectedMap(EffectMessage msg) {
return msg.isOwnShot() ? logic.getOpponentMap() : logic.getOwnMap();
}
/**
* Checks if the opponent's ship was destroyed by the player's shot.
*
* @param msg the effect message received from the server
* @return true if the shot destroyed an opponent's ship, false otherwise
*/
private boolean destroyedOpponentShip(EffectMessage msg) {
return msg.getDestroyedShip() != null && msg.isOwnShot();
}
/**
* receives an AnimationStartMessage and sets the state to AnimationState
*
* @param msg the message received
*/
public void receivedAnimationStart(AnimationStartMessage msg) {
logic.setState(new AnimationState(logic, msg.isMyTurn(), msg.getPosition()));
}
/**
* Plays a sound based on the outcome of the shot. Different sounds are played for a miss, hit,
* or destruction of a ship.
*
* @param msg the effect message containing the result of the shot
*/
private void playSound(EffectMessage msg) {
if (!msg.getShot().isHit())
logic.playSound(Sound.SPLASH);
else if (msg.getDestroyedShip() == null)
logic.playSound(Sound.EXPLOSION);
else
logic.playSound(Sound.DESTROYED_SHIP);
}
/**
* receives a BackToBattleStateMessage and sets the state to BattleState
*
* @param msg the message received
*/
@Override
public void receiveBackToBattleState(BackToBattleStateMessage msg) {
logic.setState(new BattleState(logic, msg.isMyTurn()));
}
}

View File

@@ -7,15 +7,9 @@
package pp.battleship.game.client;
import com.jme3.math.Vector3f;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.AnimationStartMessage;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
import pp.battleship.model.ShipMap;
import pp.battleship.notification.Sound;
import java.lang.System.Logger.Level;
/**
* Represents the state of the client where players take turns to attack each other's ships.
@@ -35,8 +29,9 @@ public BattleState(ClientGameLogic logic, boolean myTurn) {
}
/**
* displays the battle scene.
* @return true to show the battle
* this return-statement decides, whether the battle will be shown
*
* @return true, so the battle will be displayed
*/
@Override
public boolean showBattle() {
@@ -44,8 +39,9 @@ public boolean showBattle() {
}
/**
* Handles clicking on the opponent's map. If it's the player's turn and the position is valid, a ShootMessage is sent.
* @param pos the clicked position on the opponent's map
* the logic, responsible for deciding, whether it was a valid input or not
*
* @param pos the position where the click occurred
*/
@Override
public void clickOpponentMap(IntPoint pos) {
@@ -56,43 +52,13 @@ else if (logic.getOpponentMap().isValid(pos))
}
/**
* Reports the effect of a shot based on the server message.
* Receives an AnimationStartEvent and changes then the client-state to AnimationState
*
* @param msg the message containing the effect of the shot
* @param msg the message received
*/
@Override
public void receivedEffect(EffectMessage msg) {
ClientGameLogic.LOGGER.log(Level.INFO, "report effect: {0}", msg); //NON-NLS
myTurn = msg.isMyTurn();
logic.playSound(Sound.MISSILE_LAUNCH);
logic.setInfoText(msg.getInfoTextKey());
affectedMap(msg).add(msg.getShot());
affectedMap(msg).add(new Shell(new Vector3f(0, 50, 0), new Vector3f(msg.getShot().getY() + 0.5f, -0.4f, msg.getShot().getX() + 0.5f), 1f,msg,logic));
if (destroyedOpponentShip(msg))
logic.getOpponentMap().add(msg.getDestroyedShip());
if (msg.isGameOver()) {
msg.getRemainingOpponentShips().forEach(logic.getOpponentMap()::add);
logic.setState(new GameOverState(logic));
}
public void receivedAnimationStart(AnimationStartMessage msg) {
logic.setState(new AnimationState(logic, msg.isMyTurn(), msg.getPosition()));
}
/**
* Determines which map (own or opponent's) should be affected by the shot based on the message.
*
* @param msg the effect message received from the server
* @return the map (either the opponent's or player's own map) that is affected by the shot
*/
private ShipMap affectedMap(EffectMessage msg) {
return msg.isOwnShot() ? logic.getOpponentMap() : logic.getOwnMap();
}
/**
* Checks if the opponent's ship was destroyed by the player's shot.
*
* @param msg the effect message received from the server
* @return true if the shot destroyed an opponent's ship, false otherwise
*/
private boolean destroyedOpponentShip(EffectMessage msg) {
return msg.getDestroyedShip() != null && msg.isOwnShot();
}
}

View File

@@ -8,10 +8,7 @@
package pp.battleship.game.client;
import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.ServerInterpreter;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.*;
import pp.battleship.model.IntPoint;
import pp.battleship.model.ShipMap;
import pp.battleship.model.dto.ShipMapDTO;
@@ -226,6 +223,26 @@ public void received(EffectMessage msg) {
state.receivedEffect(msg);
}
/**
* Reports the AnimationStartMessage based on the server-state
*
* @param animationStartMessage the StartMessage received
*/
@Override
public void received(AnimationStartMessage animationStartMessage) {
state.receivedAnimationStart(animationStartMessage);//TODO
}
/**
* Reports the BackToBattleStateMessage based on the server-state
*
* @param backToBattleStateMessage the Message received
*/
@Override
public void received(BackToBattleStateMessage backToBattleStateMessage) {
state.receiveBackToBattleState(backToBattleStateMessage);
}
/**
* Initializes the player's own map, opponent's map, and harbor based on the game details.
*
@@ -304,7 +321,7 @@ public void saveMap(File file) throws IOException {
*
* @param msg the message to be sent
*/
void send(ClientMessage msg) {
public void send(ClientMessage msg) {
if (clientSender == null)
LOGGER.log(Level.ERROR, "trying to send {0} with sender==null", msg); //NON-NLS
else

View File

@@ -7,9 +7,7 @@
package pp.battleship.game.client;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.*;
import pp.battleship.model.IntPoint;
import java.io.File;
@@ -165,6 +163,13 @@ void receivedEffect(EffectMessage msg) {
ClientGameLogic.LOGGER.log(Level.ERROR, "receivedEffect not allowed in {0}", getName()); //NON-NLS
}
/**
* @param msg the message received
*/
void receivedAnimationStart(AnimationStartMessage msg) {
ClientGameLogic.LOGGER.log(Level.ERROR, "receivedAnimationStart not allowed in {0}", getName());
}
/**
* Loads a map from the specified file.
*
@@ -193,6 +198,15 @@ boolean maySaveMap() {
return true;
}
/**
* Received a BackToBattleStateMessage and logs it
*
* @param msg the message received
*/
public void receiveBackToBattleState(BackToBattleStateMessage msg) {
ClientGameLogic.LOGGER.log(Level.ERROR, "receivedBackToBattleState not allowed in {0}", getName());
}
/**
* Called once per frame by the update loop if this state is active.
*

View File

@@ -10,12 +10,14 @@
import pp.battleship.message.client.MapMessage;
import pp.battleship.model.Battleship;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Rotation;
import pp.battleship.model.ShipMap;
import pp.battleship.model.dto.ShipMapDTO;
import java.io.File;
import java.io.IOException;
import java.lang.System.Logger.Level;
import java.util.ArrayList;
import java.util.List;
import static pp.battleship.Resources.lookup;
@@ -112,7 +114,8 @@ private void placeShip(IntPoint cursor) {
harbor().remove(selectedInHarbor);
preview = null;
selectedInHarbor = null;
} else {
}
else {
preview.setStatus(INVALID_PREVIEW);
ownMap().add(preview);
}
@@ -135,7 +138,8 @@ public void clickHarbor(IntPoint pos) {
harbor().add(selectedInHarbor);
preview = null;
selectedInHarbor = null;
} else if (shipAtCursor != null) {
}
else if (shipAtCursor != null) {
selectedInHarbor = shipAtCursor;
selectedInHarbor.setStatus(VALID_PREVIEW);
harbor().remove(selectedInHarbor);
@@ -227,7 +231,7 @@ private ShipMap harbor() {
}
/**
* Loads a map from the specified file. Also Checks if the map is valid
* Loads a map from the specified file.
*
* @param file the file to load the map from
* @throws IOException if the map cannot be loaded
@@ -237,8 +241,8 @@ public void loadMap(File file) throws IOException {
final ShipMapDTO dto = ShipMapDTO.loadFrom(file);
if (!dto.fits(logic.getDetails()))
throw new IOException(lookup("map.doesnt.fit"));
if(!validMap(dto)){
throw new IOException(lookup("map.is.invalid"));
if (!verifyMap(dto)) {
throw new IOException(lookup("player.submitted.invalid.map"));
}
ownMap().clear();
dto.getShips().forEach(ownMap()::add);
@@ -247,6 +251,50 @@ public void loadMap(File file) throws IOException {
selectedInHarbor = null;
}
/**
* this method returns true, if the given map is valid (don't overlap or out of bound)
*
* @param dto the map
* @return true, if the map is valid
*/
private boolean verifyMap(ShipMapDTO dto) { //MapMessage msg, int playerID
return verifyBounds(dto) && verifyOverlap(dto);
}
/**
* checks, whether a ship is out of the grid
*
* @param dto is the Map, where the ships are in
* @return true, if all ships are in bound
*/
private boolean verifyBounds(ShipMapDTO dto) {
int mapWidth = dto.getWidth();
int mapHeight = dto.getHeight();
for (Battleship ship : dto.getShips()) {
if (ship.getMaxX() > mapWidth || ship.getMinX() < 0 || ship.getMaxY() > mapHeight || ship.getMinY() < 0)
return false;
}
return true;
}
/**
* checks whether the ships overlap each other
*
* @param dto ist the map, where the ships are in
* @return true, if no ships overlap
*/
private boolean verifyOverlap(ShipMapDTO dto) {
List<Battleship> ships = dto.getShips();
for (Battleship ship : ships) {
for (Battleship compareShip : ships) {
if (!ship.equals(compareShip)) {
if (ship.collidesWith(compareShip)) return false;
}
}
}
return true;
}
/**
* Checks if the player's own map may be loaded from a file.
*
@@ -266,51 +314,4 @@ public boolean mayLoadMap() {
public boolean maySaveMap() {
return harbor().getItems().isEmpty();
}
/**
* Checks if the map is valid in terms of overlapping and if the ship is within the boundries of the map
* @param dto DataTransferObject is the loaded json file
* @return returns true if the map is valid, false otherwhise
*/
private boolean validMap(ShipMapDTO dto) {
return inBoundsClient(dto) && overLapClient(dto);
}
/**
* Checks if the Ships overlap on the map
* @param dto DataTransferObject is the loaded json file
* @return returns true if the ships arent overlapping, false otherwhise
*/
private boolean overLapClient(ShipMapDTO dto) {
List<Battleship> battleshipList = dto.getShips();
for (int i = 0; i < battleshipList.size(); i++) {
Battleship ship1 = battleshipList.get(i);
for (int j = i + 1; j < battleshipList.size(); j++) {
Battleship ship2 = battleshipList.get(j);
if (ship1.collidesWith(ship2)) {
return false;
}
}
}
return true;
}
/**
* Checks if the Ship is in the map Boundries
* @param dto DataTransferObject is the loaded json file
* @return true if the ship is in the maps boundriess, false otherwhise
*/
private boolean inBoundsClient(ShipMapDTO dto) {
int widht = dto.getWidth();
int height = dto.getHeight();
for (int i = 0; i < dto.getShips().size(); i++) {
Battleship localShip = dto.getShips().get(i);
if (!(localShip.getMaxX() < widht && localShip.getMaxY() < height && localShip.getMinY() >= 0 && localShip.getMinX() >= 0)) {
return false;
}
}
return true;
}
}

View File

@@ -7,6 +7,7 @@
package pp.battleship.game.client;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.StartBattleMessage;
import java.lang.System.Logger.Level;
@@ -38,4 +39,18 @@ public void receivedStartBattle(StartBattleMessage msg) {
logic.setInfoText(msg.getInfoTextKey());
logic.setState(new BattleState(logic, msg.isMyTurn()));
}
/**
* Handles the GameDetails message received from the server.
* If the map is invalid, the editor state is set.
*
* @param msg the GameDetails message received
*/
@Override
public void receivedGameDetails(GameDetails msg) {
ClientGameLogic.LOGGER.log(Level.WARNING, "Invalid Map"); //NON-NLS
logic.setInfoText("map.invalid");
logic.setState(new EditorState(logic));
}
}

View File

@@ -8,13 +8,11 @@
package pp.battleship.game.server;
import pp.battleship.BattleshipConfig;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.ServerMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.*;
import pp.battleship.model.Battleship;
import pp.battleship.model.IntPoint;
@@ -38,6 +36,8 @@ public class ServerGameLogic implements ClientInterpreter {
private final ServerSender serverSender;
private Player activePlayer;
private ServerState state = ServerState.WAIT;
private boolean playerOneAnimationReady = false;
private boolean playerTwoAnimationReady = false;
/**
* Constructs a ServerGameLogic with the specified sender and configuration.
@@ -54,7 +54,6 @@ public ServerGameLogic(ServerSender serverSender, BattleshipConfig config) {
* Returns the state of the game.
*/
ServerState getState() {
return state;
}
@@ -134,7 +133,7 @@ public Player addPlayer(int id) {
}
/**
* Handles the reception of a MapMessage. Also Checks if the given map is valid or invalid
* Handles the reception of a MapMessage.
*
* @param msg the received MapMessage
* @param from the ID of the sender client
@@ -143,60 +142,77 @@ public Player addPlayer(int id) {
public void received(MapMessage msg, int from) {
if (state != ServerState.SET_UP)
LOGGER.log(Level.ERROR, "playerReady not allowed in {0}", state); //NON-NLS
else if(!validMap(msg,from)){
LOGGER.log(Level.ERROR, "Map message not valid",state);
}
else
else if (!verifyMap(msg, from)) {
LOGGER.log(Level.ERROR, "player submitted invalid map", state);
send(getPlayerById(from), new GameDetails(config));
} else
playerReady(getPlayerById(from), msg.getShips());
}
/**
* Checks if the map is Valid in terms of boundries and overlaps
* *
* @param msg the received MapMessage
* @param id the ID of the sender client
* @return returns true if the map is valid, false otherwhise
*/
private boolean validMap(MapMessage msg, int id) {
return inBounds(msg, id) && overLap(msg);
@Override
public void received(AnimationEndMessage msg, int from) {
LOGGER.log(Level.INFO, "AnimationEndMessage was received by ServerGameLogic");
if (state != ServerState.ANIMATION_WAIT_STATE)
LOGGER.log(Level.ERROR, "animation not allowed in {0}", state);
else if (getPlayerById(from) == players.get(0)) {
LOGGER.log(Level.DEBUG, "{0} set to true", getPlayerById(from));
playerOneAnimationReady = true;
shoot(getPlayerById(from), msg.getPosition());
} else if (getPlayerById(from) == players.get(1)) {
LOGGER.log(Level.DEBUG, "{0} set to true {1}", getPlayerById(from), getPlayerById(from).toString());
playerTwoAnimationReady = true;
shoot(getPlayerById(from), msg.getPosition());
}
if (playerOneAnimationReady && playerTwoAnimationReady) {
setState(ServerState.BATTLE);
for (Player player : players)
send(player, new BackToBattleStateMessage(player == activePlayer));
playerOneAnimationReady = false;
playerTwoAnimationReady = false;
}
}
/**
* Checks if the Ships overLap
* this method returns true, if the given map is valid (don't overlap or out of bound)
*
* @param msg the received MapMessage
* @return returns true if the ships arent overlapping, false otherwhise
* @param msg the message, where the map is in
* @param playerID the player, who committed the map
* @return true, if the map is valid
*/
private boolean overLap(MapMessage msg) {
List<Battleship> battleshipList = msg.getShips();
private boolean verifyMap(MapMessage msg, int playerID) {
return verifyBounds(msg, playerID) && verifyOverlap(msg);
}
for (int i = 0; i < battleshipList.size(); i++) {
Battleship ship1 = battleshipList.get(i);
for (int j = i + 1; j < battleshipList.size(); j++) {
Battleship ship2 = battleshipList.get(j);
if (ship1.collidesWith(ship2)) {
/**
* checks, whether a ship is out of the grid
*
* @param msg is the message, where the map is in
* @return true, if all ships are in bound
*/
private boolean verifyBounds(MapMessage msg, int playerID) {
int mapWidth = getPlayerById(playerID).getMap().getWidth();
int mapHeight = getPlayerById(playerID).getMap().getHeight();
for (Battleship ship : msg.getShips()) {
if (ship.getMaxX() > mapWidth || ship.getMinX() < 0 || ship.getMaxY() > mapHeight || ship.getMinY() < 0)
return false;
}
}
}
return true;
}
/**
* Checks if the Ship is placed in Bounds with the Map
* checks whether the ships overlap each other
*
* @param msg the received MapMessage
* @param id the ID of the sender client
* @return returns true if the ship is within the maps boundries, false otherwhise
* @param msg is the message, where the map is in
* @return true, if no ships overlap
*/
private boolean inBounds(MapMessage msg, int id) {
int widht = getPlayerById(id).getMap().getWidth();
int height = getPlayerById(id).getMap().getHeight();
for (int i = 0; i < msg.getShips().size(); i++) {
Battleship localShip = msg.getShips().get(i);
if (!(localShip.getMaxX() < widht && localShip.getMaxY() < height && localShip.getMinY() >= 0 && localShip.getMinX() >= 0)) {
return false;
private boolean verifyOverlap(MapMessage msg) {
List<Battleship> ships = msg.getShips();
for (Battleship ship : ships) {
for (Battleship compareShip : ships) {
if (!ship.equals(compareShip)) {
if (ship.collidesWith(compareShip)) return false;
}
}
}
return true;
@@ -212,8 +228,13 @@ private boolean inBounds(MapMessage msg, int id) {
public void received(ShootMessage msg, int from) {
if (state != ServerState.BATTLE)
LOGGER.log(Level.ERROR, "shoot not allowed in {0}", state); //NON-NLS
else
shoot(getPlayerById(from), msg.getPosition());
else {
for (Player player : players) {
send(player, new AnimationStartMessage(msg.getPosition(), player == activePlayer));
setState(ServerState.ANIMATION_WAIT_STATE);
}
}
}
/**
@@ -240,34 +261,124 @@ void playerReady(Player player, List<Battleship> ships) {
* Handles the shooting action by the player.
*
* @param p the player who shot
* @param pos the position of the shot
* @param position the position of the shot
*/
void shoot(Player p, IntPoint pos) {
if (p != activePlayer) return;
final Player otherPlayer = getOpponent(activePlayer);
final Battleship selectedShip = otherPlayer.getMap().findShipAt(pos);
void shoot(Player p, IntPoint position) {
final Battleship selectedShip;
selectedShip = getSelectedShip(p, position);
if (selectedShip == null) {
// shot missed
send(activePlayer, EffectMessage.miss(true, pos));
send(otherPlayer, EffectMessage.miss(false, pos));
activePlayer = otherPlayer;
nullShip(p, position);
} else {
// shot hit a ship
selectedShip.hit(pos);
if (otherPlayer.getMap().getRemainingShips().isEmpty()) {
// game is over
send(activePlayer, EffectMessage.won(pos, selectedShip));
send(otherPlayer, EffectMessage.lost(pos, selectedShip, activePlayer.getMap().getRemainingShips()));
setState(ServerState.GAME_OVER);
shootShip(p, position, selectedShip);
}
}
/**
* getter for the selected battleship through the shot
*
* @param p the current player
* @param position the position shot at
* @return the battleship, on the position shot at
*/
private Battleship getSelectedShip(Player p, IntPoint position) {
return (p != activePlayer) ? p.getMap().findShipAt(position) : getOpponent(p).getMap().findShipAt(position);
}
/**
* this method handles the shot logic, if the shot misses
*
* @param p the current player
* @param position the position shot at
*/
private void nullShip(Player p, IntPoint position) {
if (p != activePlayer) {
send(p, EffectMessage.miss(false, position));
} else {
send(activePlayer, EffectMessage.miss(true, position));
}
//switches the active player, when both have finished their animation
if (playerOneAnimationReady && playerTwoAnimationReady) {
LOGGER.log(Level.DEBUG, "switched active player");
if (p != activePlayer) {
activePlayer = p;
} else {
activePlayer = getOpponent(p);
}
}
}
/**
* this method handles the shot logic, if the shot misses
*
* @param p the current player
* @param position the position shot at
* @param selectedShip the ship shot at
*/
private void shootShip(Player p, IntPoint position, Battleship selectedShip) {
selectedShip.hit(position);
if (isGameOver(getOpponent(p))) {
gameOver(p, position, selectedShip);
} else if (selectedShip.isDestroyed()) {
// ship has been destroyed, but game is not yet over
send(activePlayer, EffectMessage.shipDestroyed(true, pos, selectedShip));
send(otherPlayer, EffectMessage.shipDestroyed(false, pos, selectedShip));
shipDestroys(p, position, selectedShip);
} else {
// ship has been hit, but it hasn't been destroyed
send(activePlayer, EffectMessage.hit(true, pos));
send(otherPlayer, EffectMessage.hit(false, pos));
}
shipHit(p, position);
}
}
/**
* checks, if the given player ends the game, bc he has no ships
*
* @param p the player
* @return true, if the given player has no shi left
*/
private boolean isGameOver(Player p) {
return p.getMap().getRemainingShips().isEmpty();
}
/**
* handles the shot logic,if the game is over
*
* @param p the player
* @param position the position shot at
* @param selectedShip the current ship, shot at
*/
private void gameOver(Player p, IntPoint position, Battleship selectedShip) {
if (p != activePlayer) {
send(p, EffectMessage.lost(position, selectedShip, activePlayer.getMap().getRemainingShips()));
} else {
send(activePlayer, EffectMessage.won(position, selectedShip));
}
if (playerOneAnimationReady && playerTwoAnimationReady) {
setState(ServerState.GAME_OVER);
}
}
/**
* handles the logic,if the ship is destroyed and it's not gameOver
*
* @param p the player
* @param position the position shot at
* @param selectedShip the ship shot at
*/
private void shipDestroys(Player p, IntPoint position, Battleship selectedShip) {
if (p != activePlayer) {
send(p, EffectMessage.shipDestroyed(false, position, selectedShip));
} else {
send(activePlayer, EffectMessage.shipDestroyed(true, position, selectedShip));
}
}
/**
* handles the logic,if the ship is hit and it's not gameOver
*
* @param p the player
* @param position the position shot at
*/
private void shipHit(Player p, IntPoint position) {
if (p != activePlayer) {
send(p, EffectMessage.hit(false, position));
} else {
send(activePlayer, EffectMessage.hit(true, position));
}
}
}

View File

@@ -29,5 +29,10 @@ enum ServerState {
/**
* The game has ended because all the ships of one player have been destroyed.
*/
GAME_OVER
GAME_OVER,
/**
* The game has paused, cause the clients need time to play their respective animations
*/
ANIMATION_WAIT_STATE
}

View File

@@ -7,6 +7,7 @@
package pp.battleship.game.singlemode;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.ClientMessage;
import pp.battleship.message.client.MapMessage;
@@ -63,6 +64,17 @@ public void received(MapMessage msg, int from) {
copiedMessage = new MapMessage(msg.getShips().stream().map(Copycat::copy).toList());
}
/**
* Receives an AnimationEndMessage, copies it
*
* @param msg the message
* @param from the connectionID
*/
@Override
public void received(AnimationEndMessage msg, int from) {
copiedMessage = new AnimationEndMessage(msg.getPosition());
}
/**
* Creates a copy of the provided {@link Battleship}.
*

View File

@@ -9,19 +9,19 @@
import pp.battleship.game.client.BattleshipClient;
import pp.battleship.game.client.ClientGameLogic;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.ServerInterpreter;
import pp.battleship.message.server.ServerMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.*;
import java.io.IOException;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
/**
* A proxy class that interprets messages from the server and forwards them to the BattleshipClient.
* Implements the ServerInterpreter interface to handle specific server messages.
*/
class InterpreterProxy implements ServerInterpreter {
private static final Logger LOGGER = System.getLogger(InterpreterProxy.class.getName());
private final BattleshipClient playerClient;
/**
@@ -55,8 +55,7 @@ private void loadMap() {
final ClientGameLogic clientGameLogic = playerClient.getGameLogic();
try {
clientGameLogic.loadMap(playerClient.getConfig().getOwnMap());
}
catch (IOException e) {
} catch (IOException e) {
throw new RuntimeException("Failed to load PlayerClient map", e);
}
clientGameLogic.mapFinished();
@@ -82,6 +81,27 @@ public void received(EffectMessage msg) {
forward(msg);
}
/**
* Received an AnimationStartMessage, logs it and forwards it
*
* @param animationStartMessage the StartMessage received
*/
@Override
public void received(AnimationStartMessage animationStartMessage) {
LOGGER.log(Level.INFO, "AnimationStartMessage was received by InterpreterProxy");
forward(animationStartMessage);
}
/**
* Received a BackToBattleStateMessage, and forwards it
*
* @param backToBattleStateMessage the Message received
*/
@Override
public void received(BackToBattleStateMessage backToBattleStateMessage) {
forward(backToBattleStateMessage);
}
/**
* Forwards the specified ServerMessage to the client's game logic by enqueuing the message acceptance.
*

View File

@@ -1,12 +1,10 @@
package pp.battleship.game.singlemode;
import pp.battleship.game.client.BattleshipClient;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.message.client.MapMessage;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.ServerInterpreter;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.*;
import pp.battleship.model.IntPoint;
import pp.battleship.model.dto.ShipMapDTO;
import pp.util.RandomPositionIterator;
@@ -124,4 +122,27 @@ public void received(EffectMessage msg) {
if (msg.isMyTurn())
shoot();
}
/**
* Received an AnimationStartMessage, logs it, and sends an AnimationEndMessage, bc it can't be displayed
*
* @param msg the StartMessage received
*/
@Override
public void received(AnimationStartMessage msg) {
LOGGER.log(Level.INFO, "AnimationStartMessage was received by RobotClient");
connection.sendRobotMessage(new AnimationEndMessage(msg.getPosition()));
}
/**
* Received an Message, if the BackToBattleState is active, checks, if it's his turn and fires, if it is
*
* @param backToBattleStateMessage the Message received
*/
@Override
public void received(BackToBattleStateMessage backToBattleStateMessage) {
if (backToBattleStateMessage.isMyTurn()) {
shoot();
}
}
}

View File

@@ -0,0 +1,50 @@
package pp.battleship.message.client;
import com.jme3.network.serializing.Serializable;
import pp.battleship.model.IntPoint;
/**
* this class represents the AnimationEndMessage, that is sent from the clients to the server, to say, they are finished with the animation
*/
@Serializable
public class AnimationEndMessage extends ClientMessage {
/**
* the position, where was shot at
*/
private IntPoint position;
/**
* this private constructor is used for the serialization
*/
private AnimationEndMessage() { /* nothing */}
/**
* this is the constructor for this class
*
* @param position IntPoint
*/
public AnimationEndMessage(IntPoint position) {
this.position = position;
}
/**
* the getter for the position
*
* @return IntPoint position
*/
public IntPoint getPosition() {
return position;
}
/**
* the accept-method for the ClientInterpreter
*
* @param interpreter the visitor to be used for processing
* @param from the connection ID of the sender
*/
@Override
public void accept(ClientInterpreter interpreter, int from) {
interpreter.received(this, from);
}
}

View File

@@ -26,4 +26,12 @@ public interface ClientInterpreter {
* @param from the connection ID from which the message was received
*/
void received(MapMessage msg, int from);
/**
* Processes a received AnimationEndMessage
*
* @param animationEndMessage the message processed
* @param from the connectionID
*/
void received(AnimationEndMessage animationEndMessage, int from);
}

View File

@@ -0,0 +1,67 @@
package pp.battleship.message.server;
import com.jme3.network.serializing.Serializable;
import pp.battleship.model.IntPoint;
/**
* This class represents the AnimationStartMessage, which tells the clients, that they should display their animations
*/
@Serializable
public class AnimationStartMessage extends ServerMessage {
private IntPoint position;
private boolean myTurn;
/**
* this empty constructor is needed for the serialization
*/
private AnimationStartMessage() { /* nothing */}
/**
* this is the constructor for the AnimationMessage
*
* @param position the position, where was shot
* @param isTurn of the receiving client
*/
public AnimationStartMessage(IntPoint position, boolean isTurn) {
this.position = position;
this.myTurn = isTurn;
}
/**
* getter for the position
*
* @return IntPoint position
*/
public IntPoint getPosition() {
return position;
}
/**
* getter for myTurn
*
* @return boolean myTurn
*/
public boolean isMyTurn() {
return myTurn;
}
/**
* this method accept ServerInterpreter
*
* @param interpreter the visitor to be used for processing
*/
@Override
public void accept(ServerInterpreter interpreter) {
interpreter.received(this);
}
/**
* getter for the Info text for each state
*
* @return String InfoText
*/
@Override
public String getInfoTextKey() {
return (position + " to be animated");
}
}

View File

@@ -0,0 +1,59 @@
package pp.battleship.message.server;
import com.jme3.network.serializing.Serializable;
/**
* this Message tells the clients, that they should return to the BattleState
*/
@Serializable
public class BackToBattleStateMessage extends ServerMessage {
/**
* the boolean describes, whether it is his turn
*/
private boolean isMyTurn;
/**
* the private constructor is used for the serialization
*/
private BackToBattleStateMessage() { /* nothing */}
/**
* the constructor for the message
*
* @param isMyTurn indicates, whether the client, that receives this message, has his turn
*/
public BackToBattleStateMessage(boolean isMyTurn) {
this.isMyTurn = isMyTurn;
}
/**
* getter for the MyTurn
*
* @return boolean myTurn
*/
public boolean isMyTurn() {
return isMyTurn;
}
/**
* accept-method for ServerInterpreter
*
* @param interpreter the visitor to be used for processing
*/
@Override
public void accept(ServerInterpreter interpreter) {
interpreter.received(this);
}
/**
* returns info text for this Message
*
* @return String
*/
@Override
public String getInfoTextKey() {
return "";
}
}

View File

@@ -33,4 +33,18 @@ public interface ServerInterpreter {
* @param msg the EffectMessage received
*/
void received(EffectMessage msg);
/**
* Handles the AnimationStartMessage
*
* @param animationStartMessage the StartMessage received
*/
void received(AnimationStartMessage animationStartMessage);
/**
* Handles the Message, that sets the clients back in the BattleState
*
* @param backToBattleStateMessage the Message received
*/
void received(BackToBattleStateMessage backToBattleStateMessage);
}

View File

@@ -1,65 +1,36 @@
package pp.battleship.model;
import com.jme3.math.Vector3f;
import pp.battleship.game.client.ClientGameLogic;
import pp.battleship.message.server.EffectMessage;
import pp.util.FloatMath;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
/**
* this class is the model for the shell, that hits the Battleships
*/
public class Shell implements Item {
private final Vector3f startPosition; // Startposition des Geschosses
private final Vector3f targetPosition; // Zielposition des Geschosses0
private final Vector3f currentPosition; // Aktuelle Position des Geschosses
private final float speed; // Geschwindigkeit des Geschosses
private final EffectMessage msg;
private final ClientGameLogic logic;
private float progress;
private static final Logger LOGGER = System.getLogger(Shell.class.getName());
/**
* Initializes a Shell with start position, target position, speed, message, and game logic.
* @param startPosition initial position of the shell
* @param targetPosition target position of the shell
* @param speed movement speed of the shell
* @param msg effect message related to the shell
* @param logic game logic instance
* the Target, the Shell will hit
*/
public Shell(Vector3f startPosition, Vector3f targetPosition, float speed, EffectMessage msg, ClientGameLogic logic) {
this.startPosition = startPosition;
this.targetPosition = targetPosition;
this.currentPosition = new Vector3f(startPosition); // Initiale Position ist die Startposition
this.speed = speed;
this.msg = msg;
this.logic = logic;
}
/**
* Updates the shell's position based on elapsed time, using eased interpolation between start and target positions.
* @param deltaTime time elapsed since last update
*/
public void updatePosition(float deltaTime) {
progress += deltaTime * speed;
progress = FloatMath.clamp(progress, 0.0f, 1.0f);
float t = FloatMath.easeInOutElastic(progress);
// Interpoliere die Position zwischen Start- und Zielposition basierend auf dem Fortschritt
currentPosition.y = FloatMath.extrapolateLinear(t, startPosition.y, targetPosition.y);
currentPosition.x = FloatMath.extrapolateLinear(t, startPosition.x, targetPosition.x);
currentPosition.z = FloatMath.extrapolateLinear(t, startPosition.z, targetPosition.z);
}
/**
* getter for Current Position
* @return current position
*/
public Vector3f getCurrentPosition() {
return currentPosition;
private IntPoint target;
/**
* the constructor for this class
*
* @param target the target, the shell is fired at
*/
public Shell(IntPoint target) {
this.target = target;
LOGGER.log(Level.INFO, "Shell has been initialized");
}
/**
* the accept-method for a generic visitor
*
* @param visitor the visitor performing operations on the item
* @param <T> generic type
* @return shell
* @param <T> cause it is generic
* @return T
*/
@Override
public <T> T accept(Visitor<T> visitor) {
@@ -67,8 +38,9 @@ public <T> T accept(Visitor<T> visitor) {
}
/**
* Visitor pattern
* @param visitor the visitor to accept
* the accept-method for the void visitor
*
* @param visitor the visitor performing operations on the item
*/
@Override
public void accept(VoidVisitor visitor) {
@@ -76,28 +48,20 @@ public void accept(VoidVisitor visitor) {
}
/**
* getter for the isFinished boolean
* @return true if progress lesser than 1, false otherwise
* getter for the x coordinate
*
* @return int x coordinate
*/
public boolean isFinished() {
return progress >= 1;
public int getX() {
return target.getX();
}
/**
* getter for EffectMessage
* @return EffectMessage
* getter for the y coordinate
*
* @return int y coordinate
*/
public EffectMessage getMsg() {
return msg;
}
/**
* getter for Client logic
* @return Client logic
*/
public ClientGameLogic getLogic() {
return logic;
public int getY() {
return target.getY();
}
}

Some files were not shown because too many files have changed in this diff Show More