Browse Source

:tada: Ajout client de test du serveur

Arthur Brandao 6 năm trước cách đây
mục cha
commit
8c20c4b227
76 tập tin đã thay đổi với 3185 bổ sung0 xóa
  1. BIN
      BSWFX/dist/BSWFX.jar
  2. 32 0
      BSWFX/dist/README.TXT
  3. 21 0
      BSWFX/dist/file/css/map.css
  4. BIN
      BSWFX/dist/file/img.png
  5. 0 0
      BSWFX/dist/file/index.html
  6. BIN
      BSWFX/dist/file/sprite/bomb.png
  7. BIN
      BSWFX/dist/file/sprite/bomb_down.png
  8. BIN
      BSWFX/dist/file/sprite/bomb_up.png
  9. BIN
      BSWFX/dist/file/sprite/broken_leg.png
  10. BIN
      BSWFX/dist/file/sprite/classic_bomb.png
  11. BIN
      BSWFX/dist/file/sprite/fire_power.png
  12. BIN
      BSWFX/dist/file/sprite/life_max.png
  13. BIN
      BSWFX/dist/file/sprite/life_up.png
  14. BIN
      BSWFX/dist/file/sprite/limite.png
  15. BIN
      BSWFX/dist/file/sprite/major.png
  16. BIN
      BSWFX/dist/file/sprite/mine.png
  17. BIN
      BSWFX/dist/file/sprite/mine_bomb.png
  18. BIN
      BSWFX/dist/file/sprite/mur.png
  19. BIN
      BSWFX/dist/file/sprite/other.png
  20. BIN
      BSWFX/dist/file/sprite/player.png
  21. BIN
      BSWFX/dist/file/sprite/remote.png
  22. BIN
      BSWFX/dist/file/sprite/remote_bomb.png
  23. BIN
      BSWFX/dist/file/sprite/scooter.png
  24. BIN
      BSWFX/dist/file/sprite/sol.png
  25. 10 0
      BSWFX/dist/file/webfx/config.json
  26. BIN
      BSWFX/dist/file/webfx/icon.png
  27. 377 0
      BSWFX/dist/file/webfx/loader.html
  28. BIN
      BSWFX/dist/lib/json.jar
  29. 1 0
      BSWFX/dist/start.sh
  30. 21 0
      BSWFX/file/css/map.css
  31. BIN
      BSWFX/file/img.png
  32. 0 0
      BSWFX/file/index.html
  33. BIN
      BSWFX/file/sprite/bomb.png
  34. BIN
      BSWFX/file/sprite/bomb_down.png
  35. BIN
      BSWFX/file/sprite/bomb_up.png
  36. BIN
      BSWFX/file/sprite/broken_leg.png
  37. BIN
      BSWFX/file/sprite/classic_bomb.png
  38. BIN
      BSWFX/file/sprite/fire_power.png
  39. BIN
      BSWFX/file/sprite/life_max.png
  40. BIN
      BSWFX/file/sprite/life_up.png
  41. BIN
      BSWFX/file/sprite/limite.png
  42. BIN
      BSWFX/file/sprite/major.png
  43. BIN
      BSWFX/file/sprite/mine.png
  44. BIN
      BSWFX/file/sprite/mine_bomb.png
  45. BIN
      BSWFX/file/sprite/mur.png
  46. BIN
      BSWFX/file/sprite/other.png
  47. BIN
      BSWFX/file/sprite/player.png
  48. BIN
      BSWFX/file/sprite/remote.png
  49. BIN
      BSWFX/file/sprite/remote_bomb.png
  50. BIN
      BSWFX/file/sprite/scooter.png
  51. BIN
      BSWFX/file/sprite/sol.png
  52. 10 0
      BSWFX/file/webfx/config.json
  53. BIN
      BSWFX/file/webfx/icon.png
  54. 377 0
      BSWFX/file/webfx/loader.html
  55. BIN
      BSWFX/library/json.jar
  56. 484 0
      BSWFX/src/bs/Game.java
  57. 305 0
      BSWFX/src/bs/Player.java
  58. 131 0
      BSWFX/src/bswfx/BomberStudent.java
  59. 57 0
      BSWFX/src/bswfx/KeyHandler.java
  60. 29 0
      BSWFX/src/bswfx/ScreenManager.java
  61. 29 0
      BSWFX/src/bswfx/handler/HandlerAttackAffect.java
  62. 47 0
      BSWFX/src/bswfx/handler/HandlerAttackBomb.java
  63. 92 0
      BSWFX/src/bswfx/handler/HandlerAttackExplose.java
  64. 23 0
      BSWFX/src/bswfx/handler/HandlerMajorEnd.java
  65. 30 0
      BSWFX/src/bswfx/handler/HandlerPlayerJoin.java
  66. 51 0
      BSWFX/src/bswfx/handler/HandlerPlayerMove.java
  67. 32 0
      BSWFX/src/bswfx/handler/HandlerPlayerQuit.java
  68. 24 0
      BSWFX/src/bswfx/handler/HandlerServerEnd.java
  69. 216 0
      BSWFX/src/rsx/BomberStudentClient.java
  70. 13 0
      BSWFX/src/rsx/BomberStudentHandler.java
  71. 98 0
      BSWFX/src/rsx/BomberStudentRequest.java
  72. 177 0
      BSWFX/src/rsx/tcp/TcpClient.java
  73. 168 0
      BSWFX/src/rsx/udp/Broadcast.java
  74. 192 0
      BSWFX/src/wfx/WebFx.java
  75. 137 0
      BSWFX/src/wfx/WebFxConfig.java
  76. 1 0
      BSWFX/start.sh

BIN
BSWFX/dist/BSWFX.jar


+ 32 - 0
BSWFX/dist/README.TXT

@@ -0,0 +1,32 @@
+========================
+BUILD OUTPUT DESCRIPTION
+========================
+
+When you build an Java application project that has a main class, the IDE
+automatically copies all of the JAR
+files on the projects classpath to your projects dist/lib folder. The IDE
+also adds each of the JAR files to the Class-Path element in the application
+JAR files manifest file (MANIFEST.MF).
+
+To run the project from the command line, go to the dist folder and
+type the following:
+
+java -jar "BSWFX.jar" 
+
+To distribute this project, zip up the dist folder (including the lib folder)
+and distribute the ZIP file.
+
+Notes:
+
+* If two JAR files on the project classpath have the same name, only the first
+JAR file is copied to the lib folder.
+* Only JAR files are copied to the lib folder.
+If the classpath contains other types of files or folders, these files (folders)
+are not copied.
+* If a library on the projects classpath also has a Class-Path element
+specified in the manifest,the content of the Class-Path element has to be on
+the projects runtime path.
+* To set a main class in a standard Java project, right-click the project node
+in the Projects window and choose Properties. Then click Run and enter the
+class name in the Main Class field. Alternatively, you can manually type the
+class name in the manifest Main-Class element.

+ 21 - 0
BSWFX/dist/file/css/map.css

@@ -0,0 +1,21 @@
+table{
+	border-collapse: collapse;
+}
+
+td, img, tr{
+	border-collapse: collapse;
+	margin: 0px;
+	padding: 0px;
+	border: none;
+	position: relative;
+}
+
+img{
+	vertical-align:bottom
+}
+
+#game{
+  	position: absolute;
+	top: 50%; left: 50%;
+  	transform: translate(-50%, -50%);
+}

BIN
BSWFX/dist/file/img.png


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
BSWFX/dist/file/index.html


BIN
BSWFX/dist/file/sprite/bomb.png


BIN
BSWFX/dist/file/sprite/bomb_down.png


BIN
BSWFX/dist/file/sprite/bomb_up.png


BIN
BSWFX/dist/file/sprite/broken_leg.png


BIN
BSWFX/dist/file/sprite/classic_bomb.png


BIN
BSWFX/dist/file/sprite/fire_power.png


BIN
BSWFX/dist/file/sprite/life_max.png


BIN
BSWFX/dist/file/sprite/life_up.png


BIN
BSWFX/dist/file/sprite/limite.png


BIN
BSWFX/dist/file/sprite/major.png


BIN
BSWFX/dist/file/sprite/mine.png


BIN
BSWFX/dist/file/sprite/mine_bomb.png


BIN
BSWFX/dist/file/sprite/mur.png


BIN
BSWFX/dist/file/sprite/other.png


BIN
BSWFX/dist/file/sprite/player.png


BIN
BSWFX/dist/file/sprite/remote.png


BIN
BSWFX/dist/file/sprite/remote_bomb.png


BIN
BSWFX/dist/file/sprite/scooter.png


BIN
BSWFX/dist/file/sprite/sol.png


+ 10 - 0
BSWFX/dist/file/webfx/config.json

@@ -0,0 +1,10 @@
+{
+	"title": "BSWFX",
+	"icon" : "file/webfx/icon.png",
+	"defaultHtml" : {
+		"file" : true,
+		"html" : "file/webfx/loader.html"
+	},
+	"width" : 1000,
+	"height": 1000
+}

BIN
BSWFX/dist/file/webfx/icon.png


+ 377 - 0
BSWFX/dist/file/webfx/loader.html

@@ -0,0 +1,377 @@
+<style type="text/css">
+html, body {
+  background: white;
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+
+.loader {
+  position: absolute;
+  width: 15rem;
+  height: 15rem;
+  left: 50%;
+  top: 50%;
+  -moz-transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+  -ms-transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+  -webkit-transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+  transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+}
+.loader div {
+  position: absolute;
+  left: 0;
+  width: 0.5rem;
+  height: 0.5rem;
+  background: white;
+  border-radius: 1rem;
+  opacity: 0;
+}
+
+.loader div:nth-child(1) {
+  top: 0rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0s infinite ease-in-out;
+  animation: dna_rotate 2s 0s infinite ease-in-out;
+}
+
+.loader div:nth-child(2) {
+  top: 0.6rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.1s infinite ease-in-out;
+  animation: dna_rotate 2s 1.1s infinite ease-in-out;
+}
+
+.loader div:nth-child(3) {
+  top: 1.2rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.2s infinite ease-in-out;
+  animation: dna_rotate 2s 0.2s infinite ease-in-out;
+}
+
+.loader div:nth-child(4) {
+  top: 1.8rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.3s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.3s infinite ease-in-out;
+  animation: dna_rotate 2s 1.3s infinite ease-in-out;
+}
+
+.loader div:nth-child(5) {
+  top: 2.4rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.4s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.4s infinite ease-in-out;
+  animation: dna_rotate 2s 0.4s infinite ease-in-out;
+}
+
+.loader div:nth-child(6) {
+  top: 3rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.5s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.5s infinite ease-in-out;
+  animation: dna_rotate 2s 1.5s infinite ease-in-out;
+}
+
+.loader div:nth-child(7) {
+  top: 3.6rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.6s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.6s infinite ease-in-out;
+  animation: dna_rotate 2s 0.6s infinite ease-in-out;
+}
+
+.loader div:nth-child(8) {
+  top: 4.2rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.7s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.7s infinite ease-in-out;
+  animation: dna_rotate 2s 1.7s infinite ease-in-out;
+}
+
+.loader div:nth-child(9) {
+  top: 4.8rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.8s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.8s infinite ease-in-out;
+  animation: dna_rotate 2s 0.8s infinite ease-in-out;
+}
+
+.loader div:nth-child(10) {
+  top: 5.4rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.9s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.9s infinite ease-in-out;
+  animation: dna_rotate 2s 1.9s infinite ease-in-out;
+}
+
+.loader div:nth-child(11) {
+  top: 6rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1s infinite ease-in-out;
+  animation: dna_rotate 2s 1s infinite ease-in-out;
+}
+
+.loader div:nth-child(12) {
+  top: 6.6rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.1s infinite ease-in-out;
+  animation: dna_rotate 2s 2.1s infinite ease-in-out;
+}
+
+.loader div:nth-child(13) {
+  top: 7.2rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.2s infinite ease-in-out;
+  animation: dna_rotate 2s 1.2s infinite ease-in-out;
+}
+
+.loader div:nth-child(14) {
+  top: 7.8rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.3s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.3s infinite ease-in-out;
+  animation: dna_rotate 2s 2.3s infinite ease-in-out;
+}
+
+.loader div:nth-child(15) {
+  top: 8.4rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.4s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.4s infinite ease-in-out;
+  animation: dna_rotate 2s 1.4s infinite ease-in-out;
+}
+
+.loader div:nth-child(16) {
+  top: 9rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.5s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.5s infinite ease-in-out;
+  animation: dna_rotate 2s 2.5s infinite ease-in-out;
+}
+
+.loader div:nth-child(17) {
+  top: 9.6rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.6s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.6s infinite ease-in-out;
+  animation: dna_rotate 2s 1.6s infinite ease-in-out;
+}
+
+.loader div:nth-child(18) {
+  top: 10.2rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.7s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.7s infinite ease-in-out;
+  animation: dna_rotate 2s 2.7s infinite ease-in-out;
+}
+
+.loader div:nth-child(19) {
+  top: 10.8rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.8s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.8s infinite ease-in-out;
+  animation: dna_rotate 2s 1.8s infinite ease-in-out;
+}
+
+.loader div:nth-child(20) {
+  top: 11.4rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.9s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.9s infinite ease-in-out;
+  animation: dna_rotate 2s 2.9s infinite ease-in-out;
+}
+
+.loader div:nth-child(21) {
+  top: 12rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2s infinite ease-in-out;
+  animation: dna_rotate 2s 2s infinite ease-in-out;
+}
+
+.loader div:nth-child(22) {
+  top: 12.6rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 3.1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 3.1s infinite ease-in-out;
+  animation: dna_rotate 2s 3.1s infinite ease-in-out;
+}
+
+.loader div:nth-child(23) {
+  top: 13.2rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 2.2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.2s infinite ease-in-out;
+  animation: dna_rotate 2s 2.2s infinite ease-in-out;
+}
+
+.loader div:nth-child(24) {
+  top: 13.8rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 3.3s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 3.3s infinite ease-in-out;
+  animation: dna_rotate 2s 3.3s infinite ease-in-out;
+}
+
+.loader div:nth-child(25) {
+  top: 14.4rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 2.4s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.4s infinite ease-in-out;
+  animation: dna_rotate 2s 2.4s infinite ease-in-out;
+}
+
+.loader div:nth-child(26) {
+  top: 15rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 3.5s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 3.5s infinite ease-in-out;
+  animation: dna_rotate 2s 3.5s infinite ease-in-out;
+}
+
+@-moz-keyframes dna_rotate {
+  0% {
+    opacity: 1;
+    -moz-transform: scale(1);
+    transform: scale(1);
+    left: 40%;
+    z-index: 0;
+  }
+  25% {
+    opacity: 1;
+    -moz-transform: scale(1.8);
+    transform: scale(1.8);
+  }
+  50% {
+    opacity: 1;
+    left: 60%;
+    z-index: 1;
+    -moz-transform: scale(1);
+    transform: scale(1);
+  }
+  75% {
+    opacity: 1;
+    -moz-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    opacity: 1;
+    left: 40%;
+    z-index: 0;
+    -moz-transform: scale(1);
+    transform: scale(1);
+  }
+}
+@-webkit-keyframes dna_rotate {
+  0% {
+    opacity: 1;
+    -webkit-transform: scale(1);
+    transform: scale(1);
+    left: 40%;
+    z-index: 0;
+  }
+  25% {
+    opacity: 1;
+    -webkit-transform: scale(1.8);
+    transform: scale(1.8);
+  }
+  50% {
+    opacity: 1;
+    left: 60%;
+    z-index: 1;
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+  75% {
+    opacity: 1;
+    -webkit-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    opacity: 1;
+    left: 40%;
+    z-index: 0;
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+}
+@keyframes dna_rotate {
+  0% {
+    opacity: 1;
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -webkit-transform: scale(1);
+    transform: scale(1);
+    left: 40%;
+    z-index: 0;
+  }
+  25% {
+    opacity: 1;
+    -moz-transform: scale(1.8);
+    -ms-transform: scale(1.8);
+    -webkit-transform: scale(1.8);
+    transform: scale(1.8);
+  }
+  50% {
+    opacity: 1;
+    left: 60%;
+    z-index: 1;
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+  75% {
+    opacity: 1;
+    -moz-transform: scale(0.5);
+    -ms-transform: scale(0.5);
+    -webkit-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    opacity: 1;
+    left: 40%;
+    z-index: 0;
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+}
+</style>
+
+<div class='loader'>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>

BIN
BSWFX/dist/lib/json.jar


+ 1 - 0
BSWFX/dist/start.sh

@@ -0,0 +1 @@
+ 

+ 21 - 0
BSWFX/file/css/map.css

@@ -0,0 +1,21 @@
+table{
+	border-collapse: collapse;
+}
+
+td, img, tr{
+	border-collapse: collapse;
+	margin: 0px;
+	padding: 0px;
+	border: none;
+	position: relative;
+}
+
+img{
+	vertical-align:bottom
+}
+
+#game{
+  	position: absolute;
+	top: 50%; left: 50%;
+  	transform: translate(-50%, -50%);
+}

BIN
BSWFX/file/img.png


Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 0 - 0
BSWFX/file/index.html


BIN
BSWFX/file/sprite/bomb.png


BIN
BSWFX/file/sprite/bomb_down.png


BIN
BSWFX/file/sprite/bomb_up.png


BIN
BSWFX/file/sprite/broken_leg.png


BIN
BSWFX/file/sprite/classic_bomb.png


BIN
BSWFX/file/sprite/fire_power.png


BIN
BSWFX/file/sprite/life_max.png


BIN
BSWFX/file/sprite/life_up.png


BIN
BSWFX/file/sprite/limite.png


BIN
BSWFX/file/sprite/major.png


BIN
BSWFX/file/sprite/mine.png


BIN
BSWFX/file/sprite/mine_bomb.png


BIN
BSWFX/file/sprite/mur.png


BIN
BSWFX/file/sprite/other.png


BIN
BSWFX/file/sprite/player.png


BIN
BSWFX/file/sprite/remote.png


BIN
BSWFX/file/sprite/remote_bomb.png


BIN
BSWFX/file/sprite/scooter.png


BIN
BSWFX/file/sprite/sol.png


+ 10 - 0
BSWFX/file/webfx/config.json

@@ -0,0 +1,10 @@
+{
+	"title": "BSWFX",
+	"icon" : "file/webfx/icon.png",
+	"defaultHtml" : {
+		"file" : true,
+		"html" : "file/webfx/loader.html"
+	},
+	"width" : 1000,
+	"height": 1000
+}

BIN
BSWFX/file/webfx/icon.png


+ 377 - 0
BSWFX/file/webfx/loader.html

@@ -0,0 +1,377 @@
+<style type="text/css">
+html, body {
+  background: white;
+  width: 100%;
+  height: 100%;
+  margin: 0;
+  padding: 0;
+}
+
+.loader {
+  position: absolute;
+  width: 15rem;
+  height: 15rem;
+  left: 50%;
+  top: 50%;
+  -moz-transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+  -ms-transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+  -webkit-transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+  transform: translateX(-50%) translateY(-50%) rotate(-90deg) scaleX(-1);
+}
+.loader div {
+  position: absolute;
+  left: 0;
+  width: 0.5rem;
+  height: 0.5rem;
+  background: white;
+  border-radius: 1rem;
+  opacity: 0;
+}
+
+.loader div:nth-child(1) {
+  top: 0rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0s infinite ease-in-out;
+  animation: dna_rotate 2s 0s infinite ease-in-out;
+}
+
+.loader div:nth-child(2) {
+  top: 0.6rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.1s infinite ease-in-out;
+  animation: dna_rotate 2s 1.1s infinite ease-in-out;
+}
+
+.loader div:nth-child(3) {
+  top: 1.2rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.2s infinite ease-in-out;
+  animation: dna_rotate 2s 0.2s infinite ease-in-out;
+}
+
+.loader div:nth-child(4) {
+  top: 1.8rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.3s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.3s infinite ease-in-out;
+  animation: dna_rotate 2s 1.3s infinite ease-in-out;
+}
+
+.loader div:nth-child(5) {
+  top: 2.4rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.4s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.4s infinite ease-in-out;
+  animation: dna_rotate 2s 0.4s infinite ease-in-out;
+}
+
+.loader div:nth-child(6) {
+  top: 3rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.5s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.5s infinite ease-in-out;
+  animation: dna_rotate 2s 1.5s infinite ease-in-out;
+}
+
+.loader div:nth-child(7) {
+  top: 3.6rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.6s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.6s infinite ease-in-out;
+  animation: dna_rotate 2s 0.6s infinite ease-in-out;
+}
+
+.loader div:nth-child(8) {
+  top: 4.2rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.7s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.7s infinite ease-in-out;
+  animation: dna_rotate 2s 1.7s infinite ease-in-out;
+}
+
+.loader div:nth-child(9) {
+  top: 4.8rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 0.8s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 0.8s infinite ease-in-out;
+  animation: dna_rotate 2s 0.8s infinite ease-in-out;
+}
+
+.loader div:nth-child(10) {
+  top: 5.4rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 1.9s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.9s infinite ease-in-out;
+  animation: dna_rotate 2s 1.9s infinite ease-in-out;
+}
+
+.loader div:nth-child(11) {
+  top: 6rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1s infinite ease-in-out;
+  animation: dna_rotate 2s 1s infinite ease-in-out;
+}
+
+.loader div:nth-child(12) {
+  top: 6.6rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.1s infinite ease-in-out;
+  animation: dna_rotate 2s 2.1s infinite ease-in-out;
+}
+
+.loader div:nth-child(13) {
+  top: 7.2rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.2s infinite ease-in-out;
+  animation: dna_rotate 2s 1.2s infinite ease-in-out;
+}
+
+.loader div:nth-child(14) {
+  top: 7.8rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.3s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.3s infinite ease-in-out;
+  animation: dna_rotate 2s 2.3s infinite ease-in-out;
+}
+
+.loader div:nth-child(15) {
+  top: 8.4rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.4s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.4s infinite ease-in-out;
+  animation: dna_rotate 2s 1.4s infinite ease-in-out;
+}
+
+.loader div:nth-child(16) {
+  top: 9rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.5s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.5s infinite ease-in-out;
+  animation: dna_rotate 2s 2.5s infinite ease-in-out;
+}
+
+.loader div:nth-child(17) {
+  top: 9.6rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.6s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.6s infinite ease-in-out;
+  animation: dna_rotate 2s 1.6s infinite ease-in-out;
+}
+
+.loader div:nth-child(18) {
+  top: 10.2rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.7s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.7s infinite ease-in-out;
+  animation: dna_rotate 2s 2.7s infinite ease-in-out;
+}
+
+.loader div:nth-child(19) {
+  top: 10.8rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 1.8s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 1.8s infinite ease-in-out;
+  animation: dna_rotate 2s 1.8s infinite ease-in-out;
+}
+
+.loader div:nth-child(20) {
+  top: 11.4rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 2.9s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.9s infinite ease-in-out;
+  animation: dna_rotate 2s 2.9s infinite ease-in-out;
+}
+
+.loader div:nth-child(21) {
+  top: 12rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2s infinite ease-in-out;
+  animation: dna_rotate 2s 2s infinite ease-in-out;
+}
+
+.loader div:nth-child(22) {
+  top: 12.6rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 3.1s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 3.1s infinite ease-in-out;
+  animation: dna_rotate 2s 3.1s infinite ease-in-out;
+}
+
+.loader div:nth-child(23) {
+  top: 13.2rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 2.2s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.2s infinite ease-in-out;
+  animation: dna_rotate 2s 2.2s infinite ease-in-out;
+}
+
+.loader div:nth-child(24) {
+  top: 13.8rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 3.3s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 3.3s infinite ease-in-out;
+  animation: dna_rotate 2s 3.3s infinite ease-in-out;
+}
+
+.loader div:nth-child(25) {
+  top: 14.4rem;
+  background: #ffdd00;
+  -moz-animation: dna_rotate 2s 2.4s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 2.4s infinite ease-in-out;
+  animation: dna_rotate 2s 2.4s infinite ease-in-out;
+}
+
+.loader div:nth-child(26) {
+  top: 15rem;
+  background: black;
+  -moz-animation: dna_rotate 2s 3.5s infinite ease-in-out;
+  -webkit-animation: dna_rotate 2s 3.5s infinite ease-in-out;
+  animation: dna_rotate 2s 3.5s infinite ease-in-out;
+}
+
+@-moz-keyframes dna_rotate {
+  0% {
+    opacity: 1;
+    -moz-transform: scale(1);
+    transform: scale(1);
+    left: 40%;
+    z-index: 0;
+  }
+  25% {
+    opacity: 1;
+    -moz-transform: scale(1.8);
+    transform: scale(1.8);
+  }
+  50% {
+    opacity: 1;
+    left: 60%;
+    z-index: 1;
+    -moz-transform: scale(1);
+    transform: scale(1);
+  }
+  75% {
+    opacity: 1;
+    -moz-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    opacity: 1;
+    left: 40%;
+    z-index: 0;
+    -moz-transform: scale(1);
+    transform: scale(1);
+  }
+}
+@-webkit-keyframes dna_rotate {
+  0% {
+    opacity: 1;
+    -webkit-transform: scale(1);
+    transform: scale(1);
+    left: 40%;
+    z-index: 0;
+  }
+  25% {
+    opacity: 1;
+    -webkit-transform: scale(1.8);
+    transform: scale(1.8);
+  }
+  50% {
+    opacity: 1;
+    left: 60%;
+    z-index: 1;
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+  75% {
+    opacity: 1;
+    -webkit-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    opacity: 1;
+    left: 40%;
+    z-index: 0;
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+}
+@keyframes dna_rotate {
+  0% {
+    opacity: 1;
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -webkit-transform: scale(1);
+    transform: scale(1);
+    left: 40%;
+    z-index: 0;
+  }
+  25% {
+    opacity: 1;
+    -moz-transform: scale(1.8);
+    -ms-transform: scale(1.8);
+    -webkit-transform: scale(1.8);
+    transform: scale(1.8);
+  }
+  50% {
+    opacity: 1;
+    left: 60%;
+    z-index: 1;
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+  75% {
+    opacity: 1;
+    -moz-transform: scale(0.5);
+    -ms-transform: scale(0.5);
+    -webkit-transform: scale(0.5);
+    transform: scale(0.5);
+  }
+  100% {
+    opacity: 1;
+    left: 40%;
+    z-index: 0;
+    -moz-transform: scale(1);
+    -ms-transform: scale(1);
+    -webkit-transform: scale(1);
+    transform: scale(1);
+  }
+}
+</style>
+
+<div class='loader'>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+  <div></div>
+</div>

BIN
BSWFX/library/json.jar


+ 484 - 0
BSWFX/src/bs/Game.java

@@ -0,0 +1,484 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bs;
+
+import bswfx.BomberStudent;
+import java.util.HashMap;
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+/**
+ *
+ * @author loquicom
+ */
+public class Game {
+
+    protected HashMap<Integer, Player> player = new HashMap<>();
+    protected int mainPlayer;
+    protected int width;
+    protected int height;
+    protected String map[][];
+
+    public Game(JSONObject jo) {
+        //Recup la map
+        JSONObject joMap = jo.getJSONObject("map");
+        this.width = joMap.getInt("width");
+        this.height = joMap.getInt("height");
+        this.map = this.parseMap(joMap.getString("content"));
+        //Creation joueur principale
+        JSONObject joPlayer = jo.getJSONObject("player");
+        Player p = new Player(joPlayer, jo.getString("startPos"));
+        this.player.put(joPlayer.getInt("id"), p);
+        this.map[p.getX()][p.getY()] = "" + p.getId();
+        this.mainPlayer = p.getId();
+        //Creation autre joueurs
+        if (jo.has("players")) {
+            JSONArray ja = jo.getJSONArray("players");
+            for (int i = 0; i < ja.length(); i++) {
+                joPlayer = ja.getJSONObject(i);
+                int id = joPlayer.getInt("id");
+                if (id != this.mainPlayer) {
+                    p = new Player(id, joPlayer.getString("pos"));
+                    this.player.put(id, p);
+                    this.map[p.getX()][p.getY()] = "" + id;
+                }
+            }
+        }
+    }
+
+    /* --- Méthodes jeu --- */
+    public void join(int id, String pos) {
+        Player p = new Player(id, pos);
+        this.player.put(id, p);
+        this.map[p.getX()][p.getY()] = "" + id;
+    }
+
+    public boolean move(int player, int dir) {
+        //Recup le joueur
+        Player p = this.player.get(player);
+        if (p == null) {
+            return false;
+        }
+        //Calcul nouvelle coord
+        int x = p.getX();
+        int y = p.getY();
+        switch (dir) {
+            case Player.UP:
+                if (y > 0) {
+                    y--;
+                }
+                break;
+            case Player.LEFT:
+                if (x > 0) {
+                    x--;
+                }
+                break;
+            case Player.DOWN:
+                if (y < this.height - 1) {
+                    y++;
+                }
+                break;
+            case Player.RIGHT:
+                if (x < this.width - 1) {
+                    x++;
+                }
+                break;
+            default:
+                return false;
+        }
+        //Regarde si le joueur marche sur un objet
+        switch (this.map[x][y]) {
+            case "cb":
+                this.getObject(Player.CLASSIC);
+                break;
+            case "mb":
+                this.getObject(Player.MINE);
+                break;
+            case "rb":
+                this.getObject(Player.REMOTE);
+                break;
+            case "bu":
+                this.getObject(Player.BOMBUP);
+                break;
+            case "bd":
+                this.getObject(Player.BOMBDOWN);
+                break;
+            case "f":
+                this.getObject(Player.FIREPOWER);
+                break;
+            case "s":
+                this.getObject(Player.SCOOTER);
+                break;
+            case "bl":
+                this.getObject(Player.BROKENLEG);
+                break;
+            case "i":
+                this.getObject(Player.MAJOR);
+                break;
+            case "lm":
+                this.getObject(Player.LIFEMAX);
+                break;
+            case "lu":
+                this.getObject(Player.LIFEUP);
+                break;
+        }
+        //Deplacement
+        p.setDir(dir);
+        this.map[x][y] = "" + p.getId();
+        this.map[p.getX()][p.getY()] = "_";
+        //Met à jour le joueur
+        p.setX(x);
+        p.setY(y);
+        return true;
+    }
+
+    public boolean newBomb(int type, String coord) {
+        //Recup la position
+        int pos[] = this.parseCoord(coord);
+        //Met la bombe sur la map
+        switch (type) {
+            case Player.CLASSIC:
+                this.map[pos[0]][pos[1]] = "b";
+                break;
+            case Player.MINE:
+                this.map[pos[0]][pos[1]] = "m";
+                break;
+            case Player.REMOTE:
+                this.map[pos[0]][pos[1]] = "r";
+                break;
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    public void removeBomb(String coord) {
+        int pos[] = this.parseCoord(coord);
+        if (this.map[pos[0]][pos[1]].equals("b") || this.map[pos[0]][pos[1]].equals("m") || this.map[pos[0]][pos[1]].equals("r")) {
+            this.map[pos[0]][pos[1]] = "_";
+        }
+    }
+
+    public boolean newObject(int type, String coord) {
+        //Recup la position
+        int pos[] = this.parseCoord(coord);
+        //Met la bombe sur la map
+        switch (type) {
+            case Player.CLASSIC:
+                this.map[pos[0]][pos[1]] = "cb";
+                break;
+            case Player.MINE:
+                this.map[pos[0]][pos[1]] = "mb";
+                break;
+            case Player.REMOTE:
+                this.map[pos[0]][pos[1]] = "rb";
+                break;
+            case Player.BOMBUP:
+                this.map[pos[0]][pos[1]] = "bu";
+                break;
+            case Player.BOMBDOWN:
+                this.map[pos[0]][pos[1]] = "bd";
+                break;
+            case Player.FIREPOWER:
+                this.map[pos[0]][pos[1]] = "f";
+                break;
+            case Player.SCOOTER:
+                this.map[pos[0]][pos[1]] = "s";
+                break;
+            case Player.BROKENLEG:
+                this.map[pos[0]][pos[1]] = "bl";
+                break;
+            case Player.MAJOR:
+                this.map[pos[0]][pos[1]] = "i";
+                break;
+            case Player.LIFEUP:
+                this.map[pos[0]][pos[1]] = "lu";
+                break;
+            case Player.LIFEMAX:
+                this.map[pos[0]][pos[1]] = "lm";
+                break;
+            default:
+                return false;
+        }
+        return true;
+    }
+
+    public boolean getObject(int type) {
+        JSONObject param = new JSONObject();
+        //Creation json en fonction type
+        switch (type) {
+            case Player.CLASSIC:
+                param.put("type", "bomb");
+                param.put("class", "classic");
+                break;
+            case Player.MINE:
+                param.put("type", "bomb");
+                param.put("class", "mine");
+                break;
+            case Player.REMOTE:
+                param.put("type", "bomb");
+                param.put("class", "remote");
+                break;
+            case Player.BOMBUP:
+                param.put("type", "bonusMalus");
+                param.put("class", "bomb_up");
+                break;
+            case Player.BOMBDOWN:
+                param.put("type", "bonusMalus");
+                param.put("class", "bomb_down");
+                break;
+            case Player.FIREPOWER:
+                param.put("type", "bonusMalus");
+                param.put("class", "fire_power");
+                break;
+            case Player.SCOOTER:
+                param.put("type", "bonusMalus");
+                param.put("class", "scooter");
+                break;
+            case Player.BROKENLEG:
+                param.put("type", "bonusMalus");
+                param.put("class", "broken_legs");
+                break;
+            case Player.MAJOR:
+                param.put("type", "bonusMalus");
+                param.put("class", "major");
+                break;
+            case Player.LIFEUP:
+                param.put("type", "bonusMalus");
+                param.put("class", "life_up");
+                break;
+            case Player.LIFEMAX:
+                param.put("type", "bonusMalus");
+                param.put("class", "life_max");
+                break;
+            default:
+                return false;
+        }
+        //Envoi
+        if (!BomberStudent.bsc.send("POST", "object/new", param)) {
+            return false;
+        }
+        //Reception
+        JSONObject res = BomberStudent.bsc.receive();
+        if (res.getInt("status") != 201) {
+            return false;
+        }
+        //MaJ joueur
+        Player p = this.player.get(this.mainPlayer);
+        p.setLife(res.getInt("life"));
+        p.setMaxLife(res.getInt("maxLife"));
+        p.setSpeed(res.getInt("speed"));
+        p.setBomb(res.getInt("currentNbClassicBomb"));
+        p.setMine(res.getInt("currentNbMine"));
+        p.setRemote(res.getInt("currentNbRemoteBomb"));
+        p.setMaxBomb(res.getInt("maxNbBomb"));
+        //Ajout bonus
+        if (type == Player.FIREPOWER) {
+            p.setFirepower(p.getFirepower() + 1);
+        } else if (type == Player.MAJOR) {
+            System.out.println("Get major");
+            //p.setMajor(true); Inutile le serveur n'envoi pas les infos de degats pendant la durée du Major
+        }
+        return true;
+    }
+
+    public void updateMap(String mapContent) {
+        String map[][] = this.parseMap(mapContent);
+        //Compare les 2 cartes
+        for (int i = 0; i < height; i++) {
+            for (int j = 0; j < width; j++) {
+                if (this.map[j][i].equals("*")) {
+                    this.map[j][i] = map[j][i];
+                }
+            }
+        }
+    }
+
+    public void updateLife(int newLife) {
+        Player p = this.player.get(this.mainPlayer);
+        //Si non invincible
+        if (!p.isMajor()) {
+            if (newLife > 0) {
+                p.setLife(newLife);
+            } else {
+                BomberStudent.end();
+            }
+        }
+    }
+
+    public boolean quit(int id) {
+        //Recup joueur
+        Player p = this.player.get(id);
+        if (p == null) {
+            return false;
+        }
+        //Le retire
+        this.player.remove(id);
+        this.map[p.getX()][p.getY()] = "_";
+        return true;
+    }
+
+    /* --- Méthodes affichage --- */
+    public String toHtml() {
+        String html = "<!DOCTYPE html><html><head><link rel=\"stylesheet\" type=\"text/css\" href=\"file:" + System.getProperty("user.dir") + "/file/css/map.css\"></head><body><div id=\"game\"><table><tbody>";
+        for (int i = 0; i < height; i++) {
+            html += "<tr>";
+            for (int j = 0; j < width; j++) {
+                html += "<td><img src=\"file:" + System.getProperty("user.dir") + "/";
+                switch (this.map[j][i].charAt(0)) {
+                    case '_':
+                        html += "file/sprite/sol.png";
+                        break;
+                    case '-':
+                        html += "file/sprite/limite.png";
+                        break;
+                    case '*':
+                        html += "file/sprite/mur.png";
+                        break;
+                    case 'b':
+                        switch (this.map[j][i]) {
+                            case "bu":
+                                html += "file/sprite/bomb_up.png";
+                                break;
+                            case "bd":
+                                html += "file/sprite/bomb_down.png";
+                                break;
+                            case "bl":
+                                html += "file/sprite/broken_leg.png";
+                                break;
+                            default:
+                                html += "file/sprite/bomb.png";
+                                break;
+                        }
+                        break;
+                    case 'm':
+                        switch (this.map[j][i]) {
+                            case "mb":
+                                html += "file/sprite/mine_bomb.png";
+                                break;
+                            default:
+                                html += "file/sprite/mine.png";
+                                break;
+                        }
+                        break;
+                    case 'r':
+                        switch (this.map[j][i]) {
+                            case "rb":
+                                html += "file/sprite/remote_bomb.png";
+                                break;
+                            default:
+                                html += "file/sprite/remote.png";
+                                break;
+                        }
+                        break;
+                    case 'c':
+                        html += "file/sprite/classic_bomb.png";
+                        break;
+                    case 'f':
+                        html += "file/sprite/fire_power.png";
+                        break;
+                    case 's':
+                        html += "file/sprite/scooter.png";
+                        break;
+                    case 'i':
+                        html += "file/sprite/major.png";
+                        break;
+                    case 'l':
+                        switch (this.map[j][i]) {
+                            case "lu":
+                                html += "file/sprite/life_up.png";
+                                break;
+                            default:
+                                html += "file/sprite/life_max.png";
+                                break;
+                        }
+                        break;
+                    case '0':
+                    case '1':
+                    case '2':
+                    case '3':
+                    case '4':
+                    case '5':
+                    case '6':
+                    case '7':
+                    case '8':
+                    case '9':
+                        Player p = this.player.get(Integer.parseInt(this.map[j][i]));
+                        if (p.main) {
+                            html += "file/sprite/player.png";
+                        } else {
+                            html += "file/sprite/other.png";
+                        }
+                        break;
+                }
+                html += "\"></td>";
+            }
+            html += "</tr>";
+        }
+        html += "</tbody></table></div></body></html>";
+        return html;
+    }
+
+    public void showMap() {
+        for (int i = 0; i < height; i++) {
+            for (int j = 0; j < width; j++) {
+                System.out.print(this.map[j][i]);
+            }
+            System.out.println("");
+        }
+    }
+
+    /* --- Getter/Setter --- */
+    public Player getPlayer(int index) {
+        return this.player.get(index);
+    }
+
+    public int getMainPlayerId() {
+        return this.mainPlayer;
+    }
+
+    public int getHeight() {
+        return this.height;
+    }
+
+    public int getWidth() {
+        return this.width;
+    }
+
+    /* --- Methodes privée --- */
+    private String[][] parseMap(String mapContent) {
+        String[][] map = new String[this.width][this.height];
+        for (int i = 0; i < this.height; i++) {
+            for (int j = 0; j < this.width; j++) {
+                map[j][i] = "" + mapContent.charAt((i * this.width) + j);
+            }
+        }
+        return map;
+    }
+
+    private int[] parseCoord(String coord) {
+        int res[] = new int[2];
+        //Cherche le separateur
+        int pos = 0;
+        while (pos < coord.length()) {
+            if (coord.charAt(pos) == ',') {
+                break;
+            }
+            pos++;
+        }
+        //Si pas de separateur
+        if (pos == coord.length()) {
+            return null;
+        }
+        //Recup les 2 string + extraction int
+        String substr1 = coord.substring(0, pos);
+        String substr2 = coord.substring(pos + 1);
+        res[0] = Integer.parseInt(substr1);
+        res[1] = Integer.parseInt(substr2);
+        return res;
+    }
+
+}

+ 305 - 0
BSWFX/src/bs/Player.java

@@ -0,0 +1,305 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bs;
+
+import bswfx.BomberStudent;
+import org.json.JSONObject;
+
+/**
+ *
+ * @author loquicom
+ */
+public class Player {
+    
+    //Deplacement
+    public static final int UP = 0;
+    public static final int LEFT = 1; 
+    public static final int DOWN = 2;
+    public static final int RIGHT = 3;
+    //Type de bombe
+    public static final int CLASSIC = 0;
+    public static final int MINE = 1;
+    public static final int REMOTE = 2;
+    //Objet
+    public static final int BOMBUP = 3;
+    public static final int BOMBDOWN = 4;
+    public static final int FIREPOWER = 5;
+    public static final int SCOOTER = 6;
+    public static final int BROKENLEG = 7;
+    public static final int MAJOR = 8;
+    public static final int LIFEUP = 9;
+    public static final int LIFEMAX = 10;
+    
+    protected boolean main;
+    protected int id;
+    protected int dir;
+    protected int x;
+    protected int y;
+    protected int life;
+    protected int maxLife;
+    protected int speed;
+    protected int maxBomb;
+    protected int bomb;
+    protected int mine;
+    protected int remote;
+    protected int firepower;
+    protected boolean major;
+    
+    public Player(int id, String pos){
+        int coord[] = parseCoord(pos);
+        //SetUp les valeurs
+        this.main = false;
+        this.id = id;
+        this.dir = RIGHT;
+        this.x = coord[0];
+        this.y = coord[1];
+    }
+    
+    public Player(JSONObject jo, String pos){
+        int coord[] = parseCoord(pos);
+        //SetUp les valeurs
+        this.main = true;
+        this.id = jo.getInt("id");
+        this.dir = RIGHT;
+        this.x = coord[0];
+        this.y = coord[1];
+        this.life = jo.getInt("life");
+        this.maxLife = jo.getInt("maxLife");
+        this.speed = jo.getInt("speed");
+        this.maxBomb = jo.getInt("maxNbBomb");
+        this.bomb = jo.getInt("currentNbClassicBomb");
+        this.mine = jo.getInt("currentNbMine");
+        this.remote = jo.getInt("currentNbRemoteBomb");
+        this.firepower = 0;
+        this.major = false;
+    }
+    
+    /* --- Méthodes --- */
+    
+    public boolean move(int dir){
+        JSONObject jo = new JSONObject();
+        switch(dir){
+            case UP:
+                jo.put("move", "up");
+                return BomberStudent.bsc.send("POST", "player/move", jo);
+            case LEFT:
+                jo.put("move", "left");
+                return BomberStudent.bsc.send("POST", "player/move", jo);      
+            case DOWN:
+                jo.put("move", "down");
+                return BomberStudent.bsc.send("POST", "player/move", jo);
+            case RIGHT:
+                jo.put("move", "right");
+                return BomberStudent.bsc.send("POST", "player/move", jo);
+            default:
+                return false;
+        }
+    }
+    
+    public boolean attack(int type){
+        JSONObject jo = new JSONObject();
+        //Calcul position
+        int x = this.x;
+        int y = this.y;
+        switch(this.dir){
+            case UP:
+                if(y == 0){
+                    return false;
+                }
+                y--;
+                break;
+            case LEFT:
+                if(x == 0){
+                    return false;
+                }
+                x--;
+                break;   
+            case DOWN:
+                if(y == BomberStudent.game.getHeight() - 1){
+                    return false;
+                }
+                y++;
+                break;
+            case RIGHT:
+                if(x == BomberStudent.game.getWidth() - 1){
+                    return false;
+                }
+                x++;
+                break;
+            default:
+                return false;
+        }
+        jo.put("pos", x + "," + y);
+        //Regarde le type
+        switch(type){
+            case CLASSIC:
+                jo.put("class", "classic");
+                break;
+            case MINE:
+                jo.put("class", "mine");
+                break;
+            case REMOTE:
+                jo.put("class", "remote");
+                break;
+            default:
+                return false;
+        }
+        //Si il a un bonus
+        jo.put("bonus", this.firepower > 0);
+        //Envoi
+        if(!BomberStudent.bsc.send("POST", "attack/bomb", jo)){
+            return false;
+        }
+        JSONObject res = BomberStudent.bsc.receive();
+        if(res.getInt("status") == 201){
+            if(type == MINE){
+                BomberStudent.game.newBomb(MINE, x + "," + y);
+                BomberStudent.updateWindow();
+            }
+            return true;
+        }
+        return false;
+    }
+
+    /* --- Getter/Setter --- */
+    
+    public boolean isMain() {
+        return main;
+    }
+
+    public int getId() {
+        return id;
+    }
+    
+    public int getDir(){
+        return dir;
+    }
+
+    public int getX() {
+        return x;
+    }
+
+    public int getY() {
+        return y;
+    }
+
+    public int getLife() {
+        return life;
+    }
+
+    public int getMaxLife() {
+        return maxLife;
+    }
+
+    public int getSpeed() {
+        return speed;
+    }
+
+    public int getMaxBomb() {
+        return maxBomb;
+    }
+
+    public int getBomb() {
+        return bomb;
+    }
+
+    public int getMine() {
+        return mine;
+    }
+
+    public int getRemote() {
+        return remote;
+    }
+
+    public int getFirepower() {
+        return firepower;
+    }
+
+    public boolean isMajor() {
+        return major;
+    }
+
+    public void setMain(boolean main) {
+        this.main = main;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+    
+    public void setDir(int dir){
+        this.dir = dir;
+    }
+
+    public void setX(int x) {
+        this.x = x;
+    }
+
+    public void setY(int y) {
+        this.y = y;
+    }
+
+    public void setLife(int life) {
+        this.life = life;
+    }
+
+    public void setMaxLife(int maxLife) {
+        this.maxLife = maxLife;
+    }
+
+    public void setSpeed(int speed) {
+        this.speed = speed;
+    }
+
+    public void setMaxBomb(int maxBomb) {
+        this.maxBomb = maxBomb;
+    }
+
+    public void setBomb(int bomb) {
+        this.bomb = bomb;
+    }
+
+    public void setMine(int mine) {
+        this.mine = mine;
+    }
+
+    public void setRemote(int remote) {
+        this.remote = remote;
+    }
+
+    public void setFirepower(int firepower) {
+        this.firepower = firepower;
+    }
+
+    public void setMajor(boolean major) {
+        this.major = major;
+    }
+    
+    /* --- Methodes privées --- */
+    
+    private int[] parseCoord(String coord){
+        int res[] = new int[2];
+        //Cherche le separateur
+        int pos = 0;
+        while(pos < coord.length()){
+            if(coord.charAt(pos) == ','){
+                break;
+            }
+            pos++;
+        }
+        //Si pas de separateur
+        if(pos == coord.length()){
+            return null;
+        }
+        //Recup les 2 string + extraction int
+        String substr1 = coord.substring(0, pos);
+        String substr2 = coord.substring(pos + 1);
+        res[0] = Integer.parseInt(substr1);
+        res[1] = Integer.parseInt(substr2);
+        return res;
+    }
+    
+}

+ 131 - 0
BSWFX/src/bswfx/BomberStudent.java

@@ -0,0 +1,131 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx;
+
+import bswfx.handler.*;
+import bs.Game;
+import org.json.JSONArray;
+import org.json.JSONObject;
+import rsx.BomberStudentClient;
+import wfx.WebFx;
+
+/**
+ *
+ * @author Loquicom <contact@loquicom.fr>
+ */
+public class BomberStudent {
+    
+    public static WebFx wfx = new WebFx();
+    
+    public static BomberStudentClient bsc = new BomberStudentClient();
+    
+    public static Game game;
+
+    /**
+     * @param args the command line arguments
+     */
+    public static void main(String[] args) {
+        //Change passage de ligne du systeme
+        System.setProperty("line.separator", "\n");
+        
+        //Variables
+        JSONObject param;
+        JSONObject res;
+        
+        //Lancement Thread affichage
+        Thread twfx = new Thread(wfx);
+        twfx.start();
+        
+        //Ajout handler
+        bsc.addHandler("server/end", new HandlerServerEnd());
+        bsc.addHandler("player/position/update", new HandlerPlayerMove());
+        bsc.addHandler("game/newplayer", new HandlerPlayerJoin());
+        bsc.addHandler("game/quit", new HandlerPlayerQuit());
+        bsc.addHandler("attack/newbomb", new HandlerAttackBomb());
+        bsc.addHandler("attack/explose", new HandlerAttackExplose());
+        bsc.addHandler("attack/affect", new HandlerAttackAffect());
+        bsc.addHandler("player/major/end", new HandlerMajorEnd());
+        
+        //Recherche serveur actif
+        int nbRes = bsc.findServer();
+        if (nbRes == 0) {
+            System.err.println("Aucun serveur");
+            wfx.end();
+            System.exit(0);
+        }
+        System.out.println("Nombre serveur : " + nbRes);
+        
+        //Connexion serveur et recup liste des games
+        bsc.selectServer(0);
+        bsc.send("GET", "game/list");
+        res = bsc.receive();
+        
+        //Verif si une game de test existe
+        boolean gameTest = false;
+        if(res.getInt("numberGameList") != 0){
+            JSONArray ja = res.getJSONArray("games");
+            for(int i = 0; i < ja.length(); i++){
+                JSONObject jo = ja.getJSONObject(i);
+                if(jo.getString("name").equals("gameTest")){
+                    gameTest = true;
+                    break;
+                }
+            }
+        }
+        //Si pas de game creation
+        if(!gameTest){
+            //Verif que la mapTest est présente
+            JSONArray ja = res.getJSONArray("maps");
+            boolean present = false;
+            for(int i = 0; i < ja.length(); i++){
+                if(ja.getString(i).equals("mapTest")){
+                    present = true;
+                    break;
+                }
+            }
+            if(!present){
+                System.err.println("La map de test n'est pas présente sur le serveur");
+                end();
+            }
+            //Creation game
+            param = new JSONObject();
+            param.put("name", "gameTest");
+            param.put("map", "mapTest");
+            bsc.send("POST", "game/create", param);
+            res = bsc.receive();
+            if(res.getInt("status") != 201){
+                System.err.println("Impossible de créer la game");
+                end();
+            }
+        } 
+        //Sinon on rejoint
+        else {
+            param = new JSONObject();
+            param.put("name", "gameTest");
+            bsc.send("POST", "game/join", param);
+            res = bsc.receive();
+            if(res.getInt("status") != 201){
+                System.err.println("Impossible de rejoindre la game");
+                end();
+            }
+        }
+        //Creation game
+        game = new Game(res);
+        updateWindow();
+        ScreenManager.setScreen(ScreenManager.GAME_SCREEN);
+    }
+    
+    public static void updateWindow(){
+        wfx.loadHtml(game.toHtml());
+    }
+    
+    public static void end(){
+        wfx.end();
+        bsc.close();
+        System.exit(0);
+    }
+
+}

+ 57 - 0
BSWFX/src/bswfx/KeyHandler.java

@@ -0,0 +1,57 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx;
+
+import bs.Player;
+import javafx.scene.input.KeyEvent;
+
+/**
+ *
+ * @author Loquicom <contact@loquicom.fr>
+ */
+public class KeyHandler {
+
+    public static void manage(KeyEvent ke) {
+        switch (ScreenManager.getScreen()) {
+            case ScreenManager.GAME_SCREEN:
+                //System.out.println("Key : " + ke.getText());
+                gameEvent(ke);
+                break;
+        }
+    }
+
+    protected static void gameEvent(KeyEvent ke) {
+        //Recup le joueur principale
+        Player p = BomberStudent.game.getPlayer(BomberStudent.game.getMainPlayerId());
+        switch (ke.getText()) {
+            case "z":
+                p.move(Player.UP);
+                break;
+            case "q":
+                p.move(Player.LEFT);
+                break;
+            case "s":
+                p.move(Player.DOWN);
+                break;
+            case "d":
+                p.move(Player.RIGHT);
+                break;
+            case "a":
+                p.attack(Player.CLASSIC);
+                break;
+            case "e":
+                //p.attack(Player.MINE);
+                break;
+            case "r":
+                p.attack(Player.REMOTE);
+                break;
+            case "f":
+                BomberStudent.bsc.send("POST", "attack/remote/go");
+                break;
+        }
+    }
+
+}

+ 29 - 0
BSWFX/src/bswfx/ScreenManager.java

@@ -0,0 +1,29 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx;
+
+/**
+ *
+ * @author loquicom
+ */
+public class ScreenManager {
+    
+    public static final int LOADING_SCREEN = 0;
+    public static final int GAME_SCREEN = 1;
+    
+    protected static int screen = LOADING_SCREEN;
+    
+    public static int getScreen(){
+        return ScreenManager.screen;
+    }
+    
+    public static void setScreen(int screen){
+        if(!( screen != LOADING_SCREEN && screen != GAME_SCREEN )){
+            ScreenManager.screen = screen;
+        }
+    }
+    
+}

+ 29 - 0
BSWFX/src/bswfx/handler/HandlerAttackAffect.java

@@ -0,0 +1,29 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+import bswfx.BomberStudent;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerAttackAffect implements BomberStudentHandler{
+
+    @Override
+    public boolean handle(JSONObject json) {
+        //Verif param
+        if(!( json.has("life") )){
+            return false;
+        }
+        //MaJ la vie
+        BomberStudent.game.updateLife(json.getInt("life"));
+        return true;
+    }
+    
+}

+ 47 - 0
BSWFX/src/bswfx/handler/HandlerAttackBomb.java

@@ -0,0 +1,47 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import bs.Player;
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+import bswfx.BomberStudent;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerAttackBomb implements BomberStudentHandler{
+
+    @Override
+    public boolean handle(JSONObject json) {
+        //Verif json
+        if(!( json.has("pos") && json.has("class") )){
+            return false;
+        }
+        //Recup le type
+        int type;
+        switch(json.getString("class")){
+            case "classic":
+                type = Player.CLASSIC;
+                break;
+            case "mine":
+                return true;
+            case "remote":
+                type = Player.REMOTE;
+                break;
+            default:
+                return false;
+        }
+        //Ajoute sur la map
+        if(BomberStudent.game.newBomb(type, json.getString("pos"))){
+            BomberStudent.updateWindow();
+            return true;
+        }
+        return false;
+    }
+    
+}

+ 92 - 0
BSWFX/src/bswfx/handler/HandlerAttackExplose.java

@@ -0,0 +1,92 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import bs.Player;
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+import bswfx.BomberStudent;
+import org.json.JSONArray;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerAttackExplose implements BomberStudentHandler {
+
+    @Override
+    public boolean handle(JSONObject json) {
+        //Verif param
+        if (!(json.has("pos") && json.has("map"))) {
+            return false;
+        }
+        //Retire les bombes exlposées
+        BomberStudent.game.removeBomb(json.getString("pos"));
+        if (json.has("chain")) {
+            JSONArray ja = json.getJSONArray("chain");
+            for (int i = 0; i < ja.length(); i++) {
+                JSONObject jo = ja.getJSONObject(i);
+                BomberStudent.game.removeBomb(jo.getString("pos"));
+            }
+        }
+        //Met à jour la map
+        BomberStudent.game.updateMap(json.getString("map"));
+        //Ajoute les bombes / bonus
+        if (json.has("bomb")) {
+            JSONArray ja = json.getJSONArray("bomb");
+            for (int i = 0; i < ja.length(); i++) {
+                JSONObject jo = ja.getJSONObject(i);
+                switch (jo.getString("type")) {
+                    case "classic":
+                        BomberStudent.game.newObject(Player.CLASSIC, jo.getString("pos"));
+                        break;
+                    case "mine":
+                        BomberStudent.game.newObject(Player.MINE, jo.getString("pos"));
+                        break;
+                    case "remote":
+                        BomberStudent.game.newObject(Player.REMOTE, jo.getString("pos"));
+                        break;
+                }
+            }
+        }
+        if (json.has("bonusMalus")) {
+            JSONArray ja = json.getJSONArray("bonusMalus");
+            for (int i = 0; i < ja.length(); i++) {
+                JSONObject jo = ja.getJSONObject(i);
+                switch (jo.getString("type")) {
+                    case "bomb_up":
+                        BomberStudent.game.newObject(Player.BOMBUP, jo.getString("pos"));
+                        break;
+                    case "bomb_down":
+                        BomberStudent.game.newObject(Player.BOMBDOWN, jo.getString("pos"));
+                        break;
+                    case "fire_power":
+                        BomberStudent.game.newObject(Player.FIREPOWER, jo.getString("pos"));
+                        break;
+                    case "scooter":
+                        BomberStudent.game.newObject(Player.SCOOTER, jo.getString("pos"));
+                        break;
+                    case "broken_legs":
+                        BomberStudent.game.newObject(Player.BROKENLEG, jo.getString("pos"));
+                        break;
+                    case "major":
+                        BomberStudent.game.newObject(Player.MAJOR, jo.getString("pos"));
+                        break;
+                    case "life_up":
+                        BomberStudent.game.newObject(Player.LIFEUP, jo.getString("pos"));
+                        break;
+                    case "life_max":
+                        BomberStudent.game.newObject(Player.LIFEMAX, jo.getString("pos"));
+                        break;
+                }
+            }
+        }
+        //MaJ affichage
+        BomberStudent.updateWindow();
+        return true;
+    }
+
+}

+ 23 - 0
BSWFX/src/bswfx/handler/HandlerMajorEnd.java

@@ -0,0 +1,23 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerMajorEnd implements BomberStudentHandler{
+
+    @Override
+    public boolean handle(JSONObject json) {
+        System.out.println("Fin major");
+        return true;
+    }
+    
+}

+ 30 - 0
BSWFX/src/bswfx/handler/HandlerPlayerJoin.java

@@ -0,0 +1,30 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+import bswfx.BomberStudent;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerPlayerJoin implements BomberStudentHandler{
+
+    @Override
+    public boolean handle(JSONObject json) {
+        //Verif param
+        if(!( json.has("id") && json.has("pos") )){
+            return false;
+        }
+        //Ajout
+        BomberStudent.game.join(json.getInt("id"), json.getString("pos"));
+        BomberStudent.updateWindow();
+        return true;
+    }
+    
+}

+ 51 - 0
BSWFX/src/bswfx/handler/HandlerPlayerMove.java

@@ -0,0 +1,51 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import bs.Player;
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+import bswfx.BomberStudent;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerPlayerMove implements BomberStudentHandler{
+
+    @Override
+    public boolean handle(JSONObject json) {
+        //Verif param
+        if(!( json.has("player") && json.has("dir") )){
+            return false;
+        }
+        //Lecture direction
+        int dir;
+        switch(json.getString("dir")){
+            case "up":
+                dir = Player.UP;
+                break;
+            case "left":
+                dir = Player.LEFT;
+                break;
+            case "down":
+                dir = Player.DOWN;
+                break;
+            case "right":
+                dir = Player.RIGHT;
+                break;
+            default:
+                return false;
+        }
+        //Deplacement
+        if(BomberStudent.game.move(json.getInt("player"), dir)){
+            BomberStudent.updateWindow();
+            return true;
+        }
+        return false;
+    }
+    
+}

+ 32 - 0
BSWFX/src/bswfx/handler/HandlerPlayerQuit.java

@@ -0,0 +1,32 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+import bswfx.BomberStudent;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerPlayerQuit implements BomberStudentHandler{
+
+    @Override
+    public boolean handle(JSONObject json) {
+        //Verif param
+        if(!( json.has("player") )){
+            return false;
+        }
+        //Retire le joueur
+        if(BomberStudent.game.quit(json.getInt("player"))){
+            BomberStudent.updateWindow();
+            return true;
+        }
+        return false;
+    }
+    
+}

+ 24 - 0
BSWFX/src/bswfx/handler/HandlerServerEnd.java

@@ -0,0 +1,24 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package bswfx.handler;
+
+import org.json.JSONObject;
+import rsx.BomberStudentHandler;
+import bswfx.BomberStudent;
+
+/**
+ *
+ * @author loquicom
+ */
+public class HandlerServerEnd implements BomberStudentHandler{
+
+    @Override
+    public boolean handle(JSONObject json) {
+        BomberStudent.end();
+        return true;
+    }
+    
+}

+ 216 - 0
BSWFX/src/rsx/BomberStudentClient.java

@@ -0,0 +1,216 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package rsx;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.ArrayList;
+import java.util.HashMap;
+import org.json.JSONException;
+import org.json.JSONObject;
+import rsx.tcp.TcpClient;
+import rsx.udp.Broadcast;
+
+/**
+ * Connexion à un server BomberStudent
+ *
+ * @author Arthur Brandao
+ */
+public class BomberStudentClient {
+
+    /**
+     * Port pour le boradcast UDP
+     */
+    protected int portUdp;
+
+    /**
+     * Port pour la socket TCP
+     */
+    protected int portTcp;
+
+    /**
+     * Class pour broadcast
+     */
+    protected Broadcast finder;
+
+    /**
+     * Class pour le client TCP
+     */
+    protected TcpClient socket;
+
+    /**
+     * Si le client est conecter à un serveur en TCP
+     */
+    protected boolean connect;
+
+    /**
+     * Class de gestion des requetes serveurs
+     */
+    protected BomberStudentRequest request;
+
+    /**
+     * Liste des handlers pour gerer les requetes du serveur
+     */
+    protected HashMap<String, BomberStudentHandler> handlers = new HashMap<>();
+
+    /* --- Constructeurs --- */
+    /**
+     * Creation d'un client BomberStudent Le port 18624 est utilisé pour le
+     * broadcast udp Le port 18642 est utilisé pour la socket TCP
+     */
+    public BomberStudentClient() {
+        this.portUdp = 18624;
+        this.portTcp = 18642;
+        this.finder = new Broadcast(this.portUdp);
+    }
+
+    /**
+     * Creation d'un client BomberStudent
+     *
+     * @param portUdp Le port pour le broadcast UDP
+     * @param portTcp Le port pour la socket TCP
+     */
+    public BomberStudentClient(int portUdp, int portTcp) {
+        this.portUdp = portUdp;
+        this.portTcp = portTcp;
+        this.finder = new Broadcast(this.portUdp);
+    }
+
+    /* --- Methodes --- */
+    /**
+     * Ajoute un handler
+     *
+     * @param ressource Le nom de la ressource associè au handler
+     * @param handler Le handler
+     */
+    public void addHandler(String ressource, BomberStudentHandler handler) {
+        this.handlers.put(ressource, handler);
+    }
+
+    /**
+     * Cherche un serveur par broadcast
+     *
+     * @return Le nombre de serveur trouvé
+     */
+    public int findServer() {
+        this.finder.search("i'm a bomberstudent server");
+        return this.finder.getServers().size();
+    }
+
+    /**
+     * Selectionne un serveur pour s'y connecter
+     *
+     * @param index Le numero du serveur dans la liste
+     * @return Reussite
+     */
+    public boolean selectServer(int index) {
+        ArrayList<InetAddress> serv = this.finder.getServers();
+        if (!(index >= 0 && index < serv.size())) {
+            System.err.println("Index invalide");
+            return false;
+        }
+        //Lancement gestionnaire des requetes serveur
+        try {
+            this.request = new BomberStudentRequest(serv.get(index), this.portTcp + 1, handlers);
+            this.request.start();
+        } catch (IOException ex) {
+            return false;
+        }
+        //Creation socket d'envoi
+        this.socket = new TcpClient(serv.get(index), this.portTcp);
+        if (this.socket.connect()) {
+            this.connect = true;
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * Envoi requete sur le serveur
+     *
+     * @param method Methode d'envoi (POST ou GET)
+     * @param ressource Ressource demandée
+     * @return Reussite
+     */
+    public boolean send(String method, String ressource) {
+        return this.send(method, ressource, null);
+    }
+
+    /**
+     * Envoi requete sur le serveur
+     *
+     * @param method Methode d'envoi (POST ou GET)
+     * @param ressource Ressource demandée
+     * @param param Parametre JSON à envoyer au serveur
+     * @return Reussite
+     */
+    public boolean send(String method, String ressource, JSONObject param) {
+        //Verif que la methode existe
+        method = method.toUpperCase();
+        if (!method.equals("POST") && !method.equals("GET")) {
+            return false;
+        }
+        //Creation message pour envoi
+        String msg = method + " " + ressource;
+        if (param != null) {
+            msg += "\n" + param.toString();
+        }
+        //Envoi
+        this.socket.send(msg);
+        return true;
+    }
+
+    /**
+     * Attend une reponse du serveur
+     *
+     * @return La reponse analysée
+     */
+    public JSONObject receive() {
+        String msg = "";
+        /*do {
+            if(!msg.equals("")){
+                msg += "\n";
+            }
+            msg += this.socket.receive();
+        } while (msg.charAt(msg.length() - 1) != '}');*/
+        msg = this.socket.receive();
+        //System.out.println("Message : " + msg);
+        try {
+            return new JSONObject(msg);
+        } catch (JSONException ex) {
+            System.err.println("La reponse n'est pas en JSON : " + ex.getMessage());
+            return null;
+        }
+    }
+
+    /**
+     * Ferme la connexion
+     *
+     * @return Reussite
+     */
+    public boolean close() {
+        //Si connecté à un serveur
+        if (this.connect) {
+            this.connect = false;
+            //Avertit le serveur
+            this.send("POST", "client/end");
+            //Coupe le thread
+            this.request.interrupt();
+            //Verif que le thread est bien arréte
+            try {
+                Thread.sleep(3000);
+                if (this.request.isAlive()) {
+                    System.err.println("Imposible de tuer le thread de gestion des requetes");
+                }
+            } catch (InterruptedException ex) {
+
+            }
+            return this.socket.close();
+        }
+        return true;
+    }
+
+}

+ 13 - 0
BSWFX/src/rsx/BomberStudentHandler.java

@@ -0,0 +1,13 @@
+package rsx;
+
+import org.json.JSONObject;
+
+/**
+ * Interface des gestionnaires de requete du serveur
+ * @author Arthur Brandao
+ */
+public interface BomberStudentHandler {
+    
+    public boolean handle(JSONObject json);
+    
+}

+ 98 - 0
BSWFX/src/rsx/BomberStudentRequest.java

@@ -0,0 +1,98 @@
+package rsx;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.util.HashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import org.json.JSONException;
+import org.json.JSONObject;
+import rsx.tcp.TcpClient;
+
+/**
+ * Analyse les requetes emises par le serveur
+ *
+ * @author Arthur Brandao
+ */
+public class BomberStudentRequest extends Thread {
+
+    /**
+     * Indique si on coupe la boucle
+     */
+    private final AtomicBoolean running = new AtomicBoolean(true);
+
+    /**
+     * Connexion au serveur
+     */
+    protected TcpClient socket;
+
+    /**
+     * Liste des handler à appeler
+     */
+    protected HashMap<String, BomberStudentHandler> handlers;
+
+    /* --- Constructeur --- */
+    public BomberStudentRequest(InetAddress adr, int port, HashMap<String, BomberStudentHandler> handlers) throws IOException {
+        this.handlers = handlers;
+        this.socket = new TcpClient(adr, port);
+        this.socket.timeout(2);
+        if (!this.socket.connect()) {
+            System.err.println("Impossible de créer la socket");
+            throw new IOException("Connexion impossible");
+        }
+    }
+
+    /* --- Surcharge --- */
+    @Override
+    public void interrupt() {
+        this.running.set(false);
+        super.interrupt();
+    }
+
+    @Override
+    public void run() {
+        //Tant qu'actif
+        while (this.running.get()) {
+            //Attente contact serveur
+            String entete = this.socket.receive();         
+            //Si rien on continue
+            if (entete == null) {
+                continue;
+            }
+            //On recup les parametres
+            String param = this.socket.receive();
+            //Si rien on continue
+            if (param == null) {
+                continue;
+            }
+            //Regarde la requete
+            String[] requete = entete.split(" ");
+            if (requete.length < 2) {
+                continue;
+            }
+            if (!requete[0].equals("POST")) {
+                continue;
+            }
+            //Regarde si il existe un handler
+            String ressource = requete[1];
+            if (!this.handlers.containsKey(ressource)) {
+                continue;
+            }
+            //Recup json
+            JSONObject json = null;
+            try {
+                json = new JSONObject(param);
+            } catch (JSONException ex) {
+                System.err.println("La requete n'est pas en JSON : " + ex.getMessage());
+                continue;
+            }
+            //Appel handler
+            BomberStudentHandler handler = this.handlers.get(ressource);
+            if(!handler.handle(json)){
+                System.err.println("Erreur pendant l'execution du handler " + ressource);
+            }
+        }
+        //Fermeture socket
+        this.socket.close();
+    }
+
+}

+ 177 - 0
BSWFX/src/rsx/tcp/TcpClient.java

@@ -0,0 +1,177 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package rsx.tcp;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.InetAddress;
+import java.net.Socket;
+import java.net.UnknownHostException;
+
+/**
+ *
+ * @author loquicom
+ */
+public class TcpClient {
+
+    /**
+     * Adresse du serveur
+     */
+    protected InetAddress adr;
+
+    /**
+     * Port du serveur
+     */
+    protected int port;
+
+    /**
+     * Socket TCP
+     */
+    protected Socket socket;
+
+    /**
+     * Timeout de la socket (en milisecondes)
+     */
+    protected int timeout = 0;
+
+    /**
+     * Flux d'entrée
+     */
+    protected BufferedReader input;
+
+    /**
+     * Flux de sorti
+     */
+    protected PrintWriter output;
+
+    /* --- Constructeurs --- */
+    /**
+     * Creation d'un client TCP
+     *
+     * @param ip L'ip du serveur
+     * @param port Le port du serveur
+     * @throws UnknownHostException
+     */
+    public TcpClient(String ip, int port) throws UnknownHostException {
+        this.adr = InetAddress.getByName(ip);
+        this.port = port;
+    }
+
+    /**
+     * Creation d'un client TCP
+     *
+     * @param adr L'adresse du serveur
+     * @param port Le port du serveur
+     */
+    public TcpClient(InetAddress adr, int port) {
+        this.adr = adr;
+        this.port = port;
+    }
+
+    /* --- Methodes --- */
+    /**
+     * Temps avant timeout du receive (qui retournera false)
+     * @param second Le temps en senconde
+     */
+    public void timeout(int second) {
+        this.timeout = second * 1000;
+    }
+
+    /**
+     * Retire un timeout
+     */
+    public void notimeout() {
+        this.timeout = 0;
+    }
+
+    /**
+     * Connexion au serveur
+     *
+     * @return Reussite
+     */
+    public boolean connect() {
+        try {
+            this.socket = new Socket(this.adr, this.port);
+            //Si un timeout
+            if (this.timeout > 0) {
+                this.socket.setSoTimeout(this.timeout);
+            }
+            //Ouverture flux
+            this.input = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
+            this.output = new PrintWriter(this.socket.getOutputStream());
+        } catch (IOException ex) {
+            System.err.println("Impossible de se connecter au serveur : " + ex.getMessage());
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Envoi message au serveur
+     *
+     * @param msg Le message
+     * @return Reussite
+     */
+    public boolean send(String msg) {
+        output.print(msg);
+        output.flush();
+        return true;
+    }
+
+    /**
+     * Reception d'un message du serveur
+     *
+     * @return Le message ou null en cas d'erreur
+     */
+    public String receive() {
+        try {
+            return input.readLine();
+        } catch (IOException ex) {
+            //Si pas l'exception du timeout
+            if (!ex.getMessage().equals("Read timed out")) {
+                System.err.println("Impossible de lire : " + ex.getMessage() + " ");
+            }
+            return null;
+        }
+    }
+
+    /**
+     * Ferme la connexion au serveur
+     *
+     * @return Reussite
+     */
+    public boolean close() {
+        try {
+            input.close();
+            output.close();
+            socket.close();
+        } catch (IOException ex) {
+            System.err.println("Impossible de de fermer le client : " + ex.getMessage());
+            return false;
+        }
+        return true;
+    }
+
+    /* --- Getter/Setter --- */
+    public InetAddress getAdr() {
+        return adr;
+    }
+
+    public void setAdr(InetAddress adr) {
+        this.adr = adr;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+}

+ 168 - 0
BSWFX/src/rsx/udp/Broadcast.java

@@ -0,0 +1,168 @@
+package rsx.udp;
+
+import java.io.IOException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetAddress;
+import java.net.SocketException;
+import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
+import java.util.ArrayList;
+
+/**
+ * Broadcast pour trouver un serveur
+ *
+ * @author Arthur Brandao
+ */
+public class Broadcast {
+
+    /**
+     * Port pour la socket UDP
+     */
+    protected int port;
+    
+    /**
+     * Le message à envoyer
+     */
+    protected String msg;
+    
+    /**
+     * TImeout
+     */
+    protected int timeout = 5000;
+    
+    /**
+     * Taille du buffer pour l'envoi
+     */
+    protected int bufferSize = 1024;
+    
+    /**
+     * Liste des serveurs ayant répondu
+     */
+    protected ArrayList<InetAddress> servers = new ArrayList<>();
+    
+    /* --- Constructeurs --- */
+
+    /**
+     * Creation d'un Broadcast
+     * @param port Le port à utiliser
+     */
+    public Broadcast(int port) {
+        this.port = port;
+        this.msg = "looking for bomberstudent servers";
+    }
+
+    /**
+     * Creation d'un Broadcast
+     * @param port Le port à utiliser
+     * @param msg Le message à envoyer
+     */
+    public Broadcast(int port, String msg) {
+        this.port = port;
+        this.msg = msg;
+    }
+    
+    /* --- Methodes --- */
+
+    /**
+     * Cherche les serveurs
+     * @param answer La reponse attendu du serveur
+     * @return Reussite
+     */
+    public boolean search(String answer) {
+        //Creation socket
+        DatagramSocket socket = null;
+        try {
+            socket = new DatagramSocket();
+            socket.setBroadcast(true);
+            socket.setSoTimeout(this.timeout);
+        } catch (SocketException ex) {
+            System.err.println("Erreur creation de la socket : " + ex.getMessage());
+            return false;
+        }
+
+        //Envoi message
+        byte[] buffer = this.msg.getBytes();
+        DatagramPacket packet;
+        try {
+            packet = new DatagramPacket(buffer, buffer.length, InetAddress.getByName("255.255.255.255"), this.port);
+            socket.send(packet);
+        } catch (UnknownHostException ex) {
+            System.err.println("Erreur hote inconnu : " + ex.getMessage());
+            return false;
+        } catch (IOException ex) {
+            System.err.println("Erreur IO : " + ex.getMessage());
+            return false;
+        }
+        
+        //Attente reponse
+        try {
+            while (true) {
+                //Recepetion reponse
+                byte[] tampon = new byte[this.bufferSize];
+                DatagramPacket dp = new DatagramPacket(tampon, tampon.length);
+                socket.receive(dp);
+                String reponse = new String(dp.getData(), 0, dp.getLength());
+                //Analyse reponse
+                if(reponse.equals(answer)){
+                    this.servers.add(dp.getAddress());
+                }
+            }
+        } catch (SocketTimeoutException ex) {
+            //Rien on fini la methode
+        } catch (IOException ex) {
+            System.err.println("Erreur IO : " + ex.getMessage());
+            return false;
+        }
+        
+        //Fin
+        socket.close();
+        return true;
+    }
+    
+    /**
+     * Vide la liste des serveurs
+     */
+    public void clean(){
+        this.servers = new ArrayList<>();
+    }
+    
+    /* --- Getter/Setter --- */
+
+    public int getPort() {
+        return port;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public int getTimeout() {
+        return timeout;
+    }
+
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
+
+    public int getBufferSize() {
+        return bufferSize;
+    }
+
+    public void setBufferSize(int bufferSize) {
+        this.bufferSize = bufferSize;
+    }
+    
+    public ArrayList<InetAddress> getServers(){
+        return new ArrayList<>(this.servers);
+    }
+
+}

+ 192 - 0
BSWFX/src/wfx/WebFx.java

@@ -0,0 +1,192 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package wfx;
+
+import bswfx.BomberStudent;
+import bswfx.KeyHandler;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import javafx.application.Application;
+import javafx.application.Platform;
+import javafx.scene.Scene;
+import javafx.scene.image.Image;
+import javafx.scene.layout.VBox;
+import javafx.scene.web.WebView;
+import javafx.stage.Stage;
+
+/**
+ *
+ * @author Loquicom <contact@loquicom.fr>
+ */
+public class WebFx extends Application implements Runnable {
+    
+    public static Stage stage;
+    
+    protected int width = 800;
+    protected int height = 800;
+    protected String title = "WFX";
+    protected String html = "<div style=\"margin-top: 48vh\"><h1 style=\"font-family: Arial\"><div style=\"text-align: center\">Loading...</div></h1></div>";
+    protected String icon = null;
+    
+    public WebFx() {
+        WebFxConfig config = WebFxConfig.getInstance();
+        config.setUpWebFx(this);
+    }
+    
+    public WebFx(String configPath) {
+        WebFxConfig config = WebFxConfig.getInstance(configPath);
+        config.setUpWebFx(this);
+    }
+    
+    /* --- Getter/Setter --- */
+    
+    public void setSize(int width, int height) {
+        this.width = width;
+        this.height = height;
+    }
+    
+    public void setTitle(String title){
+        this.title = title;
+    }
+    
+    public void setHtml(String html){
+        this.html = html;
+    }
+    
+    public void setHtmlFile(String htmlFile){
+        String content = this.fileGetContent(htmlFile);
+        if(content != null){
+            this.html = content;
+        }
+    }
+    
+    public void setIcon(String path){
+        this.icon = "file:" + path;
+    }
+    
+    /* --- Méthodes JavaFx --- */
+    
+    public void launch() {
+        Application.launch();
+    }
+    
+    public void end() {
+        Platform.exit();
+    }
+    
+    @Override
+    public void start(final Stage stage) {
+        //Creation element graphiques
+        WebView wv = new WebView();
+        VBox root = new VBox();
+
+        //Modification taille
+        wv.setMinWidth(this.width);
+        wv.setMinHeight(this.height);
+        root.setMinWidth(this.width);
+        root.setMinHeight(this.height);
+
+        //Recup le stage
+        WebFx.stage = stage;
+
+        //Charge page par defaut
+        wv.getEngine().loadContent(this.html);
+
+        //Ajoute la Webview à la Vbox
+        root.getChildren().add(wv);
+
+        //Modifie le style de la VBox
+        /*root.setStyle("-fx-padding: 10;"
+                + "-fx-border-style: solid inside;"
+                + "-fx-border-width: 2;"
+                + "-fx-border-insets: 5;"
+                + "-fx-border-radius: 5;"
+                + "-fx-border-color: blue;");*/
+
+        //Creation et ajout de la scene
+        Scene scene = new Scene(root);
+        WebFx.stage.setScene(scene);
+        
+        //Parametrage stage
+        WebFx.stage.setTitle(title);
+        if(this.icon != null){
+            WebFx.stage.getIcons().add(new Image(this.icon));
+        }
+        
+        //Handler
+        WebFx.stage.setOnCloseRequest(event -> {
+            BomberStudent.end();
+        });
+        wv.setOnKeyPressed(keyEvent -> {
+            KeyHandler.manage(keyEvent);
+        });
+
+        //Affiche la fenetre
+        WebFx.stage.show();
+    }
+    
+    /* --- Méthodes modification fenetre --- */
+    
+    public void loadHtml(String html) {
+        Platform.runLater(new Runnable() {
+            @Override
+            public void run() {
+                VBox v = (VBox) WebFx.stage.getScene().getRoot();
+                WebView wv = (WebView) v.getChildren().get(0);
+                wv.getEngine().loadContent(html);
+            }
+        });
+    }
+    
+    public boolean loadFile(String path){
+        //Recup le contenu du fichier
+        String fileContent = this.fileGetContent(path);
+        if(fileContent == null){
+            return false;
+        }
+        //Chargement de l'html
+        this.loadHtml(fileContent);
+        return true;
+    }
+    
+    /* --- Methode Runneable --- */
+    
+    @Override
+    public void run() {
+        this.launch();
+    }
+    
+    /* --- Methodes privées --- */
+    
+    private String fileGetContent(String path){
+        //Ouverture fichier
+        File f = new File(path);
+        if(!( f.exists() && f.canRead() )){
+            return null;
+        }
+        //Lecture fichier
+        String fileContent = "";
+        try {
+            String buf;
+            BufferedReader br = new BufferedReader(new FileReader(f));
+            while((buf = br.readLine()) != null){
+               fileContent += buf;
+            }
+            br.close();
+        } catch (FileNotFoundException ex) {
+            System.err.println("Le fichier est introuvable : " + ex.getMessage());
+            return null;
+        } catch (IOException ex) {
+            System.err.println("Impossible de lire le fichier : " + ex.getMessage());
+            return null;
+        }
+        return fileContent;
+    }
+    
+}

+ 137 - 0
BSWFX/src/wfx/WebFxConfig.java

@@ -0,0 +1,137 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package wfx;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+/**
+ *
+ * @author Loquicom <contact@loquicom.fr>
+ */
+public class WebFxConfig {
+
+    private static WebFxConfig instance;
+
+    protected boolean ini = false;
+    protected String path = "file/webfx/config.json";
+    protected JSONObject json;
+
+    /* --- Singleton --- */
+    public static WebFxConfig getInstance() throws IllegalArgumentException {
+        if (instance == null) {
+            instance = new WebFxConfig();
+        }
+        return instance;
+    }
+
+    public static WebFxConfig getInstance(String path) throws IllegalArgumentException {
+        if (instance == null) {
+            instance = new WebFxConfig(path);
+        }
+        return instance;
+    }
+
+    private WebFxConfig() {
+        //Si un chemin par defaut
+        if (this.path != null) {
+            this.ini = true;
+            //Lecture fichier
+            String content = this.fileGetContent(this.path);
+            if (content == null) {
+                throw new IllegalArgumentException("Fichier introuvable");
+            }
+            //Lecture JSON
+            try {
+                this.json = new JSONObject(content);
+            } catch (JSONException ex) {
+                throw new IllegalArgumentException("JSON invalide");
+            }
+        }
+    }
+
+    private WebFxConfig(String configPath) {
+        //Verif fihchier existe
+        File f = new File(configPath);
+        if (!(f.exists() && f.canRead())) {
+            throw new IllegalArgumentException("Fichier introuvable");
+        }
+        this.ini = true;
+        this.path = configPath;
+        //Lecture fichier
+        String content = this.fileGetContent(this.path);
+        if (content == null) {
+            throw new IllegalArgumentException("Fichier introuvable");
+        }
+        //Lecture JSON
+        try {
+            this.json = new JSONObject(content);
+        } catch (JSONException ex) {
+            throw new IllegalArgumentException("JSON invalide");
+        }
+    }
+
+    /* --- Méthodes --- */
+    public void setUpWebFx(WebFx wfx) {
+        //Si pas de fichier de config
+        if(!this.ini){
+            return;
+        }
+        //Titre
+        if (this.json.has("title")) {
+            wfx.setTitle(this.json.getString("title"));
+        }
+        //HTML
+        if (this.json.has("defaultHtml")) {
+            JSONObject jo = this.json.getJSONObject("defaultHtml");
+            if (jo.getBoolean("file")) {
+                wfx.setHtmlFile(jo.getString("html"));
+            } else {
+                wfx.setHtml(jo.getString("html"));
+            }
+        }
+        //Icone
+        if (this.json.has("icon")) {
+            wfx.setIcon(this.json.getString("icon"));
+        }
+        //Dimension
+        if (this.json.has("width") && this.json.has("height")) {
+            wfx.setSize(this.json.getInt("width"), this.json.getInt("height"));
+        }
+    }
+
+    /* --- Methodes privées --- */
+    private String fileGetContent(String path) {
+        //Ouverture fichier
+        File f = new File(path);
+        if (!(f.exists() && f.canRead())) {
+            return null;
+        }
+        //Lecture fichier
+        String fileContent = "";
+        try {
+            String buf;
+            BufferedReader br = new BufferedReader(new FileReader(f));
+            while ((buf = br.readLine()) != null) {
+                fileContent += buf;
+            }
+            br.close();
+        } catch (FileNotFoundException ex) {
+            System.err.println("Le fichier est introuvable : " + ex.getMessage());
+            return null;
+        } catch (IOException ex) {
+            System.err.println("Impossible de lire le fichier : " + ex.getMessage());
+            return null;
+        }
+        return fileContent;
+    }
+
+}

+ 1 - 0
BSWFX/start.sh

@@ -0,0 +1 @@
+java -jar dist/BSWFX.jar

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác