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
191 changed files with 531210 additions and 480992 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>

File diff suppressed because it is too large Load Diff

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

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

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

@@ -4,235 +4,120 @@
import com.jme3.audio.AudioData.DataType;
import com.jme3.audio.AudioNode;
import com.jme3.audio.AudioSource.Status;
import pp.battleship.notification.Music;
import pp.battleship.notification.MusicEvent;
import pp.battleship.notification.GameEventListener;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
import java.util.prefs.Preferences;
/**
* Class to play Background music in game
* this class is used to control the background-music in the game
*/
public class BackgroundMusic implements GameEventListener {
private static final String VOLUME_PREF = "volume";
private static final String MUSIC_ENABLED_PREF = "musicEnabled";
private final Preferences pref = Preferences.userNodeForPackage(BackgroundMusic.class);
static final Logger LOGGER = System.getLogger(BackgroundMusic.class.getName());
private static final String MENU_MUSIC = "Sound/Music/menu/cinematictrailerelite.ogg";
private static final String GAME_MUSIC = "Sound/Music/game/Aluminum.ogg";
private static final String VICTORY_MUSIC = "Sound/Music/victory/victorymarchofvalor.ogg";
private static final String LOSE_MUSIC = "Sound/Music/lose/TouchofDream.ogg";
private final AudioNode menuMusic;
private final AudioNode gameMusic;
private final AudioNode victoryMusic;
private final AudioNode loseMusic;
private String lastPlayedMusic;
private boolean musicEnabled;
private float volume;
private Application app;
public class BackgroundMusic {
/**
* Constructor for BackgroundMusic class
*
* @param app The main Application
* this attribute ist the keyword to save the last volume, that was set
*/
public BackgroundMusic(Application app) {
this.volume = pref.getFloat(VOLUME_PREF, 1.0f);
this.musicEnabled = pref.getBoolean(MUSIC_ENABLED_PREF, true);
this.app = app;
private static final String VOLUME_PREV = "BackgroundVolume";
menuMusic = createMusicNode(MENU_MUSIC);
gameMusic = createMusicNode(GAME_MUSIC);
victoryMusic = createMusicNode(VICTORY_MUSIC);
loseMusic = createMusicNode(LOSE_MUSIC);
stop(gameMusic);
stop(victoryMusic);
stop(loseMusic);
lastPlayedMusic = menuMusic.getName();
/**
* this attribute ist the keyword to save the state, whether the music was on or off in the last session
*/
private static final String BACKGROUND_MUSIC_ENABLED_PREV = "BackgroundMusicEnabled";
if (musicEnabled) {
play(menuMusic);
/**
* 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(backgroundVolume);
if (backgroundMusicEnabled) { //starts playing, when enabled
play();
}
}
/**
* Creates an audio node for the music
*
* @param musicFilePath the file path to the music
* @return the created audio node
* this method plays the background sound, if it is enabled
*/
private AudioNode createMusicNode(String musicFilePath) {
AudioNode audioNode = new AudioNode(app.getAssetManager(), musicFilePath, DataType.Stream);
audioNode.setVolume(volume);
audioNode.setPositional(false);
audioNode.setLooping(true);
audioNode.setName(musicFilePath);
return audioNode;
}
/**
* Starts the music
*
* @param audioNode the audio node to be played
*/
public void play(AudioNode audioNode) {
if (musicEnabled && (audioNode.getStatus() == Status.Stopped || audioNode.getStatus() == Status.Paused)) {
audioNode.play();
lastPlayedMusic = audioNode.getName();
public void play() {
if (backgroundMusicEnabled && (backgroundMusic.getStatus() == Status.Stopped || backgroundMusic.getStatus() == Status.Paused)) { //checks, if it is enabled and stopped or paused
backgroundMusic.play();
}
}
/**
* Pauses the music
*
* @param audioNode the audio node to be paused
* this method stops the background-music
*/
public void pause(AudioNode audioNode) {
if (audioNode.getStatus() == Status.Playing) {
audioNode.pause();
}
public void stop() { //stops the music, when it is playing
if (backgroundMusic.getStatus() == Status.Playing) backgroundMusic.stop();
}
/**
* Stops the music
*
* @param audioNode the audio node to be stopped
*/
public void stop(AudioNode audioNode) {
if (audioNode.getStatus() == Status.Playing) {
audioNode.stop();
}
}
/**
* Controls which music should be played
* function to toggle the Background-music ,so if it was disabled it is now enabled and other way around
*/
public void toggleMusic() {
this.musicEnabled = !this.musicEnabled;
if (musicEnabled) {
switch (lastPlayedMusic) {
case MENU_MUSIC:
play(menuMusic);
break;
case GAME_MUSIC:
play(gameMusic);
break;
case VICTORY_MUSIC:
play(victoryMusic);
break;
case LOSE_MUSIC:
play(loseMusic);
break;
}
this.backgroundMusicEnabled = !this.backgroundMusicEnabled;
if (backgroundMusicEnabled) {
play();
}
else {
pause(menuMusic);
pause(gameMusic);
pause(victoryMusic);
pause(loseMusic);
stop();
}
pref.putBoolean(MUSIC_ENABLED_PREF, musicEnabled);
prefs.putBoolean(BACKGROUND_MUSIC_ENABLED_PREV, backgroundMusicEnabled); //puts in new enabled to the pref
}
/**
* Changes the music to the specified music if it isn't already playing
* this method sets the
*
* @param music the music to play
* @param volume is the volume the music is set to
*/
public void changeMusic(Music music) {
if (music == Music.MENU_THEME && !lastPlayedMusic.equals(MENU_MUSIC)) {
LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString());
stop(gameMusic);
stop(victoryMusic);
stop(loseMusic);
play(menuMusic);
lastPlayedMusic = menuMusic.getName();
}
else if (music == Music.GAME_THEME && !lastPlayedMusic.equals(GAME_MUSIC)) {
LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString());
stop(menuMusic);
stop(loseMusic);
stop(victoryMusic);
play(gameMusic);
lastPlayedMusic = gameMusic.getName();
}
else if (music == Music.VICTORY_THEME && !lastPlayedMusic.equals(VICTORY_MUSIC)) {
LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString());
stop(menuMusic);
stop(gameMusic);
stop(loseMusic);
play(victoryMusic);
lastPlayedMusic = victoryMusic.getName();
}
else if (music == Music.LOSE_THEME && !lastPlayedMusic.equals(LOSE_MUSIC)) {
LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString());
stop(menuMusic);
stop(gameMusic);
stop(victoryMusic);
play(loseMusic);
lastPlayedMusic = loseMusic.getName();
}
public void setBackgroundVolume(float volume) {
this.backgroundVolume = volume;
backgroundMusic.setVolume(backgroundVolume);
prefs.putFloat(VOLUME_PREV, volume);
}
/**
* Receives the different MusicEvents
* this method returns the BackgroundVolume
*
* @param music the received Event
* @return backgroundVolume
*/
@Override
public void receivedEvent(MusicEvent music) {
LOGGER.log(Level.DEBUG, "Received Music change Event {0}", music.toString());
switch (music.music()) {
case MENU_THEME:
changeMusic(Music.MENU_THEME);
break;
case GAME_THEME:
changeMusic(Music.GAME_THEME);
break;
case VICTORY_THEME:
changeMusic(Music.VICTORY_THEME);
break;
case LOSE_THEME:
changeMusic(Music.LOSE_THEME);
break;
}
public float getBackgroundVolume() {
return backgroundVolume;
}
/**
* Set the volume for the music
* return, if the background-music is enabled
*
* @param volume float to transfer the new volume
* @return true if the music is enabled
*/
public void setVolume(float volume) {
this.volume = volume;
menuMusic.setVolume(volume);
gameMusic.setVolume(volume);
victoryMusic.setVolume(volume);
loseMusic.setVolume(volume);
pref.putFloat(VOLUME_PREF, volume);
}
/**
* Returns the volume
*
* @return the current volume as a float
*/
public float getVolume() {
return volume;
}
/**
* Returns if music should be played or not
*
* @return boolean value in music should be played
*/
public boolean isMusicEnabled() {
return musicEnabled;
public boolean isBackgroundMusicEnabled() {
return backgroundMusicEnabled;
}
}

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client;
import com.jme3.app.DebugKeysAppState;
@@ -116,7 +123,7 @@ public class BattleshipApp extends SimpleApplication implements BattleshipClient
private final ActionListener escapeListener = (name, isPressed, tpf) -> escape(isPressed);
/**
* Object handling the background music
* this is the object, responsible for the background-music and to control it
*/
private BackgroundMusic backgroundMusic;
@@ -223,8 +230,7 @@ public void simpleInitApp() {
setupStates();
setupGui();
serverConnection.connect();
backgroundMusic = new BackgroundMusic(this);
logic.addListener(backgroundMusic);
backgroundMusic = new BackgroundMusic(this, "Sound/Background/backgroundMusic.ogg"); //initialise backgroundMusic and sets the backgroundMusic-path
}
/**
@@ -315,10 +321,6 @@ public Draw getDraw() {
return draw;
}
public BackgroundMusic getBackgroundMusic() {
return backgroundMusic;
}
/**
* Handles a request to close the application.
* If the request is initiated by pressing ESC, this parameter is true.
@@ -430,4 +432,12 @@ void errorDialog(String errorMessage) {
.build()
.open();
}
/**
* this method returns Background-Music
* @return background-music
*/
public BackgroundMusic getBackgroundMusic(){
return backgroundMusic;
}
}

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client;
import com.jme3.math.ColorRGBA;

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client;
import com.jme3.app.Application;

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client;
import com.jme3.app.Application;
@@ -8,7 +15,6 @@
import com.jme3.audio.AudioData;
import com.jme3.audio.AudioNode;
import pp.battleship.notification.GameEventListener;
import pp.battleship.notification.Sound;
import pp.battleship.notification.SoundEvent;
import java.lang.System.Logger;
@@ -21,14 +27,13 @@
* An application state that plays sounds.
*/
public class GameSound extends AbstractAppState implements GameEventListener {
static final Logger LOGGER = System.getLogger(GameSound.class.getName());
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.
@@ -73,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/missilefiring.wav"); //NON-NLS
rocketSound = loadSound(app, "Sound/Effects/rocket-loop-99748.wav");
}
/**
@@ -89,21 +94,12 @@ private AudioNode loadSound(Application app, String name) {
sound.setLooping(false);
sound.setPositional(false);
return sound;
}
catch (AssetLoadException | AssetNotFoundException ex) {
} catch (AssetLoadException | AssetNotFoundException ex) {
LOGGER.log(Level.ERROR, ex.getMessage(), ex);
}
return null;
}
/**
* Plays the splash sound effect.
*/
public void missileLaunch() {
if (isEnabled() && missileLaunch != null)
missileLaunch.playInstance();
}
/**
* Plays the splash sound effect.
*/
@@ -129,9 +125,9 @@ public void shipDestroyed() {
}
/**
* Plays sound according to the received SoundEvent
* when triggered, though a sound-event,it decides, which sound should be played
*
* @param event the received SoundEvent
* @param event the received event
*/
@Override
public void receivedEvent(SoundEvent event) {
@@ -139,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

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client;
import com.simsilica.lemur.Button;
@@ -42,17 +49,18 @@ public Menu(BattleshipApp app) {
addChild(new Label(lookup("battleship.name"), new ElementId("header"))); //NON-NLS
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());
addChild(musicToggle);
addChild(new Label(lookup("menu.music.volume"), new ElementId("slider_label")));
Slider volumeSlider = new Slider();
volumeSlider.setModel(new DefaultRangedValueModel(0.00, 1.00, app.getBackgroundMusic().getVolume()));
volumeSlider.setDelta(0.05);
//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);
//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)
@@ -68,34 +76,17 @@ public Menu(BattleshipApp app) {
}
/**
* Updates the volume when the slider is moved
* updates the background-volume
*
* @param tpf time per frame
* @param tmp
*/
@Override
public void update(float tpf) {
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 volume for the background music
*
* @param volume is the double value of the volume
*/
private void adjustVolume(double volume) {
app.getBackgroundMusic().setVolume((float) volume);
}
/**
* Toggles the background music on and off
*/
private void toggleMusic() {
app.getBackgroundMusic().toggleMusic();
}
/**
* Updates the state of the load and save buttons based on the game logic.
*/

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client;
import com.simsilica.lemur.Checkbox;
@@ -5,10 +12,11 @@
import com.simsilica.lemur.Label;
import com.simsilica.lemur.TextField;
import com.simsilica.lemur.component.SpringGridLayout;
import pp.battleship.client.server.BattleshipLocalServer;
import pp.battleship.client.server.BattleshipLocalServer;
import pp.dialog.Dialog;
import pp.dialog.DialogBuilder;
import pp.dialog.SimpleDialog;
import server.BattleshipServer;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
@@ -32,7 +40,7 @@ class NetworkDialog extends SimpleDialog {
private int portNumber;
private Future<Object> connectionFuture;
private Dialog progressDialog;
private boolean hostServer = false;
private boolean localServer = false;
/**
* Constructs a new NetworkDialog.
@@ -46,17 +54,19 @@ class NetworkDialog extends SimpleDialog {
host.setPreferredWidth(400f);
port.setSingleLine(true);
Checkbox hostServer = new Checkbox(lookup("start.own.server"));
hostServer.setChecked(false);
hostServer.addClickCommands(s -> toggleOwnServer());
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);
input.addChild(hostServer);
/*
* 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"))
@@ -66,13 +76,14 @@ class NetworkDialog extends SimpleDialog {
.setOkClose(false)
.setNoClose(false)
.build(this);
addChild(localServerCb); // adds the checkbox to the network dialog at the bottom
}
/**
* Handles the action for establishing the connection to a server.
* Handles the action for the connect button in the connection dialog.
* Tries to parse the port number and initiate connection to the server.
*/
private void connectToServer() {
private void connectServer() {
LOGGER.log(Level.INFO, "connect to host={0}, port={1}", host, port); //NON-NLS
try {
hostname = host.getText().trim().isEmpty() ? LOCALHOST : host.getText();
@@ -85,6 +96,40 @@ private void connectToServer() {
}
}
/**
* connects to the server, creates one, if no server is up
*/
public void connect() {
if (localServer) {
startLocalServer(); //starts a local server
try {
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
}
}
/**
*starts a local server, in another thread
*/
private void startLocalServer() {
new Thread(() -> { //creates new Thread
try {
BattleshipLocalServer battleshipLocalServer = new BattleshipLocalServer(Integer.parseInt(port.getText())); // creates local server, with the given port numbers
battleshipLocalServer.run(); // runs the local server
}
catch (Exception e) {
LOGGER.log(Level.ERROR, e.getMessage(), e);
}
}).start(); // starts the thread
}
/**
* Creates a dialog indicating that the connection is in progress.
*/
@@ -151,46 +196,4 @@ private void failure(Throwable e) {
network.getApp().errorDialog(lookup("server.connection.failed"));
network.getApp().setInfoText(e.getLocalizedMessage());
}
/**
* Handles the action for the connect-button.
* If hostServer-Checkbox is active, starts a new Server on the clients machine, else tries to connect to existing server
*/
private void connect() {
if (hostServer) {
startServer();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
LOGGER.log(Level.WARNING, e.getMessage(), e);
}
connectToServer();
}
else {
connectToServer();
}
}
/**
* Starts a server on the clients machine
*/
private void startServer() {
new Thread(() -> {
try {
BattleshipServer battleshipServer = new BattleshipServer(Integer.parseInt(port.getText()));
battleshipServer.run();
}
catch (Exception e) {
LOGGER.log(Level.ERROR, e);
}
}).start();
}
/**
* Handles the action for the hostServer-Checkbox
*/
private void toggleOwnServer() {
hostServer = !hostServer;
}
}

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client;
import com.jme3.network.Client;

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;

View File

@@ -1,181 +0,0 @@
package pp.battleship.client.gui;
import com.jme3.app.Application;
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.model.Shot;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
public class HitEffectHandler {
private final AssetManager assetManager;
private static final Logger LOGGER = System.getLogger(HitEffectHandler.class.getName());
/**
* Constructor for the HitEffectHandler class
*
* @param app the main application
*/
public HitEffectHandler(Application app) {
assetManager = app.getAssetManager();
}
/**
* Creates explosion, debris and fire effects when ship gets hit
*
* @param battleshipNode the node of the ship that gets hit and the effect should be attached to
* @param shot The shot taken on a field
*/
public void hitEffect(Node battleshipNode, Shot shot) {
//Explosion
ParticleEmitter explosion = new ParticleEmitter("Explosion", Type.Triangle, 30);
explosion.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"));
explosion.setImagesX(2);
explosion.setImagesY(2);
explosion.setStartColor(new ColorRGBA(0.96f, 0.82f, 0.6f, 1f));
explosion.setEndColor(new ColorRGBA(0.88f, 0.32f, 0.025f, 1f));
explosion.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 1, 0));
explosion.setStartSize(0.45f);
explosion.setEndSize(0.1f);
explosion.setGravity(0, -0.5f, 0);
explosion.setLowLife(1f);
explosion.setHighLife(3.5f);
explosion.setParticlesPerSec(0);
explosion.setLocalTranslation(shot.getY() + 0.5f, 0, shot.getX() + 0.5f);
explosion.emitAllParticles();
//Debris
ParticleEmitter debris = new ParticleEmitter("Debris", Type.Triangle, 6);
Material debrisMaterial = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
debrisMaterial.setTexture("Texture", assetManager.loadTexture("Textures/Debris/debris.png"));
debris.setMaterial(debrisMaterial);
debris.setImagesX(2);
debris.setImagesY(2);
debris.setStartColor(ColorRGBA.White);
debris.setEndColor(ColorRGBA.White);
debris.getParticleInfluencer().setInitialVelocity(new Vector3f(0.25f, 2f, 0.25f));
debris.setStartSize(0.25f);
debris.setEndSize(0.1f);
debris.setGravity(0, 1.5f, 0);
debris.getParticleInfluencer().setVelocityVariation(0.3f);
debris.setLowLife(1f);
debris.setHighLife(3.5f);
debris.setParticlesPerSec(0);
debris.setLocalTranslation(shot.getY() + 0.5f, 0, shot.getX() + 0.5f);
debris.emitAllParticles();
//Fire
ParticleEmitter fire = new ParticleEmitter("Fire", Type.Triangle, 30);
Material fireMaterial = new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md");
fireMaterial.setTexture("Texture", assetManager.loadTexture("Textures/Fire/fire.png"));
fire.setMaterial(fireMaterial);
fire.setImagesX(2);
fire.setImagesY(2);
fire.setStartColor(ColorRGBA.Orange);
fire.setEndColor(ColorRGBA.Red);
fire.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 1.5f, 0));
fire.setStartSize(0.2f);
fire.setEndSize(0.05f);
fire.setLowLife(1f);
fire.setHighLife(2f);
fire.getParticleInfluencer().setVelocityVariation(0.2f);
fire.setLocalTranslation(shot.getY() + 0.5f, 0f, shot.getX() + 0.5f);
fire.getLocalTranslation().subtractLocal(battleshipNode.getLocalTranslation());
battleshipNode.attachChild(fire);
fire.emitAllParticles();
// LOGGER.log(Level.DEBUG, "Created HitEffect at {0}", explosion.getLocalTranslation().toString());
// LOGGER.log(Level.DEBUG, "Created HitEffect at {0}", debris.getLocalTranslation().toString());
// LOGGER.log(Level.INFO, "Created HitEffect at {0}", fire.getLocalTranslation().toString());
battleshipNode.attachChild(explosion);
explosion.addControl(new EffectControl(explosion, battleshipNode));
fire.addControl(new EffectControl(fire, battleshipNode));
battleshipNode.attachChild(debris);
debris.addControl(new EffectControl(debris, battleshipNode));
}
/**
* Creates a splash effect if the shot hits the water
*
* @param shot The shot taken on a field
*/
public ParticleEmitter missEffect(Shot shot) {
ParticleEmitter missEffect = new ParticleEmitter("HitEffect", Type.Triangle, 45);
missEffect.setMaterial(new Material(assetManager, "Common/MatDefs/Misc/Particle.j3md"));
missEffect.setImagesX(2);
missEffect.setImagesY(2);
missEffect.setStartColor(new ColorRGBA(0.067f, 0.06f, 0.37f, 0.87f));
missEffect.setEndColor(new ColorRGBA(0.32f, 0.55f, 0.87f, 0.79f));
missEffect.getParticleInfluencer().setInitialVelocity(new Vector3f(0, 1, 0));
missEffect.setStartSize(0.1f);
missEffect.setEndSize(0.08f);
missEffect.setGravity(0, 0.36f, 0);
missEffect.setLowLife(0.7f);
missEffect.setHighLife(1.8f);
missEffect.setParticlesPerSec(0);
missEffect.setLocalTranslation(shot.getY() + 0.5f, 0, shot.getX() + 0.5f);
LOGGER.log(Level.DEBUG, "Created MissEffect at {0}", missEffect.getLocalTranslation().toString());
missEffect.emitAllParticles();
missEffect.addControl(new EffectControl(missEffect));
return missEffect;
}
/**
* Inner class to control effects
*/
private static class EffectControl extends AbstractControl {
private final ParticleEmitter emitter;
private final Node parentNode;
/**
* Constructor used to attach effect to a node
*
* @param emitter the particle emitter to be controlled
* @param parentNode the node to be attached
*/
public EffectControl(ParticleEmitter emitter, Node parentNode) {
this.emitter = emitter;
this.parentNode = parentNode;
}
/**
* Constructor used if the effect shouldn't be attached to a node
*
* @param emitter the particle emitter to be controlled
*/
public EffectControl(ParticleEmitter emitter) {
this.emitter = emitter;
this.parentNode = null;
}
/**
* Checks if the Effect is not rendered anymore so it can be removed
*
* @param tpf time per frame (in seconds)
*/
@Override
protected void controlUpdate(float tpf) {
if (emitter.getParticlesPerSec() == 0 && emitter.getNumVisibleParticles() == 0) {
if (parentNode != null)
parentNode.detachChild(emitter);
}
}
/**
* @param rm the RenderManager rendering the controlled Spatial (not null)
* @param vp the ViewPort being rendered (not null)
*/
@Override
protected void controlRender(com.jme3.renderer.RenderManager rm, com.jme3.renderer.ViewPort vp) {}
}
}

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;
@@ -7,13 +12,11 @@
import com.jme3.scene.Node;
import com.jme3.scene.Spatial;
import pp.battleship.model.Battleship;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
import pp.battleship.model.Shot;
import pp.util.Position;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
/**
* Synchronizes the visual representation of the ship map with the game model.
@@ -21,14 +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 MISSILE_DEPTH = 6f;
private static final float MISSILE_SIZE = 0.8f;
private static final float MISSILE_CENTERED_IN_MAP_GRID = 0.0625f;
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;
@@ -40,8 +43,6 @@ class MapViewSynchronizer extends ShipMapSynchronizer {
// The MapView associated with this synchronizer
private final MapView view;
static final Logger LOGGER = System.getLogger(MapViewSynchronizer.class.getName());
/**
* Constructs a new MapViewSynchronizer for the given MapView.
* Initializes the synchronizer and adds existing elements from the model to the view.
@@ -63,14 +64,16 @@ public MapViewSynchronizer(MapView view) {
*/
@Override
public Spatial visit(Shot shot) {
LOGGER.log(Level.DEBUG, "visiting" + shot);
// Convert the shot's model coordinates to view coordinates
final Position p1 = view.modelToView(shot.getX(), shot.getY());
final Position p2 = view.modelToView(shot.getX() + 1, shot.getY() + 1);
final ColorRGBA color = shot.isHit() ? HIT_COLOR : MISS_COLOR;
// Create and return a rectangle representing the shot
return view.getApp().getDraw().makeRectangle(p1.getX(), p1.getY(), SHOT_DEPTH, p2.getX() - p1.getX(), p2.getY() - p1.getY(), color);
return view.getApp().getDraw().makeRectangle(p1.getX(), p1.getY(),
SHOT_DEPTH,
p2.getX() - p1.getX(), p2.getY() - p1.getY(),
color);
}
/**
@@ -113,31 +116,34 @@ public Spatial visit(Battleship ship) {
}
/**
* Creates a visual representation on the map
* this method will create a representation of a shell in the map
*
* @param shell the Shell element to visit
* @return the node the visual representation gets attached to.
* @return the node the representation is attached to
*/
@Override
public Spatial visit(Shell shell) {
LOGGER.log(Logger.Level.DEBUG, "Visiting {0}", shell);
final Node missileNode = new Node("missile");
final Position p1 = view.modelToView(shell.getX(), shell.getY());
final Position p2 = view.modelToView(shell.getX() + MISSILE_SIZE, shell.getY() + MISSILE_SIZE);
final float x1 = p1.getX() + INDENT;
final float y1 = p1.getY() + INDENT;
final float x2 = p2.getX() - INDENT;
final float y2 = p2.getY() - INDENT;
final Position startPosition = view.modelToView(MISSILE_CENTERED_IN_MAP_GRID, MISSILE_CENTERED_IN_MAP_GRID);
missileNode.attachChild(view.getApp().getDraw().makeRectangle(startPosition.getX(), startPosition.getY(), MISSILE_DEPTH, p2.getX() - p1.getX(), p2.getY() - p1.getY(), ColorRGBA.DarkGray));
missileNode.setLocalTranslation(startPosition.getX(), startPosition.getY(), MISSILE_DEPTH);
missileNode.addControl(new ShellMapControl(p1, view.getApp(), new IntPoint(shell.getX(), shell.getY())));
return missileNode;
final Node shellNode = new Node("shell");
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.
*
@@ -149,7 +155,6 @@ public Spatial visit(Shell shell) {
* @return a Geometry representing the line
*/
private Geometry shipLine(float x1, float y1, float x2, float y2, ColorRGBA color) {
LOGGER.log(Logger.Level.DEBUG, "created Ship line");
return view.getApp().getDraw().makeFatLine(x1, y1, x2, y2, SHIP_DEPTH, color, SHIP_LINE_WIDTH);
}
}

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;

View File

@@ -1,25 +1,33 @@
////////////////////////////////////////
// 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.effect.ParticleEmitter;
import com.jme3.effect.ParticleMesh.Type;
import com.jme3.material.Material;
import com.jme3.material.RenderState;
import com.jme3.material.RenderState.BlendMode;
import com.jme3.math.ColorRGBA;
import com.jme3.renderer.queue.RenderQueue;
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.Battleship;
import pp.battleship.model.Shell;
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;
import static pp.util.FloatMath.PI;
@@ -31,22 +39,18 @@
* 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";
private static final String UBOAT_MODEL = "Models/UBOAT/14084_WWII_Ship_German_Type_II_U-boat_v2_L1.obj";
private static final String PATROL_BOAT_MODEL = "Models/PATROL_BOAT/12219_boat_v2_L2.obj";
private static final String MODERN_BATTLESHIP_MODEL = "Models/BATTLESHIP/10619_Battleship.obj";
private static final String MODERN_BATTLESHIP_TEXTURES = "Models/BATTLESHIP/BattleshipC.jpg";
private static final String MISSILE_MODEL = "Models/Missile/AIM120D.obj";
private static final String MISSILE_TEXTURE = "Models/Missile/texture.png";
private static final String KING_GEORGE_V_MODEL = "Models/KingGeorgeV/KingGeorgeV.j3o"; //NON-NLS
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 MISSILE = "missile"; //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 HitEffectHandler hitEffectHandler;
private final ShipMap map;
private final BattleshipApp app;
@@ -62,7 +66,6 @@ public SeaSynchronizer(BattleshipApp app, Node root, ShipMap map) {
super(app.getGameLogic().getOwnMap(), root);
this.app = app;
this.map = map;
hitEffectHandler = new HitEffectHandler(app);
addExisting();
}
@@ -76,7 +79,20 @@ public SeaSynchronizer(BattleshipApp app, Node root, ShipMap map) {
*/
@Override
public Spatial visit(Shot shot) {
return shot.isHit() ? handleHit(shot) : hitEffectHandler.missEffect(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;
}
/**
@@ -90,32 +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");
hitEffectHandler.hitEffect(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);
// compute the center of the shot in world coordinates
geometry.setLocalTranslation(shot.getY() + 0.5f, 0f, shot.getX() + 0.5f);
private Vector3f mapToWorldCord(int x, int y) {
return new Vector3f(y + 0.5f, 0, x + 0.5f);
}
return geometry;
/**
* this method creates the particles, when the shot misses
*
* @param shot is the parameter, where was shot
* @return the particle
*/
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;
}
/**
@@ -134,28 +230,42 @@ 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 Shell and creates a graphical representation of it.
* 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
* @param shell the shell to be represented
* @return the node containing the graphical representation of the shell
*/
@Override
public Spatial visit(Shell shell) {
final Node node = new Node(MISSILE);
node.attachChild(createMissile());
final float x = shell.getY();
final float z = shell.getX();
node.setLocalTranslation(x + 0.5f, 10f, z + 0.5f);
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;
}
/**
* 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 either a detailed model or a simple box based on the length of the ship.
@@ -164,11 +274,12 @@ public Spatial visit(Shell shell) {
* @return the spatial representing the battleship
*/
private Spatial createShip(Battleship ship) {
//return ship.getLength() == 4 ? createBattleship(ship) : createBox(ship);
return switch (ship.getLength()) {
case 1 -> createPatrolBoat(ship);
case 2 -> createModernBattleship(ship);
case 3 -> createUboat(ship);
case 4 -> createBattleship(ship);
case (1) -> createSmallShip(ship);
case (2) -> createSubmarine(ship);
case (3) -> createDestroyer(ship);
case (4) -> createBattleship(ship);
default -> createBox(ship);
};
}
@@ -181,8 +292,8 @@ private Spatial createShip(Battleship ship) {
*/
private Spatial createBox(Battleship ship) {
final Box box = new Box(0.5f * (ship.getMaxY() - ship.getMinY()) + 0.3f,
0.3f,
0.5f * (ship.getMaxX() - ship.getMinX()) + 0.3f);
0.3f,
0.5f * (ship.getMaxX() - ship.getMinX()) + 0.3f);
final Geometry geometry = new Geometry(SHIP, box);
geometry.setMaterial(createColoredMaterial(BOX_COLOR));
geometry.setShadowMode(ShadowMode.CastAndReceive);
@@ -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,86 +384,6 @@ private Spatial createBattleship(Battleship ship) {
return model;
}
/**
* Creates a detailed 3D model to represent a modern battleship.
*
* @param ship the battleship to be represented
* @return the spatial representing the battleship
*/
private Spatial createModernBattleship(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(MODERN_BATTLESHIP_MODEL);
Material mat = new Material(app.getAssetManager(), UNSHADED);
mat.setTexture("ColorMap", app.getAssetManager().loadTexture(MODERN_BATTLESHIP_TEXTURES));
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Off);
model.setMaterial(mat);
model.setQueueBucket(RenderQueue.Bucket.Opaque);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()) + HALF_PI, 0f);
model.scale(0.000075f);
model.setShadowMode(ShadowMode.CastAndReceive);
model.move(0, 0.2f, 0);
return model;
}
/**
* Creates a detailed 3D model to represent a missile.
*
* @return the spatial representing the missile
*/
private Spatial createMissile() {
final Spatial model = app.getAssetManager().loadModel(MISSILE_MODEL);
Material mat = new Material(app.getAssetManager(), UNSHADED);
mat.setTexture("ColorMap", app.getAssetManager().loadTexture(MISSILE_TEXTURE));
mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Off);
model.setMaterial(mat);
model.setQueueBucket(RenderQueue.Bucket.Opaque);
model.rotate(-HALF_PI, 0, 0);
model.scale(0.009f);
model.setShadowMode(ShadowMode.CastAndReceive);
model.move(0, 0f, 0);
return model;
}
/**
* Creates a detailed 3D model to represent a Uboat.
*
* @param ship the battleship to be represented
* @return the spatial representing the Uboat
*/
private Spatial createUboat(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(UBOAT_MODEL);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()), 0f);
model.scale(0.45f);
model.setShadowMode(ShadowMode.CastAndReceive);
model.move(0, -0.25f, 0);
return model;
}
/**
* Creates a detailed 3D model to represent a Patrol boat.
*
* @param ship the battleship to be represented
* @return the spatial representing the Patrol boat
*/
private Spatial createPatrolBoat(Battleship ship) {
final Spatial model = app.getAssetManager().loadModel(PATROL_BOAT_MODEL);
model.rotate(-HALF_PI, calculateRotationAngle(ship.getRot()), 0f);
model.scale(0.00045f);
model.setShadowMode(ShadowMode.CastAndReceive);
return model;
}
/**
* Calculates the rotation angle for the specified rotation.
*

View File

@@ -4,7 +4,7 @@
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import pp.battleship.client.BattleshipApp;
import pp.battleship.message.client.EndAnimationMessage;
import pp.battleship.message.client.AnimationEndMessage;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
@@ -12,51 +12,57 @@
import java.lang.System.Logger.Level;
/**
* Class to control the 3D representation of a shell
* this class controls the Shell in the view
*/
public class ShellControl extends AbstractControl {
private final Shell shell;
private final BattleshipApp app;
private static final float TRAVEL_SPEED = 8.5f;
static final Logger LOGGER = System.getLogger(BattleshipApp.class.getName());
private static final Logger LOGGER = System.getLogger(ShellControl.class.getName());
/**
* Constructor for ShellControl class
* 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 Shell to be displayed
* @param app the main application
* @param shell the shell it displays
* @param app the BattleshipApp
*/
public ShellControl(Shell shell, BattleshipApp app) {
LOGGER.log(Level.INFO, "ShellControl has been initialized");
this.shell = shell;
this.app = app;
}
/**
* Method to control movement of the Shell and remove it when target is reached
* this method controls the movement of the shell in dependent on fpt
*
* @param tpf time per frame (in seconds)
*/
@Override
public void controlUpdate(float tpf) {
//LOGGER.log(Level.DEBUG, "missile at x=" + shell.getX() + ", y=" + shell.getY());
spatial.move(0, -TRAVEL_SPEED * tpf, 0);
if (spatial.getLocalTranslation().getY() <= 0.2) {
protected void controlUpdate(float tpf) {
if (spatial == null) return;
if (spatial.getLocalTranslation().getY() <= HEIGHT) {
spatial.getParent().detachChild(spatial);
app.getGameLogic().send(new EndAnimationMessage(new IntPoint(shell.getX(), shell.getY())));
app.getGameLogic().send(new AnimationEndMessage(new IntPoint(shell.getX(), shell.getY())));
} else {
spatial.move(0, -1 * 4f * tpf, 0);
}
}
/**
* 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
* transformation, not its rendering process.
*
* @param rm the RenderManager rendering the controlled Spatial (not null)
* @param vp the ViewPort being rendered (not null)
*/
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {
//not in use
}
}

View File

@@ -5,56 +5,71 @@
import com.jme3.renderer.ViewPort;
import com.jme3.scene.control.AbstractControl;
import pp.battleship.client.BattleshipApp;
import pp.battleship.message.client.EndAnimationMessage;
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;
/**
* Class to control the 2D representation of a shell
* 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;
private final IntPoint pos;
private static final Vector3f VECTOR_3_F = new Vector3f();
/**
* the vector, the shell is going on the 2d screen
*/
private static final Vector3f vector = new Vector3f();
/**
* the battleship app
*/
private final BattleshipApp app;
/**
* Constructor for ShellMapControl
*
* @param position the target position of the shell
* @param app the main application
* @param pos the position the then to render shot goes to
* the shell displayed
*/
public ShellMapControl(Position position, BattleshipApp app, IntPoint pos) {
super();
this.position = position;
this.pos = pos;
this.app = app;
VECTOR_3_F.set(new Vector3f(position.getX(), position.getY(), 0));
}
private final Shell shell;
/**
* Method to control movement of the Shell on the map and remove it when target is reached
* 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)
*/
@Override
protected void controlUpdate(float tpf) {
spatial.move(VECTOR_3_F.mult(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 EndAnimationMessage(pos));
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));
}
}
/**
* 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
* transformation, not its rendering process.
*
* @param rm the RenderManager rendering the controlled Spatial (not null)
* @param vp the ViewPort being rendered (not null)
*/
@Override
protected void controlRender(RenderManager rm, ViewPort vp) {

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;
@@ -6,12 +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;
@@ -45,12 +51,18 @@ class ShipControl extends AbstractControl {
* The current time within the oscillation cycle, used to calculate the ship's pitch angle.
*/
private float time;
/**
* Ship to be controlled
*/
private final Battleship battleship;
private static final Logger LOGGER = System.getLogger(ShipControl.class.getName());
/**
* this attribute is the ship, this ShipControl controls
*/
private final Battleship ship;
/**
* this CONST represents the sinking height, when the ship will be removed
*/
private static final Float SINKING_HEIGHT = -0.6f;
/**
* Constructs a new ShipControl instance for the specified Battleship.
@@ -59,8 +71,7 @@ class ShipControl extends AbstractControl {
*
* @param ship the Battleship object to control
*/
public ShipControl(Battleship ship) {
this.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;
@@ -68,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;
}
/**
@@ -82,24 +94,25 @@ 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);
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.2f * 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);
}
// 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);

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.client.gui;
@@ -79,6 +84,7 @@ public void receivedEvent(ItemRemovedEvent event) {
@Override
public void receivedEvent(ItemAddedEvent event) {
if (shipMap == event.map())
add(event.item());
}
}

View File

@@ -1,6 +1,11 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package server;
package pp.battleship.client.server;
import com.jme3.network.ConnectionListener;
import com.jme3.network.HostedConnection;
@@ -13,16 +18,11 @@
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.EndAnimationMessage;
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.StartAnimationMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.SwitchToBattleState;
import pp.battleship.message.server.*;
import pp.battleship.model.Battleship;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shot;
@@ -39,14 +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 static int port;
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<>();
@@ -63,18 +61,17 @@ 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(int port) {
public BattleshipLocalServer(int portNumber) {
config.readFromIfExists(CONFIG_FILE);
BattleshipServer.port = port;
PORT_NUMBER = portNumber;
LOGGER.log(Level.INFO, "Configuration: {0}", config); //NON-NLS
logic = new ServerGameLogic(this, config);
}
/**
* Runs a server
*/
public void run() {
startServer();
while (true)
@@ -82,12 +79,12 @@ public void run() {
}
/**
* Starts a server
* this method is used to start a server
*/
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();
@@ -99,9 +96,6 @@ private void startServer() {
}
}
/**
* Processes next received message
*/
private void processNextMessage() {
try {
pendingMessages.take().process(logic);
@@ -112,9 +106,6 @@ private void processNextMessage() {
}
}
/**
* Registers all serializable classes
*/
private void initializeSerializables() {
Serializer.registerClass(GameDetails.class);
Serializer.registerClass(StartBattleMessage.class);
@@ -124,26 +115,18 @@ private void initializeSerializables() {
Serializer.registerClass(Battleship.class);
Serializer.registerClass(IntPoint.class);
Serializer.registerClass(Shot.class);
Serializer.registerClass(StartAnimationMessage.class);
Serializer.registerClass(EndAnimationMessage.class);
Serializer.registerClass(SwitchToBattleState.class);
Serializer.registerClass(AnimationEndMessage.class);
Serializer.registerClass(AnimationStartMessage.class);
Serializer.registerClass(BackToBattleStateMessage.class);
}
/**
* Registers all listeners
*/
private void registerListeners() {
myServer.addMessageListener(this, MapMessage.class);
myServer.addMessageListener(this, ShootMessage.class);
myServer.addMessageListener(this, EndAnimationMessage.class);
myServer.addMessageListener(this, AnimationEndMessage.class);
myServer.addConnectionListener(this);
}
/**
* Handles a received message
* @param source the connection the message comes 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
@@ -151,22 +134,12 @@ public void messageReceived(HostedConnection source, Message message) {
pendingMessages.add(new ReceivedMessage(clientMessage, source.getId()));
}
/**
* Adds a new connection to a server
* @param server the server to add the connection to
* @param hostedConnection the connection to be added
*/
@Override
public void connectionAdded(Server server, HostedConnection hostedConnection) {
LOGGER.log(Level.INFO, "new connection {0}", hostedConnection); //NON-NLS
logic.addPlayer(hostedConnection.getId());
}
/**
* Removes a standing connection from a server
* @param server the server to add the connection to
* @param hostedConnection the connection to be added
*/
@Override
public void connectionRemoved(Server server, HostedConnection hostedConnection) {
LOGGER.log(Level.INFO, "connection closed: {0}", hostedConnection); //NON-NLS
@@ -179,10 +152,6 @@ public void connectionRemoved(Server server, HostedConnection hostedConnection)
}
}
/**
* Shuts down the server and terminates the application with the given exit code
* @param exitValue the exit status code
*/
private void exit(int exitValue) { //NON-NLS
LOGGER.log(Level.INFO, "close request"); //NON-NLS
if (myServer != null)

View File

@@ -1,15 +1,15 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package server;
package pp.battleship.client.server;
import pp.battleship.message.client.ClientInterpreter;
import pp.battleship.message.client.ClientMessage;
/**
* Represents a message received from a client
* @param message the received message
* @param from the ID of the client that sent the message
*/
record ReceivedMessage(ClientMessage message, int from) {
void process(ClientInterpreter interpreter) {
message.accept(interpreter, from);

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

View File

@@ -1,12 +0,0 @@
# Blender MTL File: 'AIM120D.blend'
# Material Count: 1
newmtl Material.006
Ns 96.078431
Ka 0.000000 0.000000 0.000000
Kd 0.640000 0.640000 0.640000
Ks 0.500000 0.500000 0.500000
Ni 1.000000
d 1.000000
illum 2
map_Kd texture.png

View File

@@ -1,2 +0,0 @@
AIM-120D Missile (Air-to-Air) by https://free3d.com/3d-model/aim-120d-shell-air-to-air-20348.html
License: License for personal use

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.8 MiB

View File

@@ -1,104 +0,0 @@
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 16.12.2011 14:18:52
newmtl white
Ns 53.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.6667 0.6667 0.6667
Kd 0.6667 0.6667 0.6667
Ks 0.1800 0.1800 0.1800
Ke 0.0000 0.0000 0.0000
newmtl boat_elements_black
Ns 55.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.0000 0.0000 0.0000
Kd 0.0000 0.0000 0.0000
Ks 0.3600 0.3600 0.3600
Ke 0.0000 0.0000 0.0000
newmtl boat_glass
Ns 60.0000
Ni 7.0000
d 0.4000
Tr 0.6000
Tf 0.4000 0.4000 0.4000
illum 2
Ka 0.1059 0.1569 0.1451
Kd 0.1059 0.1569 0.1451
Ks 0.6750 0.6750 0.6750
Ke 0.0000 0.0000 0.0000
newmtl boat_screw_hooks_bronze
Ns 80.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.2941 0.2157 0.0510
Kd 0.2941 0.2157 0.0510
Ks 0.7200 0.7200 0.7200
Ke 0.0000 0.0000 0.0000
newmtl boat_silver
Ns 80.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.3333 0.3333 0.3333
Kd 0.3333 0.3333 0.3333
Ks 0.7200 0.7200 0.7200
Ke 0.0000 0.0000 0.0000
newmtl boat_buffer
Ns 10.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.2700 0.2700 0.2700
Ke 0.0000 0.0000 0.0000
map_Ka boat_buffer_diffuse.jpg
map_Kd boat_buffer_diffuse.jpg
newmtl boat_roof_accessory
Ns 15.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.3600 0.3600 0.3600
Ke 0.0000 0.0000 0.0000
map_Ka boat_roof_accessory_diffuse.jpg
map_Kd boat_roof_accessory_diffuse.jpg
newmtl boat_body
Ns 55.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.3600 0.3600 0.3600
Ke 0.0000 0.0000 0.0000
map_Ka boat_body_diffuse.jpg
map_Kd boat_body_diffuse.jpg

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 166 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 717 KiB

View File

@@ -0,0 +1,28 @@
# 3ds Max Wavefront OBJ Exporter v0.97b - (c)2007 guruware
# File Created: 08.06.2011 15:26:00
newmtl _10634_SpeedBoat_v01_LOD310634_SpeedBoat_v01
Ns 53.0000
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 0.5882 0.5882 0.5882
Kd 0.5882 0.5882 0.5882
Ks 0.2000 0.2000 0.2000
Ke 0.0000 0.0000 0.0000
map_Ka 10634_SpeedBoat_v01.jpg
map_Kd 10634_SpeedBoat_v01.jpg
newmtl glass
Ns 80.0000
Ni 1.5000
d 0.2000
Tr 0.8000
Tf 0.2000 0.2000 0.2000
illum 2
Ka 0.5882 0.5882 0.5882
Kd 0.5882 0.5882 0.5882
Ks 0.5000 0.5000 0.5000
Ke 0.0000 0.0000 0.0000

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

View File

@@ -6,7 +6,7 @@ newmtl default
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 1.0000 1.0000 1.0000
Kd 1.0000 1.0000 1.0000

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

@@ -1,2 +1,3 @@
Missile firing fl by NHMWretched (https://pixabay.com/sound-effects/missile-firing-fl-106655/)
CCO License
RocketSound origin:
https://pixabay.com/sound-effects/rocket-loop-99748/
Licence: free to use

View File

@@ -1 +0,0 @@
Aluminum | Roie Shpigler | https://artlist.io/royalty-free-music/song/aluminum/122360

View File

@@ -1 +0,0 @@
A Touch of Dream | Max H. | https://artlist.io/royalty-free-music/song/a-touch-of-dream/126111

View File

@@ -1,4 +0,0 @@
Epic Cinematic Trailer | ELITE by Alex-Productions | https://onsound.eu/
Music promoted by https://www.chosic.com/free-music/all/
Creative Commons CC BY 3.0
https://creativecommons.org/licenses/by/3.0/

View File

@@ -1 +0,0 @@
Victory march of Valor | Land_of_Books_YouTube | https://pixabay.com/users/land_of_books_youtube-7733644/s

View File

@@ -1,2 +0,0 @@
Created using Metal Plates 13 from ambientCG.com,
licensed under the Creative Commons CC0 1.0 Universal License.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 MiB

View File

@@ -1,2 +0,0 @@
https://www.rawpixel.com/image/13141087/png-fire-bonfire-illuminated-destruction-generated-image-rawpixel
Licence: Free for personal use

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.exporter;
@@ -36,7 +41,7 @@ public static void main(String[] args) {
*/
@Override
public void simpleInitApp() {
export("Models/KingGeorgeV/King_George_V.obj", "Models/KingGeorgeV/KingGeorgeV.j3o"); //NON-NLS
export("Models/KingGeorgeV/rocket/proton.obj", "proton.j3o"); //NON-NLS
stop();
}

View File

@@ -6,7 +6,7 @@ newmtl _King_George_V
Ni 1.5000
d 1.0000
Tr 0.0000
Tf 1.0000 1.0000 1.0000
Tf 1.0000 1.0000 1.0000
illum 2
Ka 1.0000 1.0000 1.0000
Kd 1.0000 1.0000 1.0000

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship;
import pp.util.config.Config;

View File

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship;
import java.util.ResourceBundle;

View File

@@ -1,52 +1,44 @@
package pp.battleship.game.client;
import pp.battleship.message.client.EndAnimationMessage;
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.message.server.SwitchToBattleState;
import pp.battleship.model.IntPoint;
import pp.battleship.model.Shell;
import pp.battleship.model.ShipMap;
import pp.battleship.notification.Music;
import pp.battleship.notification.Sound;
import java.lang.System.Logger;
import java.lang.System.Logger.Level;
/**
* Represents the state in which the animation is played
*/
public class AnimationState extends ClientState {
private boolean myTurn;
private static final Logger LOGGER = System.getLogger(AnimationState.class.getName());
/**
* Constructor for the AnimationState class
* Constructs a client state of the specified game logic.
*
* @param logic the client logic
* @param turn a boolean containing if it's the client's turn
* @param position the position a Shell gets created
* @param logic the game logic
*/
public AnimationState(ClientGameLogic logic, boolean turn, IntPoint position) {
AnimationState(ClientGameLogic logic, boolean myTurn, IntPoint pos) {
super(logic);
logic.playMusic(Music.GAME_THEME);
myTurn = turn;
if (myTurn) {
logic.getOpponentMap().add(new Shell(position));
}
else {
logic.getOwnMap().add(new Shell(position));
logic.getOpponentMap().add(new Shell(pos));
logic.playSound(Sound.ROCKET);
} else {
logic.getOwnMap().add(new Shell(pos));
logic.playSound(Sound.ROCKET);
}
}
/**
* Makes sure the client renders the correct view
*
* @return true
*/
@Override
boolean showBattle() {
return true;
}
/**
* Reports the effect of a shot based on the server message.
*
@@ -54,29 +46,20 @@ boolean showBattle() {
*/
@Override
public void receivedEffect(EffectMessage msg) {
logic.playSound(Sound.ROCKET_STOP);
ClientGameLogic.LOGGER.log(Level.INFO, "report effect: {0}", msg); //NON-NLS
playSound(msg);
myTurn = msg.isMyTurn();
logic.setInfoText(msg.getInfoTextKey());
logic.setInfoText(msg.getInfoTextKey()); //
affectedMap(msg).add(msg.getShot());
if (destroyedOpponentShip(msg))
if (destroyedOpponentShip(msg)) {
logic.getOpponentMap().add(msg.getDestroyedShip());
}
if (msg.isGameOver()) {
msg.getRemainingOpponentShips().forEach(logic.getOpponentMap()::add);
logic.setState(new GameOverState(logic, msg.isGameLost()));
logic.setState(new GameOverState(logic));
}
}
/**
* Sets the client back to the battle state
*
* @param msg the received SwitchToBattleState message
*/
@Override
public void receivedSwitchToBattleState(SwitchToBattleState msg) {
logic.setState(new BattleState(logic, msg.getTurn()));
}
/**
* Determines which map (own or opponent's) should be affected by the shot based on the message.
*
@@ -97,6 +80,15 @@ 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.
@@ -111,4 +103,14 @@ else if (msg.getDestroyedShip() == null)
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

@@ -1,16 +1,15 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;
import pp.battleship.message.client.ShootMessage;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.StartAnimationMessage;
import pp.battleship.message.server.AnimationStartMessage;
import pp.battleship.model.IntPoint;
import pp.battleship.model.ShipMap;
import pp.battleship.notification.Music;
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.
@@ -26,14 +25,13 @@ class BattleState extends ClientState {
*/
public BattleState(ClientGameLogic logic, boolean myTurn) {
super(logic);
logic.playMusic(Music.GAME_THEME);
this.myTurn = myTurn;
}
/**
* Makes sure the client renders the correct view
* this return-statement decides, whether the battle will be shown
*
* @return true
* @return true, so the battle will be displayed
*/
@Override
public boolean showBattle() {
@@ -41,7 +39,7 @@ public boolean showBattle() {
}
/**
* Triggers a shoot event if it's client's turn
* the logic, responsible for deciding, whether it was a valid input or not
*
* @param pos the position where the click occurred
*/
@@ -54,13 +52,13 @@ else if (logic.getOpponentMap().isValid(pos))
}
/**
* Triggers an animation if StartAnimationMessage is received
* Receives an AnimationStartEvent and changes then the client-state to AnimationState
*
* @param msg the received Startanimation message
* @param msg the message received
*/
@Override
public void receivedStartAnimation(StartAnimationMessage msg) {
public void receivedAnimationStart(AnimationStartMessage msg) {
logic.setState(new AnimationState(logic, msg.isMyTurn(), msg.getPosition()));
logic.playSound(Sound.MISSILE_LAUNCH);
}
}

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;

View File

@@ -1,14 +1,14 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
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.StartAnimationMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.SwitchToBattleState;
import pp.battleship.message.server.*;
import pp.battleship.model.IntPoint;
import pp.battleship.model.ShipMap;
import pp.battleship.model.dto.ShipMapDTO;
@@ -17,8 +17,6 @@
import pp.battleship.notification.GameEventBroker;
import pp.battleship.notification.GameEventListener;
import pp.battleship.notification.InfoTextEvent;
import pp.battleship.notification.Music;
import pp.battleship.notification.MusicEvent;
import pp.battleship.notification.Sound;
import pp.battleship.notification.SoundEvent;
@@ -226,23 +224,23 @@ public void received(EffectMessage msg) {
}
/**
* Reports that client should play an animation
* Reports the AnimationStartMessage based on the server-state
*
* @param msg
* @param animationStartMessage the StartMessage received
*/
@Override
public void received(StartAnimationMessage msg) {
state.receivedStartAnimation(msg);
public void received(AnimationStartMessage animationStartMessage) {
state.receivedAnimationStart(animationStartMessage);//TODO
}
/**
* Reports that client should switch to the battle state
* Reports the BackToBattleStateMessage based on the server-state
*
* @param msg
* @param backToBattleStateMessage the Message received
*/
@Override
public void received(SwitchToBattleState msg) {
state.receivedSwitchToBattleState(msg);
public void received(BackToBattleStateMessage backToBattleStateMessage) {
state.receiveBackToBattleState(backToBattleStateMessage);
}
/**
@@ -371,13 +369,4 @@ public void notifyListeners(GameEvent event) {
public void update(float delta) {
state.update(delta);
}
/**
* Triggers an event to play specified music
*
* @param music the music to be played
*/
public void playMusic(Music music) {
notifyListeners(new MusicEvent(music));
}
}

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;

View File

@@ -1,12 +1,13 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;
import pp.battleship.message.server.EffectMessage;
import pp.battleship.message.server.GameDetails;
import pp.battleship.message.server.StartAnimationMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.SwitchToBattleState;
import pp.battleship.message.server.*;
import pp.battleship.model.IntPoint;
import java.io.File;
@@ -163,21 +164,10 @@ void receivedEffect(EffectMessage msg) {
}
/**
* Reports that client should switch to battle state
*
* @param msg the received SwitchToBattleState message
* @param msg the message received
*/
void receivedSwitchToBattleState(SwitchToBattleState msg) {
ClientGameLogic.LOGGER.log(Level.ERROR, "receivedSwitchToBattleState not allowed in {0}", getName());
}
/**
* Reports that the client should start an animation
*
* @param msg the received StartAnimation message
*/
void receivedStartAnimation(StartAnimationMessage msg) {
ClientGameLogic.LOGGER.log(Level.ERROR, "receivedStartAnimation not allowed in {0}", getName());
void receivedAnimationStart(AnimationStartMessage msg) {
ClientGameLogic.LOGGER.log(Level.ERROR, "receivedAnimationStart not allowed in {0}", getName());
}
/**
@@ -208,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

@@ -1,21 +1,26 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;
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.Arrays;
import java.util.ArrayList;
import java.util.List;
import static pp.battleship.Resources.lookup;
import static pp.battleship.game.client.ClientGameLogic.LOGGER;
import static pp.battleship.model.Battleship.Status.INVALID_PREVIEW;
import static pp.battleship.model.Battleship.Status.NORMAL;
import static pp.battleship.model.Battleship.Status.VALID_PREVIEW;
@@ -54,7 +59,7 @@ public boolean showEditor() {
*/
@Override
public void movePreview(IntPoint pos) {
LOGGER.log(Level.DEBUG, "move preview to {0}", pos); //NON-NLS
ClientGameLogic.LOGGER.log(Level.DEBUG, "move preview to {0}", pos); //NON-NLS
if (preview == null || !ownMap().isValid(pos)) return;
preview.moveTo(pos);
setPreviewStatus(preview);
@@ -69,7 +74,7 @@ public void movePreview(IntPoint pos) {
*/
@Override
public void clickOwnMap(IntPoint pos) {
LOGGER.log(Level.DEBUG, "click at {0} in own map", pos); //NON-NLS
ClientGameLogic.LOGGER.log(Level.DEBUG, "click at {0} in own map", pos); //NON-NLS
if (!ownMap().isValid(pos)) return;
if (preview == null)
modifyShip(pos);
@@ -123,7 +128,7 @@ private void placeShip(IntPoint cursor) {
*/
@Override
public void clickHarbor(IntPoint pos) {
LOGGER.log(Level.DEBUG, "click at {0} in harbor", pos); //NON-NLS
ClientGameLogic.LOGGER.log(Level.DEBUG, "click at {0} in harbor", pos); //NON-NLS
if (!harbor().isValid(pos)) return;
final Battleship shipAtCursor = harbor().findShipAt(pos);
if (preview != null) {
@@ -150,7 +155,7 @@ else if (shipAtCursor != null) {
*/
@Override
public void rotateShip() {
LOGGER.log(Level.DEBUG, "pushed rotate"); //NON-NLS
ClientGameLogic.LOGGER.log(Level.DEBUG, "pushed rotate"); //NON-NLS
if (preview == null) return;
preview.rotated();
ownMap().remove(preview);
@@ -236,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"));
else if (!checkMapToLoad(dto)) {
throw new IOException(lookup("ships.dont.fit.the.map"));
if (!verifyMap(dto)) {
throw new IOException(lookup("player.submitted.invalid.map"));
}
ownMap().clear();
dto.getShips().forEach(ownMap()::add);
@@ -247,32 +252,43 @@ else if (!checkMapToLoad(dto)) {
}
/**
* Checks if the provided map meets the requirements
* this method returns true, if the given map is valid (don't overlap or out of bound)
*
* @param dto the data transfer object to check
* @return boolean if the map meets the requirements
* @param dto the map
* @return true, if the map is valid
*/
private boolean checkMapToLoad(ShipMapDTO dto) {
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();
// check if ship is out of bounds
for (int i = 0; i < dto.getShips().size(); i++) {
Battleship battleship = dto.getShips().get(i);
if (battleship.getMaxX() >= mapWidth || battleship.getMinX() < 0 || battleship.getMaxY() >= mapHeight || battleship.getMinY() < 0) {
LOGGER.log(Level.ERROR, "Ship is out of bounds ({0})", battleship.toString());
for (Battleship ship : dto.getShips()) {
if (ship.getMaxX() > mapWidth || ship.getMinX() < 0 || ship.getMaxY() > mapHeight || ship.getMinY() < 0)
return false;
}
}
return true;
}
// check if ships overlap
/**
* 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 == compareShip)) {
if (ship.collidesWith(compareShip)) {
return false;
}
if (!ship.equals(compareShip)) {
if (ship.collidesWith(compareShip)) return false;
}
}
}

View File

@@ -1,9 +1,12 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;
import pp.battleship.notification.Music;
/**
* Represents the state of the client when the game is over.
*/
@@ -13,14 +16,8 @@ class GameOverState extends ClientState {
*
* @param logic the client game logic
*/
GameOverState(ClientGameLogic logic, boolean loser) {
GameOverState(ClientGameLogic logic) {
super(logic);
if (loser) {
logic.playMusic(Music.LOSE_THEME);
}
else {
logic.playMusic(Music.VICTORY_THEME);
}
}
/**

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;
@@ -53,11 +58,6 @@ private void fillHarbor(GameDetails details) {
}
}
/**
* Checks if map may be saved to file
*
* @return false
*/
@Override
public boolean maySaveMap() {
return false;

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.client;
@@ -36,14 +41,16 @@ public void receivedStartBattle(StartBattleMessage msg) {
}
/**
* Reverts the client back to the editor state if an invalid map is provided
* Handles the GameDetails message received from the server.
* If the map is invalid, the editor state is set.
*
* @param details the game details including map size and ships
* @param msg the GameDetails message received
*/
@Override
public void receivedGameDetails(GameDetails details) {
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

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.server;

View File

@@ -1,16 +1,18 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
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.EndAnimationMessage;
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.StartAnimationMessage;
import pp.battleship.message.server.StartBattleMessage;
import pp.battleship.message.server.SwitchToBattleState;
import pp.battleship.message.server.*;
import pp.battleship.model.Battleship;
import pp.battleship.model.IntPoint;
@@ -34,9 +36,8 @@ public class ServerGameLogic implements ClientInterpreter {
private final ServerSender serverSender;
private Player activePlayer;
private ServerState state = ServerState.WAIT;
private boolean p1AnimationFinished = false;
private boolean p2AnimationFinished = false;
private boolean playerOneAnimationReady = false;
private boolean playerTwoAnimationReady = false;
/**
* Constructs a ServerGameLogic with the specified sender and configuration.
@@ -141,72 +142,76 @@ 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 (!checkMap(msg, from)) {
LOGGER.log(Level.ERROR, "The submitted map is not allowed");
send(players.get(from), new GameDetails(config));
}
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());
}
/**
* Handles the reception of an EndAnimation message
* @param msg received EndAnimation message
*/
@Override
public void received(EndAnimationMessage msg, int from) {
if (state != ServerState.WAIT_ANIMATION)
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));
p1AnimationFinished = true;
playerOneAnimationReady = true;
shoot(getPlayerById(from), msg.getPosition());
}
else if (getPlayerById(from) == players.get(1)) {
} else if (getPlayerById(from) == players.get(1)) {
LOGGER.log(Level.DEBUG, "{0} set to true {1}", getPlayerById(from), getPlayerById(from).toString());
p2AnimationFinished = true;
playerTwoAnimationReady = true;
shoot(getPlayerById(from), msg.getPosition());
}
if (p1AnimationFinished && p2AnimationFinished) {
if (playerOneAnimationReady && playerTwoAnimationReady) {
setState(ServerState.BATTLE);
for (Player player : players)
send(player, new SwitchToBattleState(player == activePlayer));
p1AnimationFinished = false;
p2AnimationFinished = false;
send(player, new BackToBattleStateMessage(player == activePlayer));
playerOneAnimationReady = false;
playerTwoAnimationReady = false;
}
}
/**
* Returns true if the map contains correct ship placement and is of the correct size
* this method returns true, if the given map is valid (don't overlap or out of bound)
*
* @param msg the received MapMessage of the player
* @param from the ID of the Player
* @return a boolean based on if the transmitted map ist correct
* @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 verifyMap(MapMessage msg, int playerID) {
return verifyBounds(msg, playerID) && verifyOverlap(msg);
}
private boolean checkMap(MapMessage msg, int from) {
int mapWidth = getPlayerById(from).getMap().getWidth();
int mapHeight = getPlayerById(from).getMap().getHeight();
if (mapHeight != 10 || mapWidth != 10)
return false;
// check if ship is out of bounds
/**
* 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) {
LOGGER.log(Level.ERROR, "Ship is out of bounds ({0})", ship.toString());
if (ship.getMaxX() > mapWidth || ship.getMinX() < 0 || ship.getMaxY() > mapHeight || ship.getMinY() < 0)
return false;
}
}
return true;
}
// check if ships overlap
/**
* checks whether the ships overlap each other
*
* @param msg is the message, where the map is in
* @return true, if no ships overlap
*/
private boolean verifyOverlap(MapMessage msg) {
List<Battleship> ships = msg.getShips();
for (Battleship ship : ships) {
for (Battleship compareShip : ships) {
if (!(ship == compareShip)) {
if (ship.collidesWith(compareShip)) {
return false;
}
if (!ship.equals(compareShip)) {
if (ship.collidesWith(compareShip)) return false;
}
}
}
@@ -223,11 +228,13 @@ private boolean checkMap(MapMessage msg, int from) {
public void received(ShootMessage msg, int from) {
if (state != ServerState.BATTLE)
LOGGER.log(Level.ERROR, "shoot not allowed in {0}", state); //NON-NLS
else
else {
for (Player player : players) {
send(player, new StartAnimationMessage(msg.getPosition(), player == activePlayer));
setState(ServerState.WAIT_ANIMATION);
send(player, new AnimationStartMessage(msg.getPosition(), player == activePlayer));
setState(ServerState.ANIMATION_WAIT_STATE);
}
}
}
/**
@@ -251,86 +258,127 @@ void playerReady(Player player, List<Battleship> ships) {
}
/**
* Handles what Effect should be triggered based on the shot
* @param player the player receiving the message
* @param position the position the shot hit
* Handles the shooting action by the player.
*
* @param p the player who shot
* @param position the position of the shot
*/
void shoot(Player player, IntPoint position) {
void shoot(Player p, IntPoint position) {
final Battleship selectedShip;
selectedShip = getSelectedShip(player, position);
selectedShip = getSelectedShip(p, position);
if (selectedShip == null) {
shotMissed(player, position);
}
else {
shotHit(player, position, selectedShip);
nullShip(p, position);
} else {
shootShip(p, position, selectedShip);
}
}
/**
* Returns the ship at a given position
* @param player the player whose map will be checked for a ship
* @param position the position to be checked for a ship
* @return if there is a ship at the given position, returns the ship, else null
* 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
*/
Battleship getSelectedShip(Player player, IntPoint position) {
if (player != activePlayer) {
return player.getMap().findShipAt(position);
}
else {
return getOpponent(player).getMap().findShipAt(position);
}
private Battleship getSelectedShip(Player p, IntPoint position) {
return (p != activePlayer) ? p.getMap().findShipAt(position) : getOpponent(p).getMap().findShipAt(position);
}
/**
* Sends a message to the client that the shot missed
* @param player the player receiving the message
* @param position the position at which the shot hit in the water
* this method handles the shot logic, if the shot misses
*
* @param p the current player
* @param position the position shot at
*/
void shotMissed(Player player, IntPoint position) {
if (player != activePlayer) {
send(player, EffectMessage.miss(false, position));
}
else
private void nullShip(Player p, IntPoint position) {
if (p != activePlayer) {
send(p, EffectMessage.miss(false, position));
} else {
send(activePlayer, EffectMessage.miss(true, position));
if (p1AnimationFinished && p2AnimationFinished)
if (player == activePlayer)
activePlayer = getOpponent(player);
else
activePlayer = player;
}
//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);
}
}
}
/**
* Sends a message to the client that the shot missed
* @param player the player receiving the message
* @param position the position at which the shot hit in the ship
* @param ship the ship that has been hit
* 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
*/
void shotHit(Player player, IntPoint position, Battleship ship) {
ship.hit(position);
if (getOpponent(activePlayer).getMap().getRemainingShips().isEmpty()) {
if (player != activePlayer)
send(player, EffectMessage.lost(position, ship, activePlayer.getMap().getRemainingShips()));
else
send(activePlayer, EffectMessage.won(position, ship));
private void shootShip(Player p, IntPoint position, Battleship selectedShip) {
selectedShip.hit(position);
if (isGameOver(getOpponent(p))) {
gameOver(p, position, selectedShip);
} else if (selectedShip.isDestroyed()) {
shipDestroys(p, position, selectedShip);
} else {
shipHit(p, position);
}
}
if (p1AnimationFinished && p2AnimationFinished) {
setState(ServerState.GAME_OVER);
}
/**
* 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));
}
else if (ship.isDestroyed()) {
if (player != activePlayer)
send(player, EffectMessage.shipDestroyed(false, position, ship));
else
send(activePlayer, EffectMessage.shipDestroyed(true, position, ship));
if (playerOneAnimationReady && playerTwoAnimationReady) {
setState(ServerState.GAME_OVER);
}
else {
if (player != activePlayer) {
send(player, EffectMessage.hit(false, position));
}
else {
send(activePlayer, EffectMessage.hit(true, position));
}
}
/**
* 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

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.server;
import pp.battleship.message.server.ServerMessage;

View File

@@ -1,4 +1,9 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.server;
@@ -21,13 +26,13 @@ enum ServerState {
*/
BATTLE,
/**
* Waits for the Animation to finish
*/
WAIT_ANIMATION,
/**
* 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

@@ -1,3 +1,10 @@
////////////////////////////////////////
// Programming project code
// UniBw M, 2022, 2023, 2024
// www.unibw.de/inf2
// (c) Mark Minas (mark.minas@unibw.de)
////////////////////////////////////////
package pp.battleship.game.singlemode;
import pp.battleship.BattleshipConfig;

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