Jump to content

martyj

Members
  • Posts

    544
  • Joined

  • Last visited

Posts posted by martyj

  1. So I've wanted this feature in an engine for a really long time, it's just a very difficult task.

     

    It would be nice if Leadwerks could have the ability to modify the map then immediately play the game without having to run a separate application. If you could "pause" your game logic in editing mode, then resume to test out new features.

     

    I think the phrasing would be seamless integration.

     

    Lua code would be easy to reload into the engine, whereas with C++ you would have to use calls like dlopen http://man7.org/linux/man-pages/man3/dlopen.3.html to reload compiled binaries. This may be come easier with the C++ Action Class.

     

     

    I could modify my game to support this, but I would require the ability save a Map out. It would be nice to also toggle Leadwerks UI elements such as the Assets pane, or terrain editing.

     

     

    At least for me, it would save a ton of time to not have to reload the game to test a feature. I spend a lot of time in my loading screen.

    • Upvote 2
  2. Might be easier and more reliable to store them in a queue, then use an std::thread which checks the queue for events to be sent off. That way if the game crashes, (which in C++ land happens a lot), you can still have the data.

  3. Success!

     

    Did some digging around in my test code. Apparently sizeof(char*) doesn't return the size of the static array, but just the size of a charater. Thanks G++.

     

    http://martyj.net/curl.zip

     

    I can't find libcurl-dev on windows for the life of me, so I had to use Linux. As I am working off of a server, I don't have Leadwerks setup so I cannot implement it in your class.

     

    Sorry about the indentation as well. I was using nano to modify the files.

     

    But this should help hopefully.

    • Upvote 1
  4. For the life of me I cannot reproduce the hmac hash.

     

    Using the key from the python file and the JSON from my sample, I get the following:

     

    import hmac
    import hashlib
    key = "16813a12f718bc5c620f56944e1abc3ea13ccbac"
    data = "{\"platform\":\"Windows\", \"os_version\":\"10\", \"sdk_version\":\"api v2\"}";
    hash = hmac.new(key, data, digestmod=hashlib.sha256)
    hash.hexdigest()
    

     

    Produces the following HEX string a39a45d2ac53e7c4d9e3b978267a6442cad0c396a52500e6c3be9e5bb1e6edbb

     

    Using the library I posted earlier I get a completely different result.

     

    Using the following code which uses OpenSSL's version

    #include <string.h>
    #include <stdio.h>
    
    #include <openssl/hmac.h>
    #include <openssl/evp.h>
    
    void hmac(unsigned char* key, unsigned char* message, int keylen, int messagelen, unsigned char* out)
    {
     HMAC_CTX ctx;
     HMAC_CTX_init(&ctx);
     unsigned int len = 32;
     unsigned char* data[32];
     // Using sha1 hash engine here.
     // You may use other hash engines. e.g EVP_md5(), EVP_sha224, EVP_sha512, etc
     HMAC_Init_ex(&ctx, key, 20, EVP_sha256(), NULL);
     HMAC_Update(&ctx, message, messagelen);
     HMAC_Final(&ctx, out, &len);
     HMAC_CTX_cleanup(&ctx);
     memcpy(out, data, len);
     memset(out+len, 0, 32-len);
     for(int i = 0; i < len; i++)
     {
    		 printf("%02x", out[i]);
     }
     printf("\n");
    }
    
    int main(int argc, const char *const *argv)
    {
     unsigned char buff[32];
     const char* message = "{\"platform\":\"Windows\", \"os_version\":\"10\", \"sdk_version\":\"api v2\"}";
     const char* key = "16813a12f718bc5c620f56944e1abc3ea13ccbac";
     hmac((unsigned char*)key, (unsigned char*)message, sizeof(key), sizeof(message), buff);
    }
    

     

    I get the following printed.

    0000000000000000b076bf49007f0000d859c149007f00008707400000000000

     

    This sample code seems to work well. The problem is it is only windows.

     

    http://stackoverflow.com/questions/22147895/is-it-possible-to-do-a-hmac-with-wincrypt

    • Upvote 2
  5. I think their python example gives the best use case of how their auth works.

     

    http://restapidocs.gameanalytics.com/#python-example

     

    # sandbox game keys
    game_key = "5c6bcb5402204249437fb5a7a80a4959"
    secret_key = "16813a12f718bc5c620f56944e1abc3ea13ccbac"
    # sandbox API urls
    url_init = 'http://sandbox-api.gameanalytics.com/v2/' + game_key + '/init'
    init_payload = {
    'platform': platform,
    'os_version': os_version,
    'sdk_version': sdk_version
    }
    init_payload_json = json.dumps(init_payload)
    headers = {
    'Authorization': hmac_hash_with_secret(init_payload_json, secret_key),
    'Content-Type': 'application/json'
    }
    
    try:
    init_response = requests.post(url_init, data=init_payload_json, headers=headers)
    except:
    print "Init request failed!"
    sys.exit()
    
    

     

    Notice the line 'Authorization': hmac_hash_with_secret(event_list_json, secret_key),

     

    Makes use of this function

     

    def hmac_hash_with_secret(message, key):
       return base64.b64encode(hmac.new(key, message, digestmod=hashlib.sha256).digest())
    

     

    Create hmac hash based upon key and message.

     

    Base64 encode hmac hash.

  6. While you're in there adding http requests with libcurl, you should make them available for other C++ developers without using libcurl :P.

     

    It would be nice to do a request to a URL with a map as GET or POST params.

  7. Two Questions

     

    1. Are you using the sandbox API keys for the sandbox API?

     

    2. Are you creating the Authorization header correctly? From what I can tell, it's a hmac hash of your POST data using your secret key, then base64 encoding it

     

    I looked into CURL a little bit further. Here is my text example thanks to libcurl's example.

     

    /***************************************************************************
    *				 _  _ ____ _
    * Project		   ___| | | | _ \| |
    *			   / __| | | | |_) | |
    *			  | (__| |_| | _ <| |___
    *			   \___|\___/|_| \_\_____|
    *
    * Copyright (C) 1998 - 2015, Daniel Stenberg, <daniel@haxx.se>, et al.
    *
    * This software is licensed as described in the file COPYING, which
    * you should have received as part of this distribution. The terms
    * are also available at https://curl.haxx.se/docs/copyright.html.
    *
    * You may opt to use, copy, modify, merge, publish, distribute and/or sell
    * copies of the Software, and permit persons to whom the Software is
    * furnished to do so, under the terms of the COPYING file.
    *
    * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
    * KIND, either express or implied.
    *
    ***************************************************************************/
    /* <DESC>
    * simple HTTP POST using the easy interface
    * </DESC>
    */
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <curl/curl.h>
    
    struct MemoryStruct {
    char *memory;
    size_t size;
    };
    static size_t
    WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
    {
    size_t realsize = size * nmemb;
    struct MemoryStruct *mem = (struct MemoryStruct *)userp;
    mem->memory = realloc(mem->memory, mem->size + realsize + 1);
    if(mem->memory == NULL)
    {
     /* out of memory! */
     printf("not enough memory (realloc returned NULL)\n");
     return 0;
    }
    memcpy(&(mem->memory[mem->size]), contents, realsize);
    mem->size += realsize;
    mem->memory[mem->size] = 0;
    return realsize;
    }
    
    int main(void)
    {
    CURL *curl;
    CURLcode res;
    struct MemoryStruct chunk;
    chunk.memory = malloc(1);
    chunk.size = 0;
    char* postData = "{\"platform\":\"Windows\", \"os_version\":\"10\", \"sdk_version\":\"api v2\"}";
    /* In windows, this will init the winsock stuff */
    curl_global_init(CURL_GLOBAL_ALL);
    /* get a curl handle */
    curl = curl_easy_init();
    if(curl)
    {
     struct curl_slist *headers=NULL;
     headers = curl_slist_append(headers, "Content-Type: text/xml");
     headers = curl_slist_append(headers, "Authorization: <token_from_hmac_sha256_hash_with_secret>");
     curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
     /* First set the URL that is about to receive our POST. This URL can
       just as well be a https:// URL if that is what should receive the
       data. */
     curl_easy_setopt(curl, CURLOPT_URL, "http://api.gameanalytics.com/v2/<game_key_here>/init");
     /* Now specify the POST data */
     curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postData);
     curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (long)strlen(postData));
     /* Perform the request, res will get the return code */
     res = curl_easy_perform(curl);
    
     /* Check for errors */
     if(res != CURLE_OK)
     {
      fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
     }
     else
     {
      printf("%s\n",chunk.memory);
     }
    
     /* always cleanup */
     curl_easy_cleanup(curl);
    }
    curl_global_cleanup();
    return 0;
    }
    

     

    To generate an Hmac hash I'd check out this code: https://github.com/unixpickle/LibOrange/blob/master/LibOrange/hmac-sha256.c

     

    Then all you have to do is to base64 encode that for your Authorization token.

    • Upvote 1
  8. What you're setting the body to isn't valid json.

     

    What I would do is see if you can use CURLOPT_POSTFIELDS and pass it like this:

     

    curl.setOptString(CURLOPT_CURLOPT_POSTFIELDS, "platform=Windows&os_version=10&sdk_version=rest api v2");

     

    What library of CURL are you using? I can try to get a quick example tomorrow morning of each of the different requests.

  9. So it looks like you have to init the API first.

     

    POST /v2/<game_key>/init

     

    Your body data needs the following fields: platform, os_version, sdk_version

     

    The Docs ask for JSON to be submitted, but I'd imagine URLEncoding should work.

     

    Once you do that, you should be able to create different events here:

     

    POST /v2/<game_key>/events

     

    Depending on the category in your data, your fields change.

     

    For example, a Category of business appears to support the following fields:

     

    category, event_id, amount, currency, transaction_num, cart_type, receipt_info

     

    A Category even of type Resource requires the following fields:

    category, event_id, amount.

  10. I see.

     

    Does having an update hook effect performance much? I have an object that I add an update hook on when it gets interacted with, then I hide the object.

     

    After x number of seconds, I show the object, and would like to remove the hook as it's no longer needed to check to see if it should show.

     

    What would be the best way to do this?

  11. In the non-beta branch.

     

    When removing a hook on an entity in the Hook's callback, an access violation occurs.

     

    When removing a hook on an entity NOT in the hook, everything works as expected.

     

    Code:

     

    void tempHook(Entity* entity)
    {
    if (Window::GetCurrent()->KeyHit(Key::J))
    {
     entity->RemoveHook(Entity::UpdateWorldHook, tempHook);
    }
    }
    
    bool App::Start()
    {
    temp = Model::Box(3, 3, 3);
    temp->AddHook(Entity::UpdateWorldHook, tempHook);
    return true;
    }
    

×
×
  • Create New...