Third Party Developer Blog

Jan
6

CREST Updates For January 2016

CCP FoxFour | 2016-01-06 16:45 | Comments

Hello and welcome to a new year! Hopefully you all had a wonderful holidays and are enjoying the new year. I was fortunate enough that during the last few weeks the office was fairly empty around here and I was able to buckle down and get a large amount of work finished for CREST. Most of the following features were already a work in progress and just needed me to actually sit down to polish them off and test them. The following are also all available right now on Singularity and should be shipped to Tranquility on Tuesday the 12th of January 2016 with the YC 118.1 release. Without further rambling let's dig into the details of what is coming.

Alliance Resources

The alliance resources were a little bit of a mess. They were one of the first resources I ever wrote and contained a few glaring mistakes. First and foremost was this odd nesting of hrefs in hrefs. Here is how an item in the v1 of the Alliances collection looked:

{
    "href": {
        "id_str": "386292982",
        "shortName": "-10.0",
        "href": "https://public-crest.eveonline.com/alliances/386292982/",
        "id": 386292982,
        "name": "Pandemic Legion"
    }
},

That href inside of a href was just... wrong. Fixing this means making a backwards incompatible change so I created a v2 of the Alliances collection and deprecated v1. Be sure to read https://eveonline-third-party-documentation.readthedocs.org/en/latest/crest/versioning/ for more information on versioning. Essentially though if you are not sending an Accept header you are instantly going to get v2 when this ships to Tranquility  - which will probably break your stuff. If you're using v1 and sending an Accept header the response is going to contain an X-Deprecated header and your application should alert you to this.

The v1 resource will be removed later this year.

Items in v2 look something like this:

{
    "id_str": "99000004",
    "shortName": "ONE-A",
    "href": "http://crest.regner.dev/alliances/99000004/",
    "id": 99000004,
    "name": "One One Corporation Alliance"
}

I also fixed a defect where if an alliance executor corporation didn't exist, which is apparently possible, the Alliance resource would fail to parse. To fix that I have made the executorCorporation field optional. If you were getting 503 errors on some alliances in the past try them again after this release.

Universe Resources

Some fairly straight forward changes here. It used to be that to get all the solar systems in the universe you would have to start with the Regions collection, then get every region which would link to constellations, then get every constellation which would link to solar systems, and then get every solar system. This was usually OK because, if you wanted universe data, you usually wanted all of it. However this isn't always the case so I have added a Constellations collection and a Systems collection. Each is linked from the root of CREST and contains all of the regions or solar systems. The other nice advantage to this is it paves the way to having search for these resources since search should go on the collection.

Along with these changes I added an ID field to regions in the Regions collection and individual Region resource. The same was done for constellations and solar systems. So you should have no problem getting region, constellation, or solar system ID numbers without having to do some odd string parsing.

Personal Contacts

The ability to read a characters contacts from CREST is actually live on TQ right now. Funny that. There is a slight problem however in that if you have an alliance in your contacts it breaks. So this release fixes that problem. Along with that however I have taken it a step further and have added the ability to ...  write personal contacts. YAY!

Here is a sample of how the Contacts resource looks:

{
  "totalCount_str": "2",
  "items": [
    {
      "standing": -10,
      "alliance": {
        "id_str": "99000003",
        "href": "http://crest.regner.dev/alliances/99000003/",
        "id": 99000003,
        "name": "One One Corporation Alliance"
      },
      "href": "http://crest.regner.dev/characters/90000001/contacts/99000003/",
      "contact": {
        "id_str": "99000003",
        "href": "http://crest.regner.dev/alliances/99000003/",
        "name": "One One Corporation Alliance",
        "id": 99000003
      },
      "contactType": "Alliance"
    },
    {
      "standing": 0,
      "character": {
        "name": "Two One",
        "corporation": {
          "name": "Two One Corporation",
          "isNPC": false,
          "href": "http://crest.regner.dev/corporations/98000002/",
          "id_str": "98000002",
          "logo": {
            "32x32": {
              "href": "https://imageserver.eveonline.com/Corporation/98000002_32.png"
            },
            "64x64": {
              "href": "https://imageserver.eveonline.com/Corporation/98000002_64.png"
            },
            "128x128": {
              "href": "https://imageserver.eveonline.com/Corporation/98000002_128.png"
            },
            "256x256": {
              "href": "https://imageserver.eveonline.com/Corporation/98000002_256.png"
            }
          },
          "id": 98000002
        },
        "isNPC": false,
        "href": "http://crest.regner.dev/characters/90000002/",
        "capsuleer": {
          "href": "http://crest.regner.dev/characters/90000002/capsuleer/"
        },
        "portrait": {
          "32x32": {
            "href": "https://imageserver.eveonline.com/Character/90000002_32.jpg"
          },
          "64x64": {
            "href": "https://imageserver.eveonline.com/Character/90000002_64.jpg"
          },
          "128x128": {
            "href": "https://imageserver.eveonline.com/Character/90000002_128.jpg"
          },
          "256x256": {
            "href": "https://imageserver.eveonline.com/Character/90000002_256.jpg"
          }
        },
        "id": 90000002,
        "id_str": "90000002"
      },
      "contact": {
        "id_str": "90000002",
        "href": "http://crest.regner.dev/characters/90000002/",
        "name": "Two One",
        "id": 90000002
      },
      "href": "http://crest.regner.dev/characters/90000001/contacts/90000002/",
      "contactType": "Character",
      "watched": false,
      "blocked": false
    }
  ],
  "pageCount": 1,
  "pageCount_str": "1",
  "totalCount": 2
}

I even made sure there was an alliance in there as proof that I fixed that. That is a GET request for contacts but how about a POST request:

{
  "standing": 10,
  "contactType": "Alliance"
  "contact": {
    "id_str": "99000003",
    "href": "http://crest.regner.dev/alliances/99000003/",
    "name": "One One Corporation Alliance",
    "id": 99000003
  },
}

Both the GET and the POST request should be sent to the Contacts collection resource (/characters/<characterID>/contacts/). What if you want to edit or delete an existing contact. Then you can do a PUT or DELETE request to the Contact resource (/characters/<characterID>/contacts/<contactID/). PUT requests match the POST requests just as PUT requests instead and to a different resource. DELETE requests are well... empty DELETE requests to the appropriate Contact resource.

Contacts will have a characterContactsRead and a characterContactsWrite scope.

Character Location

If you take a look at the Character resource you will find a fancy new href pointing to a CharacterLocation resource. This resource is a simple GET resource that returns the current solar system of a character with a 10 second cache. Here is a sample of how it looks:

{
  "solarSystem": {
    "id_str": "30000140",
    "href": "http://crest.regner.dev/solarsystems/30000140/",
    "id": 30000140,
    "name": "Maurasi"
  }
}

Very simple and straight forward. The entire solarSystem element is optional. Basically if the character is offline you will get a blank dictionary back. I hope to add more information to this in the future such as ship type or station if they are in one. For now however this is the basics of it.

While we have put a fair bit of effort into figuring out how to do this efficiently on our end the question does come up as to how do you know when to start and stop polling this resource. At this point in time we don't have a way of notifying you that a character has come online and you should start polling. So my recommendation is that if you're a wormhole mapping site you start polling it when a character visits your service and then stop when you get an empty dictionary back. Maybe with a few extra pokes to make sure it wasn't a quick disconnect or something. Would love to hear what solutions you all come up with though.

Market IDs

Continuing the addition of IDs to resources the market types collection has an added ID field for the type ID and the market groups collection has an added ID field for the market group ID. Simple but hopefully helpful.

Dogma Information

The most important thing to be aware of about this next section is that if information is missing or presented in an unclear way please give me a shout and I will do my best to update it. There are three parts to this addition. The first the the addition of the DogmaAttributes collection which contains a list of all Dogma attributes. The second is the DogmaEffects collection which, you guessed it, contains a list of all Dogma effects. The third and final piece is all types now have a dictionary element called dogma added to them that contains two other optional elements. The first is effects and the second is attributes. Fairly straight forward stuff.

The one kicker to this information to be aware of is the Dogma effects. The DogmaEffect resource for individual effects contains three elements of unique importance. the preExpression, postExpression, and modifierInfo. If I understand what others have told me modifierInfo is actually a new way for us to do the pre and post expressions. All new dogma effects created use the newer modifierInfo way of storing this data. At some point in the coming months there is a plan to change all existing Dogma effects over to this modifierInfo format. At that point I may very well remove pre and post expression from this resource. Just something to be aware of going forward.

Here is a Dogma expression with the modifierInfo:

{
  "effectCategory_str": "0",
  "postExpression_str": "17934",
  "isAssistance": false,
  "description": "",
  "isOffensive": false,
  "disallowAutoRepeat": false,
  "isWarpSafe": false,
  "published": false,
  "electronicChance": false,
  "rangeChance": false,
  "effectCategory": 0,
  "id_str": "6395",
  "postExpression": 17934,
  "modifierInfo": [
    {
      "domain": "shipID",
      "modifiedAttributeID": {
        "id_str": "767",
        "href": "http://public-crest-sisi.testeveonline.com/dogma/attributes/767/",
        "id": 767,
        "name": "trackingSpeedBonus"
      },
      ...
  ],
  "preExpression": 17933,
  "displayName": "",
  "preExpression_str": "17933",
  "id": 6395,
  "name": "shipBonusEwWeaponDisruptionStrengthAC1"
}

You can read more about Dogma, and also a bit about the new and old way of doing effects, here: https://eveonline-third-party-documentation.readthedocs.org/en/latest/dogma/overview/

Types

As explained in the Dogma information section above the Type resource has had a large amount of Dogma information added to them. While touching the types however I also added an ID element to the response. Should make life for those of you working with the SDE and CREST a little easier.

Here is an example of how it looks:

{
  "capacity": 0,
  "description": "Utilizes a combination of containment field emitters and redundancy systems to prevent critical system damage. \r\n\r\nGrants a bonus to resistance for shield, armor and hull.\r\n\r\nOnly one Damage Control can be activated at a given time.",
  "portionSize_str": "1",
  "iconID": 77,
  "portionSize": 1,
  "iconID_str": "77",
  "volume": 5,
  "dogma": {
    "attributes": [
      {
        "attribute": {
          "id_str": "6",
          "href": "http://public-crest-sisi.testeveonline.com/dogma/attributes/6/",
          "id": 6,
          "name": "capacitorNeed"
        },
        "value": 1
      },
      ...
    ],
    "effects": [
      {
        "effect": {
          "id_str": "11",
          "href": "http://public-crest-sisi.testeveonline.com/dogma/effects/11/",
          "id": 11,
          "name": "loPower"
        },
        "isDefault": false
      },
      ...
    ]
  },
  "radius": 1,
  "id_str": "521",
  "published": true,
  "mass": 5000,
  "id": 521,
  "name": "Basic Damage Control"
}

Autopilot Waypoints

This should be a really fun one for web sites such as Dotlan or wormhole mappers. You can now send a POST request to CREST and have an autopilot destination set on the client.

If this is done however it will cause the autopilot to turn off if it is turned on for the client. There are a few reasons for this, one of which being a pilot not getting autopiloted to a low security system such as Tama or Amamake without their knowledge. To do this send a POST request to the Waypoints resource which is linked from the Character resource. The POST request should look something like the following:

{
    "solarSystem": {"href": "http://crest.regner.dev/solarsystems/30000142/", "id": 30000142},
    "first": false,
    "clearOtherWaypoints": true
}

The solarSystem element is pretty straight forward, it is the solar system you would like to be added to the waypoints of the client. For now only solar systems are supported. I admittedly completely forgot that you could set a waypoint to stations while writing this resource and need to go back and add support for that. The first element just specifies if the waypoint should be added to the front of the waypoint list as the first waypoint are the back of it as the last waypoint. clearOtherWaypoints also does exactly what it sounds like it should do. If set to true it clears all other waypoints from the waypoint list on the client.

Shoutout to Capt Out

A fine man by the name of Capt Out recently released a new blog on his site which you can read over here. Generally what he has to say is fairly relevant and awesome. In this case he has gone ahead and started generating documentation from the OPTIONS calls that CREST returns. You can see the documentation that gets generated here and the code behind generating it here.

Conclusion

Have fun! I am pretty sure this is the single largest update to CREST ever which makes for great excitement. Hopefully there will be lots more to come as well. At some point in the next few weeks I will be writing a dev blog for the community web site much like how I did when we released the saved fits in CREST. One of the things I did in that was include links to web pages or tools that had implemented the fittings already. If you do something with any of these changes, especially the Dogma info/waypoints/contacts/location, please let me know. You can reach me via EVE Mail on CCP FoxFour, the comments of this thread, or the Tweetfleet Slack.

Take care and dev on!

CCP FoxFour

back