1 package cz.cuni.amis.pogamut.ut2004.agent.module.sensor;
2
3 import java.io.File;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.io.PrintWriter;
7 import java.util.ArrayList;
8 import java.util.HashMap;
9 import java.util.List;
10 import java.util.logging.Logger;
11
12 import javax.vecmath.Vector3d;
13
14 import cz.cuni.amis.pogamut.base.agent.module.SensorModule;
15 import cz.cuni.amis.pogamut.base.communication.worldview.IWorldView;
16 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEvent;
17 import cz.cuni.amis.pogamut.base.communication.worldview.object.IWorldObjectEventListener;
18 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
19 import cz.cuni.amis.pogamut.base3d.worldview.object.Location;
20 import cz.cuni.amis.pogamut.base3d.worldview.object.Rotation;
21 import cz.cuni.amis.pogamut.unreal.communication.messages.UnrealId;
22 import cz.cuni.amis.pogamut.ut2004.agent.navigation.floydwarshall.FloydWarshallMap;
23 import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotController;
24 import cz.cuni.amis.pogamut.ut2004.bot.IUT2004BotLogicController;
25 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004Bot;
26 import cz.cuni.amis.pogamut.ut2004.bot.impl.UT2004BotModuleController;
27 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.GameInfo;
28 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPoint;
29 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPointMessage;
30 import cz.cuni.amis.pogamut.ut2004.communication.messages.gbinfomessages.NavPointNeighbourLink;
31 import cz.cuni.amis.pogamut.ut2004.utils.LinkFlag;
32 import cz.cuni.amis.pogamut.ut2004.utils.UnrealUtils;
33 import cz.cuni.amis.utils.NullCheck;
34 import cz.cuni.amis.utils.exception.PogamutException;
35 import cz.cuni.amis.utils.exception.PogamutIOException;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class NavigationGraphBuilder extends SensorModule<UT2004Bot> {
60
61
62
63
64
65
66
67
68 public class NewNavPointBuilder {
69
70 private String id;
71 private Location location;
72 private List<NewNavPointEdgeBuilder> edges = new ArrayList<NewNavPointEdgeBuilder>();
73
74 protected NewNavPointBuilder() {
75 }
76
77
78
79
80
81
82 public NewNavPointBuilder setId(String id) {
83 NullCheck.check(id, "id");
84 this.id = autoPrefix(id);
85 return this;
86 }
87
88
89
90
91
92
93
94
95
96 public NewNavPointBuilder setLocation(double x, double y, double z) {
97 this.location = new Location(x,y,z);
98 return this;
99 }
100
101
102
103
104
105
106
107
108
109 public void createNavPoint() {
110 if (id == null) throw new PogamutException("Could not create navpoint, id is null, you must set it using setId() before calling this method.", this);
111 if (location == null) throw new PogamutException("Could not create navpoint (" + id + "), location is null, you must set it using setLocation() before calling this method.", this);
112 NavPoint newNavPoint =
113 new NavPointMessage(UnrealId.get(id), location, null, false, null, null, false, false, null, null, false, false, false, false, 255, false, 255, false, false, false, false, false, false, false, false, new Rotation(0,0,0), false, false, null, new HashMap<UnrealId, NavPointNeighbourLink>(), new HashMap<UnrealId, NavPointNeighbourLink>(), null);
114
115 for (NewNavPointEdgeBuilder edge : edges) {
116 Object np = agent.getWorldView().get(edge.toNavPointId);
117 if (np == null) {
118 throw new PogamutException("Could not create navpoint (" + id + ") as the remote end (" + edge.toNavPointId + ") of one of its edges could not be found in the bot's worldview. Warning, id is case-sensitive the upper/lower cases of the id depends on the concrete spelling of the map that was passed to the GB2004 during startup (either from the command line or by the UT2004).", this);
119 }
120 if (!(np instanceof NavPoint)) {
121 throw new PogamutException("Could not create navpoint (" + id + ") as the remote end (" + edge.toNavPointId + ") of one of its edges is not an instance of NavPoint, but " + np.getClass().getSimpleName() + ". Wrong id used?", this);
122 }
123 NavPoint toNavPoint = (NavPoint)np;
124 NavPointNeighbourLink link = new NavPointNeighbourLink(UnrealId.get(id), edge.flags, edge.collisionR, edge.collisionH, 0, null, false, edge.forceDoubleJump, edge.neededJump, false, false, 0, newNavPoint, toNavPoint);
125 newNavPoint.getOutgoingEdges().put(link.getToNavPoint().getId(), link);
126 link.getToNavPoint().getIncomingEdges().put(newNavPoint.getId(), link);
127 }
128
129 agent.getWorldView().notifyImmediately(newNavPoint);
130 }
131
132
133
134
135
136
137
138
139 public NewNavPointEdgeBuilder<NewNavPointBuilder> newEdge() {
140 return new NewNavPointEdgeBuilder<NewNavPointBuilder>(this);
141 }
142
143
144
145
146
147
148
149
150
151 public NewNavPointEdgeBuilder<NewNavPointBuilder> newEdgeTo(String navPointId) {
152 NullCheck.check(navPointId, "navPointId");
153 NewNavPointEdgeBuilder<NewNavPointBuilder> edgeBuilder = new NewNavPointEdgeBuilder<NewNavPointBuilder>(this);
154 edgeBuilder.setTo(navPointId);
155 return edgeBuilder;
156 }
157
158
159
160
161
162 public void createSimpleEdgeTo(String navPointId) {
163 NullCheck.check(navPointId, "navPointId");
164 newEdgeTo(navPointId).createEdge();
165 }
166
167
168
169
170
171
172 protected void addEdge(NewNavPointEdgeBuilder newNavPointEdgeBuilder) {
173 this.edges.add(newNavPointEdgeBuilder);
174 }
175
176 }
177
178
179
180
181
182
183
184
185 public class NewNavPointEdgeBuilder<OWNER> {
186
187 protected OWNER owner;
188 protected UnrealId toNavPointId;
189 protected int collisionR = (int)UnrealUtils.CHARACTER_COLLISION_RADIUS * 2;
190 protected int collisionH = (int)UnrealUtils.CHARACTER_HEIGHT_STANDING + 10;
191 protected boolean forceDoubleJump = false;
192 protected Vector3d neededJump;
193 protected int flags = 0;
194
195 protected NewNavPointEdgeBuilder(OWNER owner) {
196 this.owner = owner;
197 NullCheck.check(this.owner, "owner");
198 }
199
200
201
202
203
204
205
206 public NewNavPointEdgeBuilder<OWNER> setTo(String navPointId) {
207 NullCheck.check(navPointId, "navPointId");
208 this.toNavPointId = UnrealId.get(autoPrefix(navPointId));
209 return this;
210 }
211
212
213
214
215
216
217
218 public NewNavPointEdgeBuilder<OWNER> setTo(UnrealId navPointId) {
219 this.toNavPointId = navPointId;
220 return this;
221 }
222
223
224
225
226
227
228
229 public NewNavPointEdgeBuilder<OWNER> setCollisionRadius(int collisionRadius) {
230 this.collisionR = collisionRadius;
231 return this;
232 }
233
234
235
236
237
238
239
240 public NewNavPointEdgeBuilder<OWNER> setCollisionHeight(int collisionHeight) {
241 this.collisionH = collisionHeight;
242 return this;
243 }
244
245
246
247
248
249
250
251
252
253 public NewNavPointEdgeBuilder<OWNER> setNeededJump(double x, double y, double z) {
254 this.neededJump = new Vector3d(x,y,z);
255 return this;
256 }
257
258
259
260
261
262
263
264 public NewNavPointEdgeBuilder<OWNER> setDoubleJump() {
265 this.forceDoubleJump = true;
266 return this;
267 }
268
269
270
271
272
273
274
275
276 public NewNavPointEdgeBuilder<OWNER> setWalkFlag() {
277 flags |= LinkFlag.WALK.get();
278 return this;
279 }
280
281
282
283
284
285
286
287 public NewNavPointEdgeBuilder<OWNER> setFlyFlag() {
288 flags |= LinkFlag.FLY.get();
289 return this;
290 }
291
292
293
294
295
296
297
298 public NewNavPointEdgeBuilder<OWNER> setSwimFlag() {
299 flags |= LinkFlag.SWIM.get();
300 return this;
301 }
302
303
304
305
306
307
308
309 public NewNavPointEdgeBuilder<OWNER> setJumpFlag() {
310 flags |= LinkFlag.JUMP.get();
311 return this;
312 }
313
314
315
316
317
318
319
320 public NewNavPointEdgeBuilder<OWNER> setDoorFlag() {
321 flags |= LinkFlag.DOOR.get();
322 return this;
323 }
324
325
326
327
328
329
330
331 public NewNavPointEdgeBuilder<OWNER> setSpecialFlag() {
332 flags |= LinkFlag.SPECIAL.get();
333 return this;
334 }
335
336
337
338
339
340
341
342 public NewNavPointEdgeBuilder<OWNER> setLadderFlag() {
343 flags |= LinkFlag.LADDER.get();
344 return this;
345 }
346
347
348
349
350
351
352
353 public NewNavPointEdgeBuilder<OWNER> setProscribedFlag() {
354 flags |= LinkFlag.PROSCRIBED.get();
355 return this;
356 }
357
358
359
360
361
362
363
364 public NewNavPointEdgeBuilder<OWNER> setForcedFlag() {
365 flags |= LinkFlag.FORCED.get();
366 return this;
367 }
368
369
370
371
372
373
374
375 public NewNavPointEdgeBuilder<OWNER> setPlayerOnlyFlag() {
376 flags |= LinkFlag.PLAYERONLY.get();
377 return this;
378 }
379
380
381
382
383
384
385
386
387
388
389 public OWNER createEdge() {
390 if (toNavPointId == null) {
391 throw new PogamutException("Could not create edge - toNavPoint not specified, you must call setTo() with non-null argument (to specify the other end of the edge) before calling this method.", this);
392 }
393 ((NewNavPointBuilder)owner).addEdge(this);
394 return ((OWNER)owner);
395 }
396
397 }
398
399
400
401
402
403
404
405 public class ExistingNavPointModifier {
406
407 private NavPoint navPoint;
408
409 protected ExistingNavPointModifier(NavPoint navPoint) {
410 this.navPoint = navPoint;
411 NullCheck.check(this.navPoint, "navPoint");
412 }
413
414
415
416
417
418
419
420
421 public void removeEdgeTo(String navPointId) {
422 NullCheck.check(navPointId, "navPointId");
423 navPointId = autoPrefix(navPointId);
424 UnrealId navPointUnrealId = UnrealId.get(navPointId);
425 navPoint.getOutgoingEdges().remove(navPointUnrealId);
426 Object np = agent.getWorldView().get(navPointUnrealId);
427 if (np != null && (np instanceof NavPoint)) {
428 ((NavPoint)np).getIncomingEdges().remove(navPoint.getId());
429 }
430 }
431
432
433
434
435
436
437
438
439 public void removeEdgesBetween(String navPointId) {
440 NullCheck.check(navPointId, "navPointId");
441 navPointId = autoPrefix(navPointId);
442 UnrealId toNavPointUnrealId = UnrealId.get(navPointId);
443
444 Object np = agent.getWorldView().get(toNavPointUnrealId);
445 NavPoint toNavPoint = null;
446 if (np != null && (np instanceof NavPoint)) {
447 toNavPoint = (NavPoint)np;
448 }
449
450 navPoint.getOutgoingEdges().remove(toNavPointUnrealId);
451 navPoint.getIncomingEdges().remove(toNavPointUnrealId);
452
453 if (toNavPoint != null) {
454 toNavPoint.getOutgoingEdges().remove(navPoint.getId());
455 toNavPoint.getIncomingEdges().remove(navPoint.getId());
456 }
457 }
458
459
460
461
462
463
464
465
466
467
468
469 public ExistingNavPointEdgeBuilder modifyEdgeTo(String navPointId) {
470 NullCheck.check(navPointId, "navPointId");
471 navPointId = autoPrefix(navPointId);
472 UnrealId navPointUnrealId = UnrealId.get(navPointId);
473 NavPointNeighbourLink link = navPoint.getOutgoingEdges().get(navPointUnrealId);
474 if (link != null) {
475 return new ExistingNavPointEdgeBuilder(this, link);
476 } else {
477 return new ExistingNavPointEdgeBuilder(this).setTo(navPointId);
478 }
479 }
480
481
482
483
484
485
486
487
488
489
490
491
492
493 public ExistingNavPointEdgeBuilder createEdgeTo(String navPointId) {
494 NullCheck.check(navPointId, "navPointId");
495 navPointId = autoPrefix(navPointId);
496 ExistingNavPointEdgeBuilder builder = new ExistingNavPointEdgeBuilder(this, null);
497 builder.setTo(navPointId);
498 return builder;
499 }
500
501
502
503
504
505
506
507
508
509
510
511
512
513 public ExistingNavPointEdgeBuilder createEdge() {
514 return new ExistingNavPointEdgeBuilder(this, null);
515 }
516
517
518
519
520
521
522
523
524 public void createSimpleEdgeTo(String navPointId) {
525 NullCheck.check(navPointId, "navPointId");
526 createEdgeTo(navPointId).createEdge();
527 }
528
529
530
531
532
533
534
535
536 public void createSimpleEdgesBetween(String navPointId) {
537 NullCheck.check(navPointId, "navPointId");
538 createEdgeTo(navPointId).createEdge();
539 modifyNavPoint(navPointId).createSimpleEdgeTo(navPoint.getId().getStringId());
540 }
541
542 }
543
544 public class ExistingNavPointEdgeBuilder extends NewNavPointEdgeBuilder<ExistingNavPointModifier> {
545
546 private NavPointNeighbourLink parentLink;
547
548 protected ExistingNavPointEdgeBuilder(ExistingNavPointModifier navPointModifier) {
549 super(navPointModifier);
550 }
551
552 protected ExistingNavPointEdgeBuilder(ExistingNavPointModifier navPointModifier, NavPointNeighbourLink parent) {
553 super(navPointModifier);
554 this.parentLink = parent;
555 if (this.parentLink != null) {
556 this.collisionH = this.parentLink.getCollisionH();
557 this.collisionR = this.parentLink.getCollisionR();
558 this.flags = this.parentLink.getFlags();
559 this.forceDoubleJump = this.parentLink.isForceDoubleJump();
560 this.neededJump = this.parentLink.getNeededJump();
561 this.toNavPointId = this.parentLink.getToNavPoint().getId();
562 }
563 }
564
565 @Override
566 public ExistingNavPointEdgeBuilder setTo(String navPointId) {
567 super.setTo(navPointId);
568 return this;
569 }
570
571 @Override
572 public ExistingNavPointEdgeBuilder setTo(UnrealId navPointId) {
573 super.setTo(navPointId);
574 return this;
575 }
576
577 @Override
578 public ExistingNavPointEdgeBuilder setCollisionRadius(int collisionRadius) {
579 super.setCollisionRadius(collisionRadius);
580 return this;
581 }
582
583 @Override
584 public ExistingNavPointEdgeBuilder setCollisionHeight(int collisionHeight) {
585 super.setCollisionHeight(collisionHeight);
586 return this;
587 }
588
589 @Override
590 public ExistingNavPointEdgeBuilder setNeededJump(double x, double y, double z) {
591 super.setNeededJump(x, y, z);
592 return this;
593 }
594
595
596
597
598
599 public ExistingNavPointEdgeBuilder removeNeededJump() {
600 this.neededJump = null;
601 return this;
602 }
603
604 @Override
605 public ExistingNavPointEdgeBuilder setDoubleJump() {
606 super.setDoubleJump();
607 return this;
608 }
609
610
611
612
613
614 public ExistingNavPointEdgeBuilder removeDoubleJump() {
615 this.forceDoubleJump = false;
616 return this;
617 }
618
619
620 @Override
621 public ExistingNavPointEdgeBuilder setWalkFlag() {
622 super.setWalkFlag();
623 return this;
624 }
625
626
627
628
629
630
631 public ExistingNavPointEdgeBuilder removeWalkFlag() {
632 this.flags = (this.flags | LinkFlag.WALK.get()) ^ LinkFlag.WALK.get();
633 return this;
634 }
635
636 @Override
637 public ExistingNavPointEdgeBuilder setFlyFlag() {
638 super.setFlyFlag();
639 return this;
640 }
641
642
643
644
645
646
647 public ExistingNavPointEdgeBuilder removeFlyFlag() {
648 this.flags = (this.flags | LinkFlag.FLY.get()) ^ LinkFlag.FLY.get();
649 return this;
650 }
651
652 @Override
653 public ExistingNavPointEdgeBuilder setSwimFlag() {
654 super.setSwimFlag();
655 return this;
656 }
657
658
659
660
661
662
663 public ExistingNavPointEdgeBuilder removeSwimFlag() {
664 this.flags = (this.flags | LinkFlag.SWIM.get()) ^ LinkFlag.SWIM.get();
665 return this;
666 }
667
668 @Override
669 public ExistingNavPointEdgeBuilder setJumpFlag() {
670 super.setJumpFlag();
671 return this;
672 }
673
674
675
676
677
678
679 public ExistingNavPointEdgeBuilder removeJumpFlag() {
680 this.flags = (this.flags | LinkFlag.JUMP.get()) ^ LinkFlag.JUMP.get();
681 return this;
682 }
683
684 @Override
685 public ExistingNavPointEdgeBuilder setDoorFlag() {
686 super.setDoorFlag();
687 return this;
688 }
689
690
691
692
693
694
695 public ExistingNavPointEdgeBuilder removeDoorFlag() {
696 this.flags = (this.flags | LinkFlag.DOOR.get()) ^ LinkFlag.DOOR.get();
697 return this;
698 }
699
700 @Override
701 public ExistingNavPointEdgeBuilder setSpecialFlag() {
702 super.setSpecialFlag();
703 return this;
704 }
705
706
707
708
709
710
711 public ExistingNavPointEdgeBuilder removeSpecialFlag() {
712 this.flags = (this.flags | LinkFlag.SPECIAL.get()) ^ LinkFlag.SPECIAL.get();
713 return this;
714 }
715
716 @Override
717 public ExistingNavPointEdgeBuilder setLadderFlag() {
718 super.setLadderFlag();
719 return this;
720 }
721
722
723
724
725
726
727 public ExistingNavPointEdgeBuilder removeLadderFlag() {
728 this.flags = (this.flags | LinkFlag.LADDER.get()) ^ LinkFlag.LADDER.get();
729 return this;
730 }
731
732 @Override
733 public ExistingNavPointEdgeBuilder setProscribedFlag() {
734 super.setProscribedFlag();
735 return this;
736 }
737
738
739
740
741
742
743 public ExistingNavPointEdgeBuilder removeProscribedFlag() {
744 this.flags = (this.flags | LinkFlag.PROSCRIBED.get()) ^ LinkFlag.PROSCRIBED.get();
745 return this;
746 }
747
748 @Override
749 public ExistingNavPointEdgeBuilder setForcedFlag() {
750 super.setForcedFlag();
751 return this;
752 }
753
754
755
756
757
758
759 public ExistingNavPointEdgeBuilder removeForcedFlag() {
760 this.flags = (this.flags | LinkFlag.FORCED.get()) ^ LinkFlag.FORCED.get();
761 return this;
762 }
763
764 @Override
765 public ExistingNavPointEdgeBuilder setPlayerOnlyFlag() {
766 super.setPlayerOnlyFlag();
767 return this;
768 }
769
770
771
772
773
774
775 public ExistingNavPointEdgeBuilder removePlayerOnlyFlag() {
776 this.flags = (this.flags | LinkFlag.PLAYERONLY.get()) ^ LinkFlag.PLAYERONLY.get();
777 return this;
778 }
779
780 public ExistingNavPointEdgeBuilder setFlags(Integer flags) {
781 this.flags = flags;
782 return this;
783 }
784
785
786
787
788
789
790 public ExistingNavPointEdgeBuilder clearFlags() {
791 this.flags = 0;
792 return this;
793 }
794
795
796
797
798
799
800
801
802 @Override
803 public ExistingNavPointModifier createEdge() {
804 if (toNavPointId == null) {
805 throw new PogamutException("Could not create/modify edge from navpoint '" + owner.navPoint.getId().getStringId() + "' as toNavPoint not specified, you must call setTo() with non-null argument (to specify the other end of the edge) before calling this method.", this);
806 }
807 Object np = agent.getWorldView().get(toNavPointId);
808 if (np == null) {
809 throw new PogamutException("Could not create/modify navpoint edge from '" + owner.navPoint.getId().getStringId() + "' as the remote end (" + toNavPointId.getStringId() + ") could not be found in the bot's worldview. Warning, id is case-sensitive the upper/lower cases of the id depends on the concrete spelling of the map that was passed to the GB2004 during startup (either from the command line or by the UT2004).", this);
810 }
811 if (!(np instanceof NavPoint)) {
812 throw new PogamutException("Could not create/modify navpoint edge from '" + owner.navPoint.getId().getStringId() + "' as the remote end '" + toNavPointId.getStringId() + "' is not an instance of NavPoint but " + np.getClass().getSimpleName() + ". Wrong id specified?", this);
813 }
814
815 NavPoint toNavPoint = (NavPoint)np;
816
817 NavPointNeighbourLink link = null;
818
819 if (parentLink == null) {
820 link = new NavPointNeighbourLink(owner.navPoint.getId(), flags, collisionR, collisionH, 0, null, false, forceDoubleJump, neededJump, false, false, 0, owner.navPoint, toNavPoint);
821 } else {
822 link = new NavPointNeighbourLink(owner.navPoint.getId(), flags, collisionR, collisionH, parentLink.getTranslocZOffset(), parentLink.getTranslocTargetTag(), parentLink.isOnlyTranslocator(), forceDoubleJump, neededJump, parentLink.isNeverImpactJump(), parentLink.isNoLowGrav(), parentLink.getCalculatedGravityZ(), owner.navPoint, toNavPoint);
823 }
824
825 owner.navPoint.getOutgoingEdges().put(link.getToNavPoint().getId(), link);
826 link.getToNavPoint().getIncomingEdges().put(owner.navPoint.getId(), link);
827
828 return owner;
829 }
830
831
832
833
834
835
836
837
838 public ExistingNavPointModifier modifyEdge() {
839 return createEdge();
840 }
841
842 }
843
844
845
846
847 private class GameInfoListener implements IWorldObjectEventListener<GameInfo, IWorldObjectEvent<GameInfo>>
848 {
849 @Override
850 public void notify(IWorldObjectEvent<GameInfo> event)
851 {
852 lastGameInfo = event.getObject();
853 if (lastGameInfo.getLevel() == null) {
854 throw new PogamutException("GameInfo.getLevel() is null!!!", this);
855 }
856 mapNameLowerChar = lastGameInfo.getLevel().toLowerCase();
857 }
858
859
860
861
862
863 public GameInfoListener(IWorldView worldView)
864 {
865 worldView.addObjectListener(GameInfo.class, this);
866 }
867 }
868
869
870 GameInfoListener gameInfoListener;
871
872
873 GameInfo lastGameInfo = null;
874
875 String mapNameLowerChar = null;
876
877 public NavigationGraphBuilder(UT2004Bot bot) {
878 this(bot, null);
879 }
880
881 public NavigationGraphBuilder(UT2004Bot bot, Logger log) {
882 this(bot, log, null);
883 }
884
885 public NavigationGraphBuilder(UT2004Bot bot, Logger log, ComponentDependencies dependencies) {
886 super(bot, log, dependencies);
887 gameInfoListener = new GameInfoListener(bot.getWorldView());
888 }
889
890 @Override
891 protected void cleanUp() {
892 super.cleanUp();
893 lastGameInfo = null;
894 mapNameLowerChar = null;
895 }
896
897
898
899
900
901
902
903
904
905
906
907
908 public String getMapName() {
909 if (lastGameInfo == null) return null;
910 return lastGameInfo.getLevel();
911 }
912
913
914
915
916
917
918 public boolean isMapName(String name) {
919 if (lastGameInfo == null) return false;
920 if (name == null) return false;
921 return lastGameInfo.getLevel().toLowerCase().equals(name.toLowerCase());
922 }
923
924 private boolean autoPrefix = true;
925
926
927
928
929 private boolean used;
930
931
932
933
934
935
936
937
938
939
940
941
942 public boolean isAutoPrefix() {
943 return autoPrefix;
944 }
945
946
947
948
949
950
951
952
953
954
955
956
957 public void setAutoPrefix(boolean autoPrefix) {
958 this.autoPrefix = autoPrefix;
959 }
960
961
962
963
964
965
966
967
968
969
970
971 public String getPrefixed(String navPointId) {
972
973 if (getMapName() == null) {
974 throw new PogamutException("GameInfo was not received yet, can't auto-prefix name of the navpoint '" + navPointId + "'.", this);
975 }
976 if (navPointId.toLowerCase().startsWith(mapNameLowerChar + ".")) {
977
978 if (!navPointId.startsWith(getMapName())) {
979
980 navPointId = getMapName() + navPointId.substring(mapNameLowerChar.length());
981 }
982
983 return navPointId;
984 } else {
985
986 if (navPointId.contains(".")) {
987
988 throw new PogamutException("navPointId '" + navPointId + "' is already prefixed with '" + navPointId.substring(0, navPointId.indexOf(".")) + "' which is different from current map name '" + getMapName() + "', map name validation fails!", this);
989 }
990
991 return getMapName() + "." + navPointId;
992 }
993 }
994
995
996
997
998
999
1000
1001
1002
1003
1004 public String autoPrefix(String navPointId) {
1005 NullCheck.check(navPointId, "navPointId");
1006 if (autoPrefix) {
1007 return getPrefixed(navPointId);
1008 } else {
1009
1010 return navPointId;
1011 }
1012 }
1013
1014
1015
1016
1017
1018
1019
1020
1021 public NewNavPointBuilder newNavPoint() {
1022 used = true;
1023 return new NewNavPointBuilder();
1024 }
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035 public NewNavPointBuilder newNavPoint(String navPointId) {
1036 used = true;
1037 NullCheck.check(navPointId, "navPointId");
1038 return new NewNavPointBuilder().setId(navPointId);
1039 }
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049 public ExistingNavPointModifier modifyNavPoint(String navPointId) {
1050 used = true;
1051 NullCheck.check(navPointId, "navPointId");
1052 navPointId = autoPrefix(navPointId);
1053
1054 Object np = agent.getWorldView().get(UnrealId.get(navPointId));
1055 if (np == null) {
1056 throw new PogamutException("Could not modify navpoint '" + navPointId + "' as it was not found in the worldview. No object under this id exists in worldview. Warning, id is case-sensitive the upper/lower cases of the id depends on the concrete spelling of the map that was passed to the GB2004 during startup (either from the command line or by the UT2004).", this);
1057 }
1058 if (!(np instanceof NavPoint)) {
1059 throw new PogamutException("Could not modify navpoint '" + navPointId + "' it does not point to an NavPoint instance but " + np.getClass().getSimpleName() + ". Wrong id specified?", this);
1060 }
1061 return new ExistingNavPointModifier((NavPoint)np);
1062 }
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072 public void createSimpleEdge(String fromNavPointId, String toNavPointId) {
1073 used = true;
1074 NullCheck.check(fromNavPointId, "fromNavPointId");
1075 NullCheck.check(toNavPointId, "toNavPointId");
1076 fromNavPointId = autoPrefix(fromNavPointId);
1077 toNavPointId = autoPrefix(toNavPointId);
1078 modifyNavPoint(fromNavPointId).modifyEdgeTo(toNavPointId).createEdge();
1079 }
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089 public void createSimpleEdgesBetween(String firstNavPointId, String secondNavPointId) {
1090 used = true;
1091 NullCheck.check(firstNavPointId, "firstNavPointId");
1092 NullCheck.check(secondNavPointId, "secondNavPointId");
1093 firstNavPointId = autoPrefix(firstNavPointId);
1094 secondNavPointId = autoPrefix(secondNavPointId);
1095 modifyNavPoint(firstNavPointId).modifyEdgeTo(secondNavPointId).createEdge();
1096 modifyNavPoint(secondNavPointId).modifyEdgeTo(firstNavPointId).createEdge();
1097 }
1098
1099
1100
1101
1102
1103
1104 public void removeEdge(String fromNavPointId, String toNavPointId) {
1105 used = true;
1106 NullCheck.check(fromNavPointId, "fromNavPointId");
1107 NullCheck.check(toNavPointId, "toNavPointId");
1108 fromNavPointId = autoPrefix(fromNavPointId);
1109 toNavPointId = autoPrefix(toNavPointId);
1110 modifyNavPoint(fromNavPointId).removeEdgeTo(toNavPointId);
1111 }
1112
1113
1114
1115
1116
1117
1118 public void removeEdgesBetween(String firstNavPointId, String secondNavPointId) {
1119 used = true;
1120 NullCheck.check(firstNavPointId, "firstNavPointId");
1121 NullCheck.check(secondNavPointId, "secondNavPointId");
1122 firstNavPointId = autoPrefix(firstNavPointId);
1123 secondNavPointId = autoPrefix(secondNavPointId);
1124 modifyNavPoint(firstNavPointId).removeEdgeTo(secondNavPointId);
1125 modifyNavPoint(secondNavPointId).removeEdgeTo(firstNavPointId);
1126 }
1127
1128
1129
1130
1131
1132
1133 public boolean isUsed() {
1134 return used;
1135 }
1136
1137
1138
1139
1140
1141 public void setUsed(boolean used) {
1142 this.used = used;
1143 }
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153 public void exportAsXML(File targetXMLFile) {
1154 MapExport map = new MapExport(getMapName(), worldView.getAll(NavPoint.class).values());
1155 map.saveXML(targetXMLFile);
1156 }
1157
1158
1159
1160
1161
1162 public MapExport importFromXML(File sourceXMLFile) {
1163 return MapExport.loadXML(sourceXMLFile);
1164 }
1165
1166 public void apply(MapExport export) {
1167 List<NavPointExport> newNavPoints = new ArrayList<NavPointExport>();
1168
1169 for (NavPointExport sourceNav : export.navPoints) {
1170 NavPoint targetNav = (NavPoint)worldView.get(sourceNav.getUnrealId());
1171
1172 if (targetNav == null) {
1173 NewNavPointBuilder builder = newNavPoint();
1174 builder.setId(sourceNav.Id);
1175 if (sourceNav.Location != null) {
1176 Location loc = new Location(sourceNav.Location);
1177 builder.setLocation(loc.x, loc.y, loc.z);
1178 }
1179 builder.createNavPoint();
1180
1181 newNavPoints.add(sourceNav);
1182 } else {
1183 ExistingNavPointModifier builder = modifyNavPoint(sourceNav.Id);
1184
1185 }
1186 }
1187
1188 for (NavPointExport sourceNav : export.navPoints) {
1189 addLinks(sourceNav);
1190 }
1191 }
1192
1193 private void addLinks(NavPointExport newNav) {
1194 NavPoint targetNav = (NavPoint)worldView.get(newNav.getUnrealId());
1195 for (NavPointLinkExport newLink : newNav.outgoingEdges) {
1196 if (newLink.ToNavPoint == null) {
1197
1198 continue;
1199 }
1200
1201 NavPointNeighbourLink link = targetNav.getOutgoingEdges().get(newLink.getUnrealId());
1202
1203 ExistingNavPointModifier navBuilder = modifyNavPoint(newNav.Id);
1204 ExistingNavPointEdgeBuilder edgeBuilder;
1205
1206 if (link == null) {
1207
1208 edgeBuilder = navBuilder.createEdgeTo(newLink.ToNavPoint);
1209 } else {
1210
1211 edgeBuilder = navBuilder.modifyEdgeTo(newLink.ToNavPoint);
1212 }
1213
1214 if (newLink.CollisionH != null) edgeBuilder.setCollisionHeight(newLink.CollisionH);
1215 if (newLink.CollisionR != null) edgeBuilder.setCollisionRadius(newLink.CollisionR);
1216 if (newLink.NeededJump != null) {
1217 Location neededJump = new Location(newLink.NeededJump);
1218 edgeBuilder.setNeededJump(neededJump.x, neededJump.y, neededJump.z);
1219
1220 }
1221 if (newLink.Flags != null) edgeBuilder.setFlags(newLink.Flags);
1222 edgeBuilder.setTo(newLink.getUnrealId());
1223
1224 if (link == null) {
1225
1226 edgeBuilder.createEdge();
1227 } else {
1228
1229 edgeBuilder.modifyEdge();
1230 }
1231 }
1232 }
1233
1234 private void add(NavPointExport sourceNav) {
1235 Location loc = new Location(sourceNav.Location);
1236 NewNavPointBuilder builder = newNavPoint();
1237 builder.setId(sourceNav.Id);
1238 builder.setLocation(loc.x, loc.y, loc.z);
1239 builder.createNavPoint();
1240 }
1241
1242 }
1243