Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a warding processor #3

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
82 changes: 55 additions & 27 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -40,27 +40,27 @@
</repository>
</repositories>
<dependencies>
<!--
<dependency>
<groupId>com.github.skadistats</groupId>
<artifactId>clarity</artifactId>
<version>master-SNAPSHOT</version>
</dependency>
-->
<!--
<dependency>
<groupId>com.github.skadistats</groupId>
<artifactId>clarity</artifactId>
<version>70956f5a89fca56f3a292e739ea3eda96a33fd8c</version>
</dependency>
-->
<!--
<dependency>
<groupId>com.github.skadistats</groupId>
<artifactId>clarity</artifactId>
<version>master-SNAPSHOT</version>
</dependency>
-->
<!--
<dependency>
<groupId>com.github.skadistats</groupId>
<artifactId>clarity</artifactId>
<version>70956f5a89fca56f3a292e739ea3eda96a33fd8c</version>
</dependency>
-->

<dependency>
<groupId>com.skadistats</groupId>
<artifactId>clarity</artifactId>
<version>2.1</version>
</dependency>

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
Expand All @@ -71,24 +71,52 @@
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>yasp.Main</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
<!-- this is used by clarity-example and clarity-analyzer -->
<plugin>
<groupId>com.jolira</groupId>
<artifactId>onejar-maven-plugin</artifactId>
<version>1.4.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
<goal>one-jar</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>yasp.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
<!-- for some reason the shade-plugin doesn't work well with clarity processors.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

preferably we should find a way to avoid needing to swap this dependency.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took like 3 hours today trying to make this work. Maybe @spheenik can give some guidance because the shaded jar will crash upon populating the processors. It seems it cannot find the annotations or whatever.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IIRC this produces a jar with a different name. We have to make sure the output file is named the same, or update the Dockerfile to start the correct file.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem here is that there is an annotation scanner in clarity (org.atteo.classindex) that scans annotations on compile time, and produces a file META-INF/annotations/skadistats.clarity.event.Provides which contains a list of all classes with Provides-annotations. If you use shade, you got to make sure this file is present and correctly merged.

<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>yasp.Main</mainClass>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
</project>
64 changes: 45 additions & 19 deletions src/main/java/yasp/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,35 +2,61 @@

import java.io.IOException;
import java.io.InputStream;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;

public class Main {

public static void main(String[] args) {
try {

if (args.length > 0 && args[0].equals("--file")) { System.exit(parse(args[1])); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix brace spacing

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be honest, if you want to include the Main class, I'd rather have a proper arg-parsing, like Apache Commons CLI or similar.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current code only has the server case. i assume you added these additional startup methods to make testing easier. Previously, I just started the server and then used curl to POST a replay to it. Up to you if you want to keep them around.

else if (args.length >0 && args[0].equals("--")) { System.exit(parseStream(System.in, System.out)); }
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fix >0 spacing

else { startServer(args); }
}
catch (Exception e) {
e.printStackTrace();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do you need to catch the exception here? If we have one, we should crash since the startup is incorrect.

}
}

public static void startServer(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(Integer.valueOf(args.length > 0 ? args[0] : "5600")), 0);
server.createContext("/", new MyHandler());
server.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(4));
server.start();
}

public static void main(String[] args) throws Exception {
HttpServer server = HttpServer.create(new InetSocketAddress(Integer.valueOf(args.length > 0 ? args[0] : "5600")), 0);
server.createContext("/", new MyHandler());
server.setExecutor(java.util.concurrent.Executors.newFixedThreadPool(4));
server.start();
static int parseStream(InputStream is, OutputStream os) throws IOException {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think methods should have visibility declared.

try {
new Parse(is, os);
}
catch (Exception e)
{
e.printStackTrace();
return -1;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra space

}
finally {
is.close();
os.close();
}

return 0;
}

static int parse(String replay_file) throws Exception {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

call this parseFile

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use camelCase

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and call it fileName

System.out.print(String.format("Parsing file %s", replay_file));
return parseStream(new FileInputStream(replay_file), System.out);
}

static class MyHandler implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
t.sendResponseHeaders(200, 0);
InputStream is = t.getRequestBody();
OutputStream os = t.getResponseBody();
try {
new Parse(is, os);
}
catch (Exception e)
{
e.printStackTrace();
}
os.close();
}
@Override
public void handle(HttpExchange t) throws IOException {
t.sendResponseHeaders(200, 0);
parseStream(t.getRequestBody(), t.getResponseBody());
}
}
}
110 changes: 58 additions & 52 deletions src/main/java/yasp/Parse.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,13 @@
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Iterator;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import yasp.processors.warding.OnWardCountered;
import yasp.processors.warding.OnWardExpired;
import yasp.processors.warding.OnWardPlaced;

public class Parse {
private class Entry {
Expand Down Expand Up @@ -96,6 +100,7 @@ public Entry(Integer time) {
this.time = time;
}
}

float INTERVAL = 1;
float nextInterval = 0;
Integer time = 0;
Expand All @@ -106,7 +111,7 @@ public Entry(Integer time) {
private Gson g = new Gson();
HashMap<String, Integer> name_to_slot = new HashMap<String, Integer>();
HashMap<Integer, Integer> slot_to_playerslot = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> cosmeticsMap = new HashMap<Integer, Integer>();
HashMap<Integer, Integer> cosmeticsMap = new HashMap<Integer, Integer>();
InputStream is = null;
OutputStream os = null;

Expand All @@ -120,7 +125,6 @@ public Parse(InputStream input, OutputStream output) throws IOException
System.err.format("total time taken: %s\n", (tMatch) / 1000.0);
}


public void output(Entry e) {
try {
this.os.write((g.toJson(e) + "\n").getBytes());
Expand Down Expand Up @@ -291,15 +295,11 @@ public void onCombatLogEntry(Context ctx, CombatLogEntry cle) {
}

@OnEntityEntered
public void onEntityEntered(Context ctx, Entity e) {
processEntity(ctx, e, false);
}

@OnEntityLeft
public void onEntityLeft(Context ctx, Entity e) {
processEntity(ctx, e, true);
public void onEntityExistenceChanged(Context ctx, Entity e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the annotation here is still OnEntityLeft, I think the method name should reflect that.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, if this is only here for cosmetics entities, you should probably just keep the OnEntityEntered and remove OnEntityLeft (assuming ward-related annotated methods will be called separately)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah that could be a good way to catch this.

processEntity(ctx, e);
}

@UsesEntities
@OnTickStart
public void onTickStart(Context ctx, boolean synthetic) {
Expand Down Expand Up @@ -459,6 +459,19 @@ public void onTickStart(Context ctx, boolean synthetic) {
}
}
}

@OnWardCountered
public void onWardCountered(Context ctx, Entity e, String killer_hero_name) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

camelCase

Entry wardEntry = buildWardEntry(ctx, e);
wardEntry.attackername = killer_hero_name;
output(wardEntry);
}

@OnWardExpired
@OnWardPlaced
public void onWardExistenceChanged(Context ctx, Entity e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you unify this method with the previous one and detect from context which case it is?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think I can do that as the signatures are different.

output(buildWardEntry(ctx, e));
}

public <T> T getEntityProperty(Entity e, String property, Integer idx) {
try {
Expand All @@ -476,51 +489,44 @@ public <T> T getEntityProperty(Entity e, String property, Integer idx) {
}
}

public void processEntity(Context ctx, Entity e, boolean entityLeft)
public void processEntity(Context ctx, Entity e)
{
//CDOTA_NPC_Observer_Ward
//CDOTA_NPC_Observer_Ward_TrueSight
//s1 "DT_DOTA_NPC_Observer_Ward"
//s1 "DT_DOTA_NPC_Observer_Ward_TrueSight"
boolean isObserver = e.getDtClass().getDtName().equals("CDOTA_NPC_Observer_Ward");
boolean isSentry = e.getDtClass().getDtName().equals("CDOTA_NPC_Observer_Ward_TrueSight");
if (isObserver || isSentry) {
//System.err.println(e);
Entry entry = new Entry(time);
Integer x = getEntityProperty(e, "CBodyComponent.m_cellX", null);
Integer y = getEntityProperty(e, "CBodyComponent.m_cellY", null);
Integer z = getEntityProperty(e, "CBodyComponent.m_cellZ", null);
Integer[] pos = {x, y};
entry.x = x;
entry.y = y;
entry.z = z;
if (entityLeft)
if (e.getDtClass().getDtName().equals("CDOTAWearableItem")) {
Integer accountId = getEntityProperty(e, "m_iAccountID", null);
Integer itemDefinitionIndex = getEntityProperty(e, "m_iItemDefinitionIndex", null);
//System.err.format("%s,%s\n", accountId, itemDefinitionIndex);
if (accountId > 0)
{
entry.type = isObserver ? "obs_left" : "sen_left";
cosmeticsMap.put(itemDefinitionIndex, accountId);
}
else
{
entry.type = isObserver ? "obs" : "sen";
}
entry.key = Arrays.toString(pos);
entry.entityleft = entityLeft;
entry.ehandle = e.getHandle();
//System.err.println(entry.key);
Integer owner = getEntityProperty(e, "m_hOwnerEntity", null);
Entity ownerEntity = ctx.getProcessor(Entities.class).getByHandle(owner);
entry.slot = ownerEntity != null ? (Integer) getEntityProperty(ownerEntity, "m_iPlayerID", null) : null;
//2/3 radiant/dire
//entry.team = e.getProperty("m_iTeamNum");
output(entry);
}
else if (e.getDtClass().getDtName().equals("CDOTAWearableItem")) {
Integer accountId = getEntityProperty(e, "m_iAccountID", null);
Integer itemDefinitionIndex = getEntityProperty(e, "m_iItemDefinitionIndex", null);
//System.err.format("%s,%s\n", accountId, itemDefinitionIndex);
if (accountId > 0)
{
cosmeticsMap.put(itemDefinitionIndex, accountId);
}
}
}
}

Entry buildWardEntry(Context ctx, Entity e) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add method visibility

Entry entry = new Entry(time);
boolean isObserver = e.getDtClass().getDtName().equals("CDOTA_NPC_Observer_Ward");
Integer x = getEntityProperty(e, "CBodyComponent.m_cellX", null);
Integer y = getEntityProperty(e, "CBodyComponent.m_cellY", null);
Integer z = getEntityProperty(e, "CBodyComponent.m_cellZ", null);
Integer life_state = getEntityProperty(e, "m_lifeState", null);
Integer[] pos = {x, y};
entry.x = x;
entry.y = y;
entry.z = z;
entry.type = isObserver ? "obs" : "sen";
entry.entityleft = life_state == 1;
entry.key = Arrays.toString(pos);
entry.ehandle = e.getHandle();

if (entry.entityleft)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use braces for all if statements

entry.type += "_left";

//System.err.println(entry.key);
Integer owner = getEntityProperty(e, "m_hOwnerEntity", null);
Entity ownerEntity = ctx.getProcessor(Entities.class).getByHandle(owner);
entry.slot = ownerEntity != null ? (Integer) getEntityProperty(ownerEntity, "m_iPlayerID", null) : null;
//2/3 radiant/dire
//entry.team = e.getProperty("m_iTeamNum");
return entry;
}
}
19 changes: 19 additions & 0 deletions src/main/java/yasp/processors/warding/OnWardCountered.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package yasp.processors.warding;

import java.lang.annotation.Annotation;

import skadistats.clarity.event.UsagePointMarker;
import skadistats.clarity.event.UsagePointType;
import skadistats.clarity.model.Entity;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
@UsagePointMarker(value = UsagePointType.EVENT_LISTENER, parameterClasses = { Entity.class, String.class })
public @interface OnWardCountered {
}

19 changes: 19 additions & 0 deletions src/main/java/yasp/processors/warding/OnWardExpired.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package yasp.processors.warding;

import java.lang.annotation.Annotation;

import skadistats.clarity.event.UsagePointMarker;
import skadistats.clarity.event.UsagePointType;
import skadistats.clarity.model.Entity;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target(value = ElementType.METHOD)
@UsagePointMarker(value = UsagePointType.EVENT_LISTENER, parameterClasses = { Entity.class })
public @interface OnWardExpired {
}

Loading