Skip to content

Commit

Permalink
Documentation update 4
Browse files Browse the repository at this point in the history
  • Loading branch information
SomeCrazyGuy committed Jun 12, 2024
1 parent 02baff3 commit 4c2f87f
Showing 1 changed file with 105 additions and 65 deletions.
170 changes: 105 additions & 65 deletions betterapi.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
#ifndef BETTERAPI_API_H
#define BETTERAPI_API_H

// Always use the latest betterapi.h file from github in your build if the BETTERAPI_VERSION
// number is compatible with the published version of betterconsole on nexusmods.
// sometimes small hacks or fixes are put here to fix issues in the published mod between releases.
// https://raw.githubusercontent.com/SomeCrazyGuy/Starfield-Console-Replacer/master/betterapi.h


// Version number for betterapi, when a new version of betterconsole changes the public API
// this number is incremented. Usually only when bigger feature changes are added.
// I will not break the API in a bugfix release of betterconsole and feature releases
// are not expected to happen more often than starfield updates.
// Usually porting to a new version of the api is as easy as dropping in the new betterapi.h
// into your build and fixing the compiler errors (if any).
#define BETTERAPI_VERSION 1


///////////////////////////////////////////////////////////////////////////////
// Gain BetterConsole features for your mod in 2 easy steps: //
///////////////////////////////////////////////////////////////////////////////

// Integrate betterconsole in your mod in 3 easy steps:
//
// Step 1) Include "betterapi.h" anywhere you want to use the api
//
//
Expand Down Expand Up @@ -49,99 +65,123 @@ static int OnBetterConsoleLoad(const struct better_api_t* BetterAPI) {
// Maybe save the betterapi pointer to a global variable use elsewhere
//API = BetterAPI;
// I find it convenient to even unwrap the internal api pointers and assign them to globals
// I often find it convenient to assign the api pointers to global variables
// UI = BetterAPI->SimpleDraw
return 0; // return 0 for success or any positive number to indicate a failure
}
*/
//
// Step 3) Enjoy! betterapi integration is a soft dependency so if a user doesn't have
// or want betterconsole installed, or betterconsole updates and your mod is no
// longer compatible then your mod just works the way it would without the
// betterconsole features and api. If your mod can function without betterconsole
// you dont need to do any additional work, the OnBetterConsoleLoad function
// just wont be called.
// Sit back and relax! The callbacks registered will be called automatically when
// necessary. For example, lets implement that MyDrawCallback function above and
// assume we also decided to set that UI global variable to the SimpleDraw api:
/*
static void MyDrawCallback(void*) {
static int counter = 0;
UI->Text("Hello World!");
if (UI->Button("Click Me!")) {
counter++;
}
char label[128];
snprintf(label, 128, "You Clicked the button %d times", counter);
UI->Text(label);
}
*/
// Betterapi integration is a soft dependency - if a user doesn't have
// or want betterconsole installed, or betterconsole updates and your mod is no
// longer compatible, then your mod just works the way it would without the
// betterconsole features and api. If your mod can function without betterconsole
// you dont need to do any additional work - the OnBetterConsoleLoad function
// just wont be called.
//
//
// Bonus Step: If you are writing an asi mod or trying to port a cheat engine table,
// you may want to Control+F for SFSE_MINIMAL. You can utilize the sfse
// minimal api to make your mod into a combo asi and sfse plugin without
// having to include any other headers or libraries not even any sfse code.
// I have written and included an example of how to use this near the
// bottom of the file.
// Bonus Step:
// If you are writing an asi mod or trying to port a cheat engine table,
// you may want to Control+F for SFSE_MINIMAL. You can utilize the sfse
// minimal api to make your mod into a combo asi and sfse plugin without
// having to include any other headers or libraries not even any sfse code.
// I have written and included an example of how to use this near the
// bottom of the file.
//
//
// You can always reach out to me if you have any questions or need help integrating betterapi
// I'm almost always available in the v2 discord or nexusmods.
//


// Betterconsole is written in C++ but the public API is plain C99
// and only includes headers that are from the C standard library
// (only for types and defines, no C library functions are called).
// This makes it easier to integrate betterconsole into any project
// because the whole API is one header file with no other dependencies.
// On a philisophical level, if you cannot describe an interface in C
// using only builtin types and defines, then the interface is not
// simple enough. Since almost every programming language has some type
// of C compatible foreign function interface, this allows you to write
// mods in almost any programming language albeit with some challenges.
// Betterconsole is written in C++ but the public API is plain C99 and only includes
// headers that are from the C standard library no C library functions are even
// called by betterapi. This makes it easier to integrate betterconsole into any
// project because the whole API is one header file with no other dependencies. On a
// philisophical level, if you cannot describe an interface in C then the interface
// is not simple enough. Since almost every programming language has some type of C
// compatible foreign function interface, this allows you to write mods in almost
// any programming language albeit with some challenges.
#include <stdint.h>
#include <stdbool.h>


// you might see the use of BETTERAPI_DEVELOPMENT_FEATURES in the code below.
// You might see the use of BETTERAPI_DEVELOPMENT_FEATURES in the code below.
// these are features that will be in the next version of betterconsole but
// not part of the current release on nexusmods.
//
// adding more functions to the end of the api structs does not break the api
// so development features will usually always be added to the end of the struct
// this allows the lastest betterapi header to be compatible with older versions
// of betterconsole.
//
// if you are developing a mod using the betterconsole api you MUST NOT define
// If you are developing a mod using the betterconsole api you MUST NOT define
// BETTERAPI_DEVELOPMENT_FEATURES, as the resulting plugin will not be compatible
// with the version of betterconsole that everyone is using.
#ifdef BETTERAPI_DEVELOPMENT_FEATURES
#pragma message ("BETTERAPI_DEVELOPMENT_FEATURES is defined, any plugin using the api will not be compatible the nexusmods release of betterconsole.")
#endif // BETTERAPI_DEVELOPMENT_FEATURES


// Version number for betterapi, when a new version of betterconsole
// changes the public API this number is incremented. Usually only when
// bigger feature changes are added - I will not break the API in a bugfix
// release of betterconsole and feature releases are not expected to happen
// more often than starfield updates. Usually porting to a new version
// of the api is as easy as dropping in the new betterapi.h into your build
// and fixing anything the compiler complains about (if anything).
//
// Recommendation: always use the latest betterapi.h file from github in your build
// as long as the BETTERAPI_VERSION is compatible with the published
// version of betterconsole on nexusmods - sometimes small hacks
// or fixes are put here to fix issues in the published mod
// between releases. Likewise, when the published version of
// betterconsole changes, you should update betterapi.h and
// recompile your mod to fix any issues that may arise.
#define BETTERAPI_VERSION 1


// Forward declaration of the main betterapi structure.
// you will receive this as the only argument in your BetterConsoleReceiver
// From how this has been used internally, you might find it convenient to
// store the fields of this structure to static global variables to avoid
// writing "betterapi->structure->function" all over the place.
struct better_api_t;

// A note about thread safety
// There is no thread safety all of the betterapi functions are operating within
// the game's idxgiswapchain::present function as the game is trying submit a
// frame to the gpu. Do not use any of these apis from a separate thread unless
// it is explicitly marked as safe to do so and please keep it quick - we don't
// want to slow down the game. I will add an api for a separate task thread to
// do sig scanning or other slow tasks in a future update.


// Note: this API is not thread safe,
// all of the below functions are operating within idxgiswapchain::present
// as the game is trying submit a frame to the gpu
// do not use any of these apis from a separate thread
// and please keep it quick, don't slow down the game
// I will add an api for a separate task thread to do sig scanning or other slow tasks
// A note about "userdata"
// Several of the APIs in BetterConsole take a "userdata" argument
// since we are exposing all these capabilities in plain C99 we
// need a way to express a generic type or piece of data that you
// want to work with. Often this will show up in the SimpleDraw functions.
// Lets look at an example of why and how you would do this...
//
// say you have an array of pointers to some struct:
// struct GameType {
// ...
// uint32_t formid;
// ...
// const char* name;
// ...
// } *data_array[100] = some_pointer;
//
// how would you make a selectable list of these in a gui that knows nothing
// about GameType? The answer is userdata and a callback!
//
// Create a to_string function for GameType:
//
// const char* gametype_to_string(const void* userdata, uint32_t index, char* out_tmp, uint32_t tmp_size) {
// const GameType** pGT = (const GameType**)userdata;
// const GameType* GT = pGT[index];
// snprintf(out_tmp, tmp_size, "FormID: %X, Name: %s", GT->formid, GT->name);
// return out_tmp;
// }
//
// Then make is a selectable list:
//
// static uint32_t selected_item = 0;
// bool was_clicked = SimpleDraw->SelectionList(&selected_item, (const void*)data_array, 100, gametype_to_string);
//
// now the user can scroll through and click on an entry in the list without
// the UI code ever needing to know what the heck a GameType is


// Opaque handle for the log buffer system
Expand Down

0 comments on commit 4c2f87f

Please sign in to comment.