25 public static final String
KEY =
"$core_routeManager";
41 public static class OptionalFleetData {
42 public Float strength;
45 public String factionId;
46 public String fleetType;
49 public OptionalFleetData() {
51 public OptionalFleetData(MarketAPI market) {
52 this(market, market.getFactionId());
54 public OptionalFleetData(MarketAPI market, String factionId) {
55 quality = Misc.getShipQuality(market, factionId);
56 this.factionId = factionId;
59 public float getStrengthModifiedByDamage() {
60 if (strength ==
null)
return 0f;
63 str *= Math.max(0, 1f - damage);
69 public static class RouteSegment {
71 public float elapsed = 0f;
73 public SectorEntityToken from;
74 public SectorEntityToken to;
77 public RouteSegment(Integer
id,
float daysMax, SectorEntityToken from) {
78 this(id, daysMax, from,
null,
null);
80 public RouteSegment(
float daysMax, SectorEntityToken from) {
81 this(
null, daysMax, from,
null,
null);
83 public RouteSegment(Integer
id,
float daysMax, SectorEntityToken from, Object custom) {
84 this(id, daysMax, from,
null, custom);
86 public RouteSegment(
float daysMax, SectorEntityToken from, Object custom) {
87 this(
null, daysMax, from,
null, custom);
89 public RouteSegment(Integer
id,
float daysMax, SectorEntityToken from, SectorEntityToken to) {
90 this(id, daysMax, from, to,
null);
92 public RouteSegment(Integer
id, SectorEntityToken from, SectorEntityToken to) {
93 this(id, 0f, from, to,
null);
94 if (from.getContainingLocation() != to.getContainingLocation()) {
95 float dist = Misc.getDistance(from.getLocationInHyperspace(), to.getLocationInHyperspace());
98 float dist = Misc.getDistance(from.getLocation(), to.getLocation());
99 daysMax = dist / 1500f;
102 public RouteSegment(
float daysMax, SectorEntityToken from, SectorEntityToken to) {
103 this(
null, daysMax, from, to,
null);
105 public RouteSegment(Integer
id,
float daysMax, SectorEntityToken from, SectorEntityToken to, Object custom) {
107 this.daysMax = daysMax;
110 this.custom = custom;
113 public LocationAPI getCurrentContainingLocation() {
114 LocationAPI loc =
null;
115 if (from !=
null && to ==
null) {
116 loc = from.getContainingLocation();
117 }
else if (from ==
null && to !=
null) {
118 loc = to.getContainingLocation();
120 if (from.getContainingLocation() == to.getContainingLocation()) {
121 loc = from.getContainingLocation();
123 if (getLeaveProgress() < 1) {
124 loc = from.getContainingLocation();
125 }
else if (getTransitProgress() < 1) {
126 loc = Global.getSector().getHyperspace();
128 loc = to.getContainingLocation();
135 public LocationAPI getContainingLocationFrom() {
136 if (from ==
null)
return null;
137 return from.getContainingLocation();
140 public LocationAPI getContainingLocationTo() {
141 if (to ==
null)
return null;
142 return to.getContainingLocation();
145 public boolean isTravel() {
149 public boolean isInSystem() {
150 if (to ==
null && from !=
null && from.getContainingLocation() !=
null && !from.getContainingLocation().isHyperspace())
return true;
152 if (!from.getContainingLocation().isHyperspace() &&
153 from.getContainingLocation() == to.getContainingLocation()) {
159 public boolean isFromSystemCenter() {
160 return from !=
null && from.getContainingLocation() instanceof StarSystemAPI &&
161 ((StarSystemAPI)from.getContainingLocation()).getCenter() == from;
164 public boolean isToSystemCenter() {
165 return to !=
null && to.getContainingLocation() instanceof StarSystemAPI &&
166 ((StarSystemAPI)to.getContainingLocation()).getCenter() == to;
169 public boolean hasLeaveSystemPhase() {
170 if (isInSystem())
return false;
171 if (isFromSystemCenter())
return false;
172 if (from !=
null && from.getContainingLocation().isHyperspace())
return false;
175 public boolean hasEnterSystemPhase() {
176 if (isInSystem())
return false;
177 if (isToSystemCenter())
return false;
178 if (to !=
null && to.getContainingLocation().isHyperspace())
return false;
182 public float getProgress() {
183 if (daysMax <= 0f)
return 1f;
184 return elapsed / daysMax;
187 public float getEnterProgress() {
189 float f = 1f - Math.max(0, daysMax - elapsed) / dur;
194 public float getLeaveProgress() {
196 float f = elapsed / dur;
201 public float getTransitProgress() {
205 if (hasEnterSystemPhase()) {
208 if (hasLeaveSystemPhase()) {
218 public SectorEntityToken getDestination() {
219 if (to !=
null)
return to;
223 public SectorEntityToken getFrom() {
227 if (
id ==
null)
return 0;
235 public static interface RouteFleetSpawner {
236 CampaignFleetAPI spawnFleet(RouteData route);
237 boolean shouldCancelRouteAfterDelayCheck(RouteData route);
238 boolean shouldRepeat(RouteData route);
239 void reportAboutToBeDespawnedByRouteManager(RouteData route);
242 public static class RouteData {
243 protected OptionalFleetData extra =
null;
244 protected float delay = 0f;
245 protected String source;
246 protected MarketAPI market;
248 protected long timestamp;
249 protected List<RouteSegment> segments =
new ArrayList<RouteSegment>();
250 protected CampaignFleetAPI activeFleet =
null;
251 protected float daysSinceSeenByPlayer = 1000f;
252 protected float elapsed = 0f;
253 protected Object custom;
254 protected RouteSegment current;
255 protected RouteFleetSpawner spawner;
266 public RouteData(String source, MarketAPI market, Long seed, OptionalFleetData extra) {
267 this.source = source;
268 this.market = market;
272 public OptionalFleetData getExtra() {
275 public void setExtra(OptionalFleetData extra) {
278 public MarketAPI getMarket() {
281 public void goToAtLeastNext(RouteSegment from) {
282 int index = segments.indexOf(current);
283 int indexFrom = segments.indexOf(from);
284 if (indexFrom < 0)
return;
285 if (indexFrom < index)
return;
287 if (indexFrom < segments.size() - 1) {
288 current = segments.get(indexFrom + 1);
290 current.elapsed = current.daysMax;
294 public void expire() {
295 if (!segments.isEmpty()) {
296 current = segments.get(segments.size() - 1);
298 if (current !=
null) {
299 current.elapsed = current.daysMax;
319 public Random getRandom(
int level) {
320 if (seed ==
null)
return new Random();
321 return Misc.getRandom(seed, level);
323 public String getFactionId() {
324 if (extra ==
null || extra.factionId ==
null) {
325 if (market !=
null)
return market.getFactionId();
328 return extra.factionId;
330 public Float getQualityOverride() {
331 if (extra ==
null)
return null;
332 return extra.quality;
334 public long getTimestamp() {
337 public void setTimestamp(
long timestamp) {
338 this.timestamp = timestamp;
340 public Random getRandom() {
341 Random random =
new Random();
342 if (getSeed() !=
null) {
343 random =
new Random(getSeed());
348 public Long getSeed() {
351 public RouteSegment addSegment(RouteSegment segment) {
352 if (segments.isEmpty()) current = segment;
353 segments.add(segment);
356 public List<RouteSegment> getSegments() {
359 public void setCurrent(RouteSegment current) {
360 this.current = current;
362 public CampaignFleetAPI getActiveFleet() {
365 public float getDaysSinceSeenByPlayer() {
366 return daysSinceSeenByPlayer;
368 public float getElapsed() {
371 public Object getCustom() {
374 public RouteSegment getCurrent() {
377 public Integer getCurrentSegmentId() {
378 if (current ==
null)
return 0;
379 return current.getId();
381 public int getCurrentIndex() {
382 return segments.indexOf(current);
384 public RouteFleetSpawner getSpawner() {
387 public String getSource() {
391 public Vector2f getInterpolatedHyperLocation() {
393 if (current ==
null)
return new Vector2f(100000000f, 0);
395 if (current.isInSystem() || current.getContainingLocationTo() ==
null || current.to ==
null) {
396 return current.from.getLocationInHyperspace();
400 float p = current.getTransitProgress();
403 Vector2f from = current.getContainingLocationFrom().getLocation();
404 if (current.getContainingLocationFrom().isHyperspace()) {
405 from = current.getFrom().getLocation();
407 Vector2f to = current.getContainingLocationTo().getLocation();
408 if (current.getContainingLocationTo().isHyperspace()) {
409 to = current.to.getLocation();
415 Vector2f interpLoc = Misc.interpolateVector(from, to, p);
420 public boolean isExpired() {
421 if (segments.indexOf(current) == segments.size() - 1 && current.elapsed >= current.daysMax) {
426 public void setCustom(Object custom) {
427 this.custom = custom;
429 public float getDelay() {
432 public void setDelay(
float delay) {
449 protected List<RouteData>
routes =
new ArrayList<RouteData>();
450 protected transient Map<String, List<RouteData>>
sourceToRoute =
new LinkedHashMap<String, List<RouteData>>();
453 Object readResolve() {
454 sourceToRoute =
new LinkedHashMap<String, List<RouteData>>();
455 for (RouteData route :
routes) {
465 for (RouteData route :
routes) {
469 RouteSegment current = route.current;
470 if (current ==
null)
continue;
472 LocationAPI loc =
null;
473 if (current.from !=
null && current.to ==
null) {
474 loc = current.from.getContainingLocation();
475 }
else if (current.from ==
null && current.to !=
null) {
476 loc = current.to.getContainingLocation();
478 if (current.from.getContainingLocation() == current.to.getContainingLocation()) {
479 loc = current.from.getContainingLocation();
481 if (current.getLeaveProgress() < 1) {
482 loc = current.from.getContainingLocation();
483 }
else if (current.getTransitProgress() < 1) {
486 loc = current.to.getContainingLocation();
494 list =
new ArrayList<RouteData>();
503 if (list ==
null) list =
new ArrayList<RouteData>();
508 public RouteData
addRoute(String source, MarketAPI market, Long seed, OptionalFleetData extra, RouteFleetSpawner spawner) {
509 return addRoute(source, market, seed, extra, spawner,
null);
520 public RouteData
addRoute(String source, MarketAPI market, Long seed, OptionalFleetData extra, RouteFleetSpawner spawner, Object custom) {
523 RouteData route =
new RouteData(source, market, seed, extra);
524 route.spawner = spawner;
525 route.custom = custom;
539 if (route.source ==
null)
return;
542 forSource.add(route);
548 if (route.source ==
null)
return;
551 forSource.remove(route);
552 if (forSource.isEmpty()) {
559 if (forSource ==
null) {
560 forSource =
new ArrayList<RouteData>();
566 public RouteData
getRoute(String source, CampaignFleetAPI fleet) {
568 if (forSource ==
null) {
569 forSource =
new ArrayList<RouteData>();
572 for (RouteData data : forSource) {
573 if (data.activeFleet == fleet)
return data;
603 if (player ==
null)
return;
608 for (RouteData data :
new ArrayList<RouteData>(
routes)) {
609 if (data.activeFleet !=
null && data.activeFleet.getContainingLocation() == player.getContainingLocation()) {
610 VisibilityLevel level = data.activeFleet.getVisibilityLevelToPlayerFleet();
611 if ((level == VisibilityLevel.COMPOSITION_AND_FACTION_DETAILS ||
612 level == VisibilityLevel.COMPOSITION_DETAILS) &&
613 data.activeFleet.wasMousedOverByPlayer()) {
614 data.daysSinceSeenByPlayer = 0f;
623 data.spawner.reportAboutToBeDespawnedByRouteManager(data);
624 data.activeFleet.despawn(FleetDespawnReason.PLAYER_FAR_AWAY,
null);
625 if (data.activeFleet.getContainingLocation() !=
null) {
626 data.activeFleet.getContainingLocation().removeEntity(data.activeFleet);
628 data.activeFleet =
null;
640 data.activeFleet = data.spawner.spawnFleet(data);
641 if (data.activeFleet !=
null) {
642 data.activeFleet.addEventListener(
this);
663 if (data.delay > 0)
return false;
664 if (data.activeFleet !=
null)
return false;
672 Vector2f interpLoc = data.getInterpolatedHyperLocation();
675 float distLY = Misc.getDistanceLY(interpLoc, player.getLocationInHyperspace());
682 float distLY = Misc.getDistanceLY(from.getLocationInHyperspace(),
Global.
getSector().getPlayerFleet().getLocationInHyperspace());
689 if (data.activeFleet ==
null)
return false;
691 if (data.activeFleet.getBattle() !=
null)
return false;
692 if (data.activeFleet.isNoAutoDespawn())
return false;
697 float distLY = Misc.getDistanceLY(data.activeFleet.getLocationInHyperspace(), player.getLocationInHyperspace());
716 Iterator<RouteData> iter =
routes.iterator();
717 while (iter.hasNext()) {
718 RouteData route = iter.next();
720 boolean delay = route.delay > 0;
723 if (route.delay < 0) route.delay = 0;
724 if (route.delay > 0)
continue;
726 if (route.spawner.shouldCancelRouteAfterDelayCheck(route)) {
735 if (route.current ==
null && route.segments.isEmpty()) {
741 if (route.current ==
null) route.current = route.segments.get(0);
743 route.current.elapsed += days;
744 route.daysSinceSeenByPlayer += days;
745 route.elapsed += days;
747 if (route.getActiveFleet() !=
null)
continue;
751 if (route.current.elapsed >= route.current.daysMax) {
752 int index = route.segments.indexOf(route.current);
753 if (index < route.segments.size() - 1) {
754 route.current = route.segments.get(index + 1);
756 if (route.spawner.shouldRepeat(route)) {
757 route.current =
null;
758 for (RouteSegment segment : route.segments) {
759 segment.elapsed = 0f;
773 if (reason == FleetDespawnReason.PLAYER_FAR_AWAY) {
777 boolean found =
false;
778 for (RouteData curr :
routes) {
779 if (curr.activeFleet !=
null && curr.activeFleet == fleet) {
780 if (reason == FleetDespawnReason.PLAYER_FAR_AWAY) {