2023-02-14 13:14:18 -05:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// enginewrapper.hpp
|
|
|
|
|
//
|
|
|
|
|
// This header file contains driver's interface to class DrivenEngine.
|
|
|
|
|
// This is meant to be used across a DLL boundary. Since the DLL may have
|
|
|
|
|
// been compiled by a different compiler than the driver, we use only simple
|
|
|
|
|
// POD types and we only use C calling conventions.
|
|
|
|
|
//
|
|
|
|
|
// When calling a wrapper function, you must always pass in the wrapper as
|
|
|
|
|
// the first parameter.
|
|
|
|
|
//
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
#ifndef ENGINEWRAPPER_H
|
|
|
|
|
#define ENGINEWRAPPER_H
|
|
|
|
|
|
|
|
|
|
#define DRV_MAX_CHAN 256
|
|
|
|
|
#define DRV_MAX_LISTEN_PORTS 256
|
|
|
|
|
#define DRV_ERRMSG_SIZE 8192
|
|
|
|
|
#define DRV_SHORTSTRING_SIZE 65536
|
|
|
|
|
|
2025-06-13 21:03:13 -04:00
|
|
|
enum class AccessKind {
|
2024-09-02 21:48:24 -04:00
|
|
|
INVALID,
|
2025-06-13 21:03:13 -04:00
|
|
|
INVOKE_LUA_CALL,
|
|
|
|
|
INVOKE_LUA_EXPR,
|
|
|
|
|
INVOKE_FLUSH_PRINTS,
|
|
|
|
|
INVOKE_TICK,
|
|
|
|
|
INVOKE_LUA_SOURCE,
|
|
|
|
|
PROBE_LUA_CALL,
|
2025-06-16 19:58:26 -04:00
|
|
|
CONNECT_TO_SERVER,
|
2024-09-02 21:48:24 -04:00
|
|
|
};
|
|
|
|
|
|
2023-02-14 13:14:18 -05:00
|
|
|
class DrivenEngine;
|
|
|
|
|
class PlayLogfile;
|
|
|
|
|
class ReplayLogfile;
|
|
|
|
|
|
|
|
|
|
struct EngineWrapper {
|
|
|
|
|
char error[DRV_ERRMSG_SIZE];
|
|
|
|
|
char databuffer[DRV_SHORTSTRING_SIZE];
|
|
|
|
|
DrivenEngine *engine;
|
|
|
|
|
PlayLogfile *wlog;
|
|
|
|
|
ReplayLogfile *rlog;
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// CONSTRUCTION
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Of course, there's no constructor, since this is a C struct.
|
|
|
|
|
// To initialize it, you use 'dlsym' or 'GetProcAddress' to get the
|
|
|
|
|
// address of the function 'init_engine_wrapper'. Then, you call
|
|
|
|
|
// the function init_engine_wrapper(&wrapper).
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// GETTERS
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Get a list of all the listening ports. The driver is expected
|
|
|
|
|
// to fetch this set shortly after the event_init callback is invoked.
|
|
|
|
|
//
|
|
|
|
|
void (*get_listen_ports)(EngineWrapper *w, uint32_t *nports, const uint32_t **ports);
|
|
|
|
|
|
|
|
|
|
// Get a list of all recently-opened channels that were created using
|
|
|
|
|
// new_outgoing_channel. The driver should initiate outgoing
|
|
|
|
|
// connections for these channels.
|
|
|
|
|
//
|
|
|
|
|
void (*get_new_outgoing)(EngineWrapper *w, uint32_t *nchanids, const uint32_t **chanids);
|
|
|
|
|
|
|
|
|
|
// Get a string_view of the target of a channel. A target is a string like
|
|
|
|
|
// "cert:whatever.com:80" or "nocert:whatever.com:80".
|
|
|
|
|
// The first word indicate whether or not a valid SSL certificate
|
|
|
|
|
// is required. The second word is the hostname. The third word is
|
|
|
|
|
// the port number. The char string returned here is valid until
|
|
|
|
|
// the channel is closed.
|
|
|
|
|
//
|
|
|
|
|
const char *(*get_target)(EngineWrapper *w, uint32_t chid);
|
|
|
|
|
|
|
|
|
|
// Return true if the user has released all references to this channel.
|
|
|
|
|
// In this case, the driver should initiate shutdown of the channel,
|
|
|
|
|
// and the driver should eventually call notify_close.
|
|
|
|
|
//
|
|
|
|
|
bool (*get_channel_released)(EngineWrapper *w, uint32_t chid);
|
|
|
|
|
|
|
|
|
|
// Get a pointer to the bytes in the outgoing buffer. The char pointer
|
|
|
|
|
// returned here is naturally only valid until the buffer is changed.
|
|
|
|
|
// This function is used for all channels, including sockets and stdio.
|
|
|
|
|
//
|
|
|
|
|
void (*get_outgoing)(EngineWrapper *w, uint32_t chid, uint32_t *len, const char **data);
|
|
|
|
|
|
|
|
|
|
// Return true if the outgoing buffer is empty.
|
|
|
|
|
//
|
|
|
|
|
bool (*get_outgoing_empty)(EngineWrapper *w, uint32_t chid);
|
|
|
|
|
|
2023-05-18 22:09:54 -04:00
|
|
|
// Get the console prompt.
|
|
|
|
|
//
|
|
|
|
|
void (*get_console_prompt)(EngineWrapper *w, uint32_t *len, const char **data);
|
|
|
|
|
|
2023-02-14 13:14:18 -05:00
|
|
|
// Get the clock.
|
|
|
|
|
//
|
|
|
|
|
// Get the current time. This is equal to the last value passed
|
|
|
|
|
// in by invoke_event_update.
|
|
|
|
|
//
|
|
|
|
|
double (*get_clock)(EngineWrapper *w);
|
|
|
|
|
|
|
|
|
|
// Check the 'rescan_lua_source' flag. If this flag is set, it means
|
|
|
|
|
// that the engine wants the driver to rescan the lua source code.
|
|
|
|
|
// When the driver sees this flag, it should rescan the source and call
|
2023-10-19 19:42:33 -04:00
|
|
|
// set_lua_source_pack.
|
2023-02-14 13:14:18 -05:00
|
|
|
//
|
|
|
|
|
bool (*get_rescan_lua_source)(EngineWrapper *w);
|
|
|
|
|
|
|
|
|
|
// If true, the engine is done. Stop the driver.
|
|
|
|
|
//
|
|
|
|
|
bool (*get_stop_driver)(EngineWrapper *w);
|
|
|
|
|
|
2023-07-24 17:19:25 -04:00
|
|
|
// Get the actor ID. May return zero if the server is down.
|
|
|
|
|
//
|
|
|
|
|
uint64_t (*get_actor_id)(EngineWrapper *w);
|
|
|
|
|
|
2023-07-24 17:20:45 -04:00
|
|
|
// Do a scan to find tangibles near the specified player.
|
2023-07-24 17:19:25 -04:00
|
|
|
//
|
2023-07-24 17:21:44 -04:00
|
|
|
// Returns a count and a pointer to an array of tangible IDs. The returned
|
2023-07-26 17:40:20 -04:00
|
|
|
// pointer is valid until the next call to get_tangibles_near.
|
2023-07-24 17:21:44 -04:00
|
|
|
//
|
2023-07-24 17:19:25 -04:00
|
|
|
void (*get_tangibles_near)(EngineWrapper *w, uint64_t tanid, double rx, double ry, double rz, uint32_t *count, int64_t **ids);
|
2023-07-24 17:20:45 -04:00
|
|
|
|
2023-07-26 17:40:20 -04:00
|
|
|
// Get the animation queues for the specified tangibles.
|
2023-07-24 17:20:45 -04:00
|
|
|
//
|
2023-08-16 13:45:12 -04:00
|
|
|
// You must supply an array of tangible IDs. For each tangible, returns the
|
|
|
|
|
// animation queue as a serialized string. The serialized format is
|
|
|
|
|
// documented in header file animqueue.hpp.
|
|
|
|
|
//
|
|
|
|
|
// You must also supply a buffer for the string lengths, and a buffer for
|
|
|
|
|
// the string pointers. Both buffers must have space for number of
|
|
|
|
|
// tangibles specified in the call.
|
|
|
|
|
//
|
|
|
|
|
// The returned character pointers remain valid until the next call to
|
|
|
|
|
// get_animation_queues.
|
2023-07-24 17:21:44 -04:00
|
|
|
//
|
2023-07-26 17:40:20 -04:00
|
|
|
void (*get_animation_queues)(EngineWrapper *w, uint32_t count, const int64_t *ids, uint32_t *lengths, const char **strings);
|
2023-07-24 17:19:25 -04:00
|
|
|
|
2023-02-14 13:14:18 -05:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// MUTATORS USED ONLY IN PLAY MODE
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2025-06-16 19:58:26 -04:00
|
|
|
// Create the driven engine. You must specify the type of engine you
|
|
|
|
|
// want (typically 'lpxserver' or 'lpxclient'), and a filename for the
|
|
|
|
|
// logfile.
|
2023-02-14 13:14:18 -05:00
|
|
|
//
|
2025-06-16 19:58:26 -04:00
|
|
|
void (*play_initialize)(EngineWrapper *w, const char *engtype, const char *logfn);
|
2023-02-14 13:14:18 -05:00
|
|
|
|
|
|
|
|
// Clear the list of recently-opened channels. You are meant to fetch
|
|
|
|
|
// new outgoing channels using get_new_outgoing, then you call
|
|
|
|
|
// clear_new_outgoing after you've opened those channels.
|
|
|
|
|
//
|
|
|
|
|
void (*play_clear_new_outgoing)(EngineWrapper *w);
|
|
|
|
|
|
|
|
|
|
// Notifies the channel that some bytes were transmitted. This causes those
|
|
|
|
|
// bytes to be removed from the outgoing buffer. This function is used for
|
|
|
|
|
// all channels, including sockets and stdio.
|
|
|
|
|
//
|
|
|
|
|
void (*play_sent_outgoing)(EngineWrapper *w, uint32_t chid, uint32_t nbytes);
|
|
|
|
|
|
|
|
|
|
// Notifies the channel that some bytes were received. This causes those
|
|
|
|
|
// bytes to be appended to the incoming buffer. This function is used for
|
|
|
|
|
// all channels, including sockets and stdio.
|
|
|
|
|
//
|
|
|
|
|
void (*play_recv_incoming)(EngineWrapper *w, uint32_t chid, uint32_t len, const char *data);
|
|
|
|
|
|
|
|
|
|
// Notify the channel that the connection was closed. This includes all
|
|
|
|
|
// sorts of closes, including friendly termination, all the way to network
|
|
|
|
|
// failure. Closing the channel doesn't delete it. The engine is
|
|
|
|
|
// responsible for noticing that the channel closed and the engine must
|
|
|
|
|
// delete it. Closing a channel prevents it from showing up in
|
|
|
|
|
// 'list_channels'.
|
|
|
|
|
//
|
|
|
|
|
void (*play_notify_close)(EngineWrapper *w, uint32_t chid, uint32_t len, const char *data);
|
|
|
|
|
|
|
|
|
|
// Notify the DrivenEngine that somebody connected to an incoming port.
|
|
|
|
|
// This will cause the DrivenEngine to allocate a new channel and put the
|
|
|
|
|
// new channel into the incoming channels queue. Returns the new channel
|
|
|
|
|
// ID. The new incoming channel appears in the 'list_channels' list,
|
|
|
|
|
// even before the engine pops the channel from the incoming channels queue.
|
|
|
|
|
//
|
|
|
|
|
uint32_t (*play_notify_accept)(EngineWrapper *w, uint32_t port);
|
|
|
|
|
|
|
|
|
|
// Invoke the update event.
|
|
|
|
|
//
|
|
|
|
|
// The clock value must absolutely be monotonically increasing,
|
|
|
|
|
// and it should roughly be equal to the number of seconds since
|
|
|
|
|
// the program started.
|
|
|
|
|
//
|
2024-09-03 21:56:53 -04:00
|
|
|
void (*play_update)(EngineWrapper *w, double clock);
|
2023-02-14 13:14:18 -05:00
|
|
|
|
2024-09-02 21:48:24 -04:00
|
|
|
// Send an invoke.
|
2024-08-28 22:02:25 -04:00
|
|
|
//
|
2024-08-29 17:45:05 -04:00
|
|
|
// This is the main pathway for blueprints, or the unreal C++ code,
|
2024-09-02 21:48:24 -04:00
|
|
|
// to change the state of the world.
|
2023-10-24 00:49:15 -04:00
|
|
|
//
|
2025-06-13 21:03:13 -04:00
|
|
|
void (*play_access)(EngineWrapper *w, AccessKind kind, int64_t place, uint32_t datapklen, const char *datapk, uint32_t *retpklen, const char **retpk);
|
2023-02-14 13:14:18 -05:00
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// MUTATORS USED ONLY IN REPLAY MODE
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
// Begin a replay.
|
|
|
|
|
//
|
|
|
|
|
// Opens the logfile and prepares to replay the log.
|
|
|
|
|
// If an error occurs, the error buffer contains a message,
|
|
|
|
|
// and the done flag is set to true.
|
|
|
|
|
//
|
|
|
|
|
void (*replay_initialize)(EngineWrapper *w, const char *logfn);
|
|
|
|
|
|
|
|
|
|
// Execute a single step from the replay log.
|
|
|
|
|
//
|
|
|
|
|
// Calling this when 'done' is true is a no-op.
|
|
|
|
|
//
|
|
|
|
|
void (*replay_step)(EngineWrapper *w);
|
|
|
|
|
|
2023-02-20 16:02:18 -05:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// CALLBACKS USED ONLY IN REPLAY MODE
|
|
|
|
|
//
|
|
|
|
|
// The driver can store function pointers here. If it does so, these
|
|
|
|
|
// functions will get called during replay_step operations.
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void (*replay_cb_sent_outgoing)(void *vp, int chid, int nbytes, const char *data);
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// VOID POINTER USED IN REPLAY CALLBACKS
|
|
|
|
|
//
|
|
|
|
|
// The driver can store a void pointer here. This void pointer will get passed
|
|
|
|
|
// to all the replay callbacks.
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
void *replay_cb_vp;
|
|
|
|
|
|
2023-02-14 13:14:18 -05:00
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//
|
|
|
|
|
// FUNCTIONS THAT CAN BE USED AT ANY TIME
|
|
|
|
|
//
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
2023-02-27 17:21:00 -05:00
|
|
|
// Hook dprintf
|
|
|
|
|
//
|
|
|
|
|
// The engine provides a function 'util::dprintf' to print debugging
|
|
|
|
|
// messages. It does not use stderr or std::cerr, because in windows, those
|
|
|
|
|
// go to the bit-bucket.
|
|
|
|
|
//
|
|
|
|
|
// This routine hooks dprintf to change where the output goes. Ideally,
|
|
|
|
|
// the intent is to send the output somewhere easily accessible, like the
|
|
|
|
|
// visual studio debug output log, or the unreal editor output log, or
|
|
|
|
|
// something like that. Or, better yet, to all those places at once.
|
|
|
|
|
//
|
|
|
|
|
// The hook function will get passed one line of output at a time. The line
|
|
|
|
|
// will only contain printable characters. The line will not contain a
|
|
|
|
|
// newline - the newline is implied.
|
|
|
|
|
//
|
2023-04-05 18:41:03 -04:00
|
|
|
void (*hook_dprint)(void (*func)(const char *oneline, size_t size));
|
2023-02-27 17:21:00 -05:00
|
|
|
|
2023-05-30 22:36:26 -04:00
|
|
|
// Release: delete the engine object and close log files.
|
2023-02-14 13:14:18 -05:00
|
|
|
//
|
|
|
|
|
// Note that the wrapper must have already been initialized using
|
|
|
|
|
// init_engine_wrapper. Otherwise, the 'release' function pointer would not
|
|
|
|
|
// be initialized. If writing a logfile, this stores a 'clean exit' marker
|
|
|
|
|
// in the logfile, indicating that the engine exited cleanly, as opposed to
|
|
|
|
|
// crashing.
|
|
|
|
|
//
|
|
|
|
|
// If the wrapper is already in its clear state, this is a no-op.
|
|
|
|
|
//
|
|
|
|
|
void (*release)(EngineWrapper *w);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
#endif // ENGINEWRAPPER_HPP
|