diff --git a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/CastLocationDataEvent.java b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/CastLocationDataEvent.java index 300d675e33f2..69551cdf24f1 100644 --- a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/CastLocationDataEvent.java +++ b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/CastLocationDataEvent.java @@ -57,6 +57,11 @@ public XivCombatant getSource() { return event.getSource(); } + @Override + public XivCombatant getAnimationTarget() { + return event.getTarget(); + } + @Override public String toString() { return "CastLocationDataEvent{" + diff --git a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/DescribesCastLocation.java b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/DescribesCastLocation.java index f9ee216f3a67..4962add85074 100644 --- a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/DescribesCastLocation.java +++ b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/events/DescribesCastLocation.java @@ -2,6 +2,7 @@ import gg.xp.reevent.events.Event; import gg.xp.xivsupport.models.Position; +import gg.xp.xivsupport.models.XivCombatant; import javax.annotation.Nullable; @@ -31,6 +32,8 @@ public interface DescribesCastLocation other) { + this.event = event; + this.pos = other.getPos(); + this.heading = other.getHeadingOnly(); + this.animationTarget = animationTarget; + } + + public SnapshotLocationDataEvent(AbilityUsedEvent event, @Nullable XivCombatant animationTarget, Position pos) { + this.event = event; + this.pos = pos; + this.heading = null; + this.animationTarget = animationTarget; + } + + public SnapshotLocationDataEvent(AbilityUsedEvent event, @Nullable XivCombatant animationTarget, double heading) { + this.event = event; + this.pos = null; + this.heading = heading; + this.animationTarget = animationTarget; + } + + @Deprecated // Use constructors with animationTarget public SnapshotLocationDataEvent(AbilityUsedEvent event, DescribesCastLocation other) { this.event = event; this.pos = other.getPos(); this.heading = other.getHeadingOnly(); + this.animationTarget = null; } + @Deprecated // Use constructors with animationTarget public SnapshotLocationDataEvent(AbilityUsedEvent event, Position pos) { this.event = event; this.pos = pos; this.heading = null; + this.animationTarget = null; } + @Deprecated // Use constructors with animationTarget public SnapshotLocationDataEvent(AbilityUsedEvent event, double heading) { this.event = event; this.pos = null; this.heading = heading; + this.animationTarget = null; } - + @Override public AbilityUsedEvent originalEvent() { return event; @@ -63,12 +92,18 @@ public XivCombatant getSource() { return event.getSource(); } + @Override + public @Nullable XivCombatant getAnimationTarget() { + return animationTarget; + } + @Override public String toString() { return "SnapshotLocationDataEvent{" + "id=" + event.getAbility().getId() + ", pos=" + pos + ", heading=" + heading + + ", animTgt=" + animationTarget + '}'; } } diff --git a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/FieldMapper.java b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/FieldMapper.java index f68b45c7187f..603176c38260 100644 --- a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/FieldMapper.java +++ b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/FieldMapper.java @@ -54,7 +54,7 @@ public int getInt(K key) { public @Nullable Long getOptionalHex(K key) { String rawStr = raw.get(key); - if (rawStr.isEmpty()) { + if (rawStr == null || rawStr.isEmpty()) { return null; } return Long.parseLong(rawStr, 16); @@ -62,7 +62,7 @@ public int getInt(K key) { public @Nullable Long getOptionalLong(K key) { String rawStr = raw.get(key); - if (rawStr.isEmpty()) { + if (rawStr == null || rawStr.isEmpty()) { return null; } return Long.parseLong(rawStr, 10); @@ -70,12 +70,20 @@ public int getInt(K key) { public @Nullable Double getOptionalDouble(K key) { String rawStr = raw.get(key); - if (rawStr.isEmpty()) { + if (rawStr == null || rawStr.isEmpty()) { return null; } return Double.parseDouble(rawStr); } + public @Nullable XivCombatant getOptionalEntity(K key) { + Long idMaybe = getOptionalHex(key); + if (idMaybe == null) { + return null; + } + return getEntity(idMaybe); + } + public int fieldCount() { return rawLineSplit.length; } diff --git a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line263Parser.java b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line263Parser.java index aba96d541d87..fba67595b49b 100644 --- a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line263Parser.java +++ b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line263Parser.java @@ -44,6 +44,7 @@ protected Event convert(FieldMapper fields, int lineNumber, ZonedDateTim if (match == null) { return null; } + // Logic: Ignore the position info if there is a real target for the cast, since we know that it is unit targeted in that case. if ((match.getTarget().isEnvironment() || match.getTarget().equals(match.getSource())) && match.getSource().getId() == entity diff --git a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line264Parser.java b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line264Parser.java index 7283b4609fd0..e0b8f7d87d82 100644 --- a/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line264Parser.java +++ b/xivsupport/src/main/java/gg/xp/xivsupport/events/actlines/parsers/Line264Parser.java @@ -7,7 +7,9 @@ import gg.xp.xivsupport.events.actlines.events.DescribesCastLocation; import gg.xp.xivsupport.events.actlines.events.SnapshotLocationDataEvent; import gg.xp.xivsupport.models.Position; +import gg.xp.xivsupport.models.XivCombatant; import org.picocontainer.PicoContainer; +import org.slf4j.LoggerFactory; import java.time.ZonedDateTime; import java.util.ArrayList; @@ -24,7 +26,7 @@ public Line264Parser(PicoContainer container) { } enum Fields { - entityId, abilityId, sequence, hasData, x, y, z, rotation + entityId, abilityId, sequence, hasPositionMaybe, x, y, z, rotation, animationTargetId } private final Map> lastAbilityByEntity = new HashMap<>(); @@ -66,12 +68,17 @@ protected Event convert(FieldMapper fields, int lineNumber, ZonedDateTim && firstMatch.getAbility().getId() == ability && firstMatch.getSequenceId() == sequenceId) { + // Animation Target Id + // TODO: backwards compat? make sure this doesn't catch the hash + XivCombatant animationTarget = fields.getOptionalEntity(Fields.animationTargetId); + LoggerFactory.getLogger(Line264Parser.class).info("animation target: {}", animationTarget); + // Cast location/angle // First, check if the line indicates that such data is actually present. - int hasData = fields.getInt(Fields.hasData); + int hasPositionMaybe = fields.getInt(Fields.hasPositionMaybe); SnapshotLocationDataEvent slde; // 0 = no data, 1 = data, 256 = error - if (hasData == 1) { + if (hasPositionMaybe == 1) { double x = fields.getDouble(Fields.x); double y = fields.getDouble(Fields.y); double z = fields.getDouble(Fields.z); @@ -80,20 +87,25 @@ protected Event convert(FieldMapper fields, int lineNumber, ZonedDateTim AbilityCastStart precursor = firstMatch.getPrecursor(); DescribesCastLocation castLocation; if (precursor != null && (castLocation = precursor.getLocationInfo()) != null && castLocation.getPos() != null) { - slde = new SnapshotLocationDataEvent(firstMatch, castLocation); - } - else if (h == 0.0) { - slde = null; + slde = new SnapshotLocationDataEvent(firstMatch, animationTarget, castLocation); } else { - slde = new SnapshotLocationDataEvent(firstMatch, h); + slde = new SnapshotLocationDataEvent(firstMatch, animationTarget, h); } } else { Position pos = new Position(x, y, z, h); - slde = new SnapshotLocationDataEvent(firstMatch, pos); + slde = new SnapshotLocationDataEvent(firstMatch, animationTarget, pos); } - if (slde != null) { + // Associate back to all events + allMatches.forEach(match -> match.setLocationInfo(slde)); + return slde; + } + else { + Double h = fields.getOptionalDouble(Fields.rotation); + // Backwards compat with old OP + if (h != null) { + slde = new SnapshotLocationDataEvent(firstMatch, animationTarget, h); // Associate back to all events allMatches.forEach(match -> match.setLocationInfo(slde)); return slde; diff --git a/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/CastFinishedOmen.java b/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/CastFinishedOmen.java index 30ca9dfb38c9..a9a058319cd3 100644 --- a/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/CastFinishedOmen.java +++ b/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/CastFinishedOmen.java @@ -59,8 +59,9 @@ public Instant happensAt() { return pos; } Double heading = locInfo.getHeadingOnly(); - if (heading != null && sourcePosSnapshot != null) { - return sourcePosSnapshot.facing(heading); + Position basis = locInfo.getAnimationTarget().getPos(); + if (heading != null && basis != null) { + return basis.facing(heading); } } if (info.type().locationType() == OmenLocationType.CASTER) { @@ -75,7 +76,11 @@ public Instant happensAt() { if (sourcePosSnapshot == null) { return null; } - return sourcePosSnapshot.facing(aue.getTarget().getPos()); + Position faceTowards = aue.getTarget().getPos(); + if (faceTowards != null) { + return sourcePosSnapshot.facing(faceTowards); + } + return null; } else { return aue.getTarget().getPos(); diff --git a/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/InstantOmen.java b/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/InstantOmen.java index 404939f9ee81..6558121c2c40 100644 --- a/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/InstantOmen.java +++ b/xivsupport/src/main/java/gg/xp/xivsupport/gui/map/omen/InstantOmen.java @@ -51,6 +51,10 @@ public Instant happensAt() { if (pos != null) { return pos; } + @Nullable XivCombatant animTgt = locInfo.getAnimationTarget(); + if (animTgt != null) { + sourcePos = animTgt.getPos(); + } Double heading = locInfo.getHeadingOnly(); if (heading != null && sourcePos != null) { return sourcePos.facing(heading); diff --git a/xivsupport/src/test/java/gg/xp/xivsupport/events/actlines/Line264Test.java b/xivsupport/src/test/java/gg/xp/xivsupport/events/actlines/Line264Test.java index 0bf9b0cff1e9..8e9c3b72409a 100644 --- a/xivsupport/src/test/java/gg/xp/xivsupport/events/actlines/Line264Test.java +++ b/xivsupport/src/test/java/gg/xp/xivsupport/events/actlines/Line264Test.java @@ -4,6 +4,7 @@ import gg.xp.reevent.events.TestEventCollector; import gg.xp.xivsupport.events.ACTLogLineEvent; import gg.xp.xivsupport.events.actlines.events.SnapshotLocationDataEvent; +import gg.xp.xivsupport.models.Position; import gg.xp.xivsupport.sys.XivMain; import org.picocontainer.MutablePicoContainer; import org.testng.Assert; @@ -14,7 +15,7 @@ public class Line264Test { @Test - public void positiveTest() { + public void positiveHeadingOnlyTest() { MutablePicoContainer container = XivMain.testingMasterInit(); TestEventCollector coll = new TestEventCollector(); EventDistributor dist = container.getComponent(EventDistributor.class); @@ -37,7 +38,38 @@ public void positiveTest() { Assert.assertEquals(event.getSource().getId(), 0x4000619DL); Assert.assertNull(event.getPos()); Assert.assertEquals(event.getHeadingOnly(), 1.570); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertNull(event.getAnimationTarget()); } + + @Test + public void positiveHeadingOnly2Test() { + MutablePicoContainer container = XivMain.testingMasterInit(); + TestEventCollector coll = new TestEventCollector(); + EventDistributor dist = container.getComponent(EventDistributor.class); + dist.registerHandler(coll); + String castLine1 = "21|2023-11-04T17:53:45.2940000+01:00|4000619D|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-16.15|125.01|-10.00|1.57|00000662|0|0|b13a891c224580d2"; + String locationLine1 = "264|2023-11-04T17:53:45.2940000+01:00|4000619D|8BC0|00000662|0||||1.570|7e82907c710ee781"; + String castLine2 = "21|2023-11-04T17:53:45.2940000+01:00|4000619E|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||16.42|75.08|-10.00|-1.59|00000663|0|0|21ca6acb29c4082f"; + String locationLine2 = "264|2023-11-04T17:53:45.2940000+01:00|4000619E|8BC0|00000663|0||||-1.589|711909381311a052"; + String castLine3 = "21|2023-11-04T17:53:45.2940000+01:00|4000619F|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-13.13|103.81|-10.00|3.14|00000664|0|0|3dd4dd4e468cd0a2"; + String locationLine3 = "264|2023-11-04T17:53:45.2940000+01:00|4000619F|8BC0|00000664|0||||3.141|fc680d77fb5897f1"; + // Intentionally submit out-of-order + dist.acceptEvent(new ACTLogLineEvent(castLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine3)); + dist.acceptEvent(new ACTLogLineEvent(locationLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine3)); + List events = coll.getEventsOf(SnapshotLocationDataEvent.class); + SnapshotLocationDataEvent event = events.get(0); + Assert.assertEquals(event.getSource().getId(), 0x4000619DL); + Assert.assertNull(event.getPos()); + Assert.assertEquals(event.getHeadingOnly(), 1.570); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertNull(event.getAnimationTarget()); + } + @Test public void outOfOrderTest() { MutablePicoContainer container = XivMain.testingMasterInit(); @@ -62,5 +94,146 @@ public void outOfOrderTest() { Assert.assertEquals(event.getSource().getId(), 0x4000619DL); Assert.assertNull(event.getPos()); Assert.assertEquals(event.getHeadingOnly(), 1.570); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertNull(event.getAnimationTarget()); + } + + @Test + public void positionTest() { + MutablePicoContainer container = XivMain.testingMasterInit(); + TestEventCollector coll = new TestEventCollector(); + EventDistributor dist = container.getComponent(EventDistributor.class); + dist.registerHandler(coll); + String castLine1 = "21|2023-11-04T17:53:45.2940000+01:00|4000619D|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-16.15|125.01|-10.00|1.57|00000662|0|0|b13a891c224580d2"; + String locationLine1 = "264|2023-11-04T17:53:45.2940000+01:00|4000619D|8BC0|00000662|1|1.000|2.000|3.000|1.570|7e82907c710ee781"; + String castLine2 = "21|2023-11-04T17:53:45.2940000+01:00|4000619E|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||16.42|75.08|-10.00|-1.59|00000663|0|0|21ca6acb29c4082f"; + String locationLine2 = "264|2023-11-04T17:53:45.2940000+01:00|4000619E|8BC0|00000663|1|0.000|0.000|0.000|-1.589|711909381311a052"; + String castLine3 = "21|2023-11-04T17:53:45.2940000+01:00|4000619F|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-13.13|103.81|-10.00|3.14|00000664|0|0|3dd4dd4e468cd0a2"; + String locationLine3 = "264|2023-11-04T17:53:45.2940000+01:00|4000619F|8BC0|00000664|1|0.000|0.000|0.000|3.141|fc680d77fb5897f1"; + // Intentionally submit out-of-order + dist.acceptEvent(new ACTLogLineEvent(castLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine3)); + dist.acceptEvent(new ACTLogLineEvent(locationLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine3)); + List events = coll.getEventsOf(SnapshotLocationDataEvent.class); + SnapshotLocationDataEvent event = events.get(0); + Assert.assertEquals(event.getSource().getId(), 0x4000619DL); + Assert.assertEquals(event.getPos(), new Position(1.0, 2.0, 3.0, 1.570)); + Assert.assertNull(event.getHeadingOnly()); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertNull(event.getAnimationTarget()); + } + + @Test + public void positiveHeadingOnlyNewTest() { + MutablePicoContainer container = XivMain.testingMasterInit(); + TestEventCollector coll = new TestEventCollector(); + EventDistributor dist = container.getComponent(EventDistributor.class); + dist.registerHandler(coll); + String castLine1 = "21|2023-11-04T17:53:45.2940000+01:00|4000619D|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-16.15|125.01|-10.00|1.57|00000662|0|0|b13a891c224580d2"; + String locationLine1 = "264|2023-11-04T17:53:45.2940000+01:00|4000619D|8BC0|00000662|1|0.000|0.000|0.000|1.570|1234ABCD|7e82907c710ee781"; + String castLine2 = "21|2023-11-04T17:53:45.2940000+01:00|4000619E|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||16.42|75.08|-10.00|-1.59|00000663|0|0|21ca6acb29c4082f"; + String locationLine2 = "264|2023-11-04T17:53:45.2940000+01:00|4000619E|8BC0|00000663|1|0.000|0.000|0.000|-1.589|1234ABCD|711909381311a052"; + String castLine3 = "21|2023-11-04T17:53:45.2940000+01:00|4000619F|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-13.13|103.81|-10.00|3.14|00000664|0|0|3dd4dd4e468cd0a2"; + String locationLine3 = "264|2023-11-04T17:53:45.2940000+01:00|4000619F|8BC0|00000664|1|0.000|0.000|0.000|3.141|1234ABCD|fc680d77fb5897f1"; + // Intentionally submit out-of-order + dist.acceptEvent(new ACTLogLineEvent(castLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine3)); + dist.acceptEvent(new ACTLogLineEvent(locationLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine3)); + List events = coll.getEventsOf(SnapshotLocationDataEvent.class); + SnapshotLocationDataEvent event = events.get(0); + Assert.assertEquals(event.getSource().getId(), 0x4000619DL); + Assert.assertNull(event.getPos()); + Assert.assertEquals(event.getHeadingOnly(), 1.570); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertEquals(event.getAnimationTarget().getId(), 0x1234ABCDL); + } + @Test + public void positiveHeadingOnly2NewTest() { + MutablePicoContainer container = XivMain.testingMasterInit(); + TestEventCollector coll = new TestEventCollector(); + EventDistributor dist = container.getComponent(EventDistributor.class); + dist.registerHandler(coll); + String castLine1 = "21|2023-11-04T17:53:45.2940000+01:00|4000619D|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-16.15|125.01|-10.00|1.57|00000662|0|0|b13a891c224580d2"; + String locationLine1 = "264|2023-11-04T17:53:45.2940000+01:00|4000619D|8BC0|00000662|0||||1.570|1234ABCD|7e82907c710ee781"; + String castLine2 = "21|2023-11-04T17:53:45.2940000+01:00|4000619E|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||16.42|75.08|-10.00|-1.59|00000663|0|0|21ca6acb29c4082f"; + String locationLine2 = "264|2023-11-04T17:53:45.2940000+01:00|4000619E|8BC0|00000663|0||||-1.589|1234ABCD|711909381311a052"; + String castLine3 = "21|2023-11-04T17:53:45.2940000+01:00|4000619F|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-13.13|103.81|-10.00|3.14|00000664|0|0|3dd4dd4e468cd0a2"; + String locationLine3 = "264|2023-11-04T17:53:45.2940000+01:00|4000619F|8BC0|00000664|0||||3.141|1234ABCD|fc680d77fb5897f1"; + // Intentionally submit out-of-order + dist.acceptEvent(new ACTLogLineEvent(castLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine3)); + dist.acceptEvent(new ACTLogLineEvent(locationLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine3)); + List events = coll.getEventsOf(SnapshotLocationDataEvent.class); + SnapshotLocationDataEvent event = events.get(0); + Assert.assertEquals(event.getSource().getId(), 0x4000619DL); + Assert.assertNull(event.getPos()); + Assert.assertEquals(event.getHeadingOnly(), 1.570); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertEquals(event.getAnimationTarget().getId(), 0x1234ABCDL); + } + + @Test + public void outOfOrderNewTest() { + MutablePicoContainer container = XivMain.testingMasterInit(); + TestEventCollector coll = new TestEventCollector(); + EventDistributor dist = container.getComponent(EventDistributor.class); + dist.registerHandler(coll); + String castLine1 = "21|2023-11-04T17:53:45.2940000+01:00|4000619D|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-16.15|125.01|-10.00|1.57|00000662|0|0|b13a891c224580d2"; + String castLine3 = "21|2023-11-04T17:53:45.2940000+01:00|4000619F|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-13.13|103.81|-10.00|3.14|00000664|0|0|3dd4dd4e468cd0a2"; + String locationLine1 = "264|2023-11-04T17:53:45.2940000+01:00|4000619D|8BC0|00000662|1|0.000|0.000|0.000|1.570|1234ABCD|7e82907c710ee781"; + String castLine2 = "21|2023-11-04T17:53:45.2940000+01:00|4000619E|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||16.42|75.08|-10.00|-1.59|00000663|0|0|21ca6acb29c4082f"; + String locationLine2 = "264|2023-11-04T17:53:45.2940000+01:00|4000619E|8BC0|00000663|1|0.000|0.000|0.000|-1.589|1234ABCD|711909381311a052"; + String locationLine3 = "264|2023-11-04T17:53:45.2940000+01:00|4000619F|8BC0|00000664|1|0.000|0.000|0.000|3.141|1234ABCD|fc680d77fb5897f1"; + // Intentionally submit out-of-order + dist.acceptEvent(new ACTLogLineEvent(castLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine3)); + dist.acceptEvent(new ACTLogLineEvent(locationLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine3)); + List events = coll.getEventsOf(SnapshotLocationDataEvent.class); + SnapshotLocationDataEvent event = events.get(0); + Assert.assertEquals(event.getSource().getId(), 0x4000619DL); + Assert.assertNull(event.getPos()); + Assert.assertEquals(event.getHeadingOnly(), 1.570); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertEquals(event.getAnimationTarget().getId(), 0x1234ABCDL); + } + + @Test + public void positionNewTest() { + MutablePicoContainer container = XivMain.testingMasterInit(); + TestEventCollector coll = new TestEventCollector(); + EventDistributor dist = container.getComponent(EventDistributor.class); + dist.registerHandler(coll); + String castLine1 = "21|2023-11-04T17:53:45.2940000+01:00|4000619D|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-16.15|125.01|-10.00|1.57|00000662|0|0|b13a891c224580d2"; + String locationLine1 = "264|2023-11-04T17:53:45.2940000+01:00|4000619D|8BC0|00000662|1|1.000|2.000|3.000|1.570|1234ABCD|7e82907c710ee781"; + String castLine2 = "21|2023-11-04T17:53:45.2940000+01:00|4000619E|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||16.42|75.08|-10.00|-1.59|00000663|0|0|21ca6acb29c4082f"; + String locationLine2 = "264|2023-11-04T17:53:45.2940000+01:00|4000619E|8BC0|00000663|1|0.000|0.000|0.000|-1.589|1234ABCD|711909381311a052"; + String castLine3 = "21|2023-11-04T17:53:45.2940000+01:00|4000619F|Twister|8BC0|unknown_8bc0|E0000000||0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|0|||||||||||44|44|0|10000|||-13.13|103.81|-10.00|3.14|00000664|0|0|3dd4dd4e468cd0a2"; + String locationLine3 = "264|2023-11-04T17:53:45.2940000+01:00|4000619F|8BC0|00000664|1|0.000|0.000|0.000|3.141|1234ABCD|fc680d77fb5897f1"; + // Intentionally submit out-of-order + dist.acceptEvent(new ACTLogLineEvent(castLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine1)); + dist.acceptEvent(new ACTLogLineEvent(castLine3)); + dist.acceptEvent(new ACTLogLineEvent(locationLine2)); + dist.acceptEvent(new ACTLogLineEvent(locationLine3)); + List events = coll.getEventsOf(SnapshotLocationDataEvent.class); + SnapshotLocationDataEvent event = events.get(0); + Assert.assertEquals(event.getSource().getId(), 0x4000619DL); + Assert.assertEquals(event.getPos(), new Position(1.0, 2.0, 3.0, 1.570)); + Assert.assertNull(event.getHeadingOnly()); + Assert.assertEquals(event.getBestHeading(), 1.570); + Assert.assertEquals(event.getAnimationTarget().getId(), 0x1234ABCDL); } }