Files
integration/luprex/cpp/core/enginewrapper.hpp

309 lines
12 KiB
C++
Raw Normal View History

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
2025-06-16 21:32:40 -04:00
#include <cstdint>
#include <cstddef>
2023-02-14 13:14:18 -05:00
#define DRV_MAX_CHAN 256
#define DRV_MAX_LISTEN_PORTS 256
#define DRV_ERRMSG_SIZE 8192
#define DRV_SHORTSTRING_SIZE 65536
enum class AccessKind {
2024-09-02 21:48:24 -04:00
INVALID,
INVOKE_LUA_CALL,
INVOKE_LUA_EXPR,
INVOKE_FLUSH_PRINTS,
INVOKE_TICK,
INVOKE_LUA_SOURCE,
PROBE_LUA_CALL,
CONNECT_TO_SERVER,
VALIDATE_LUA_EXPR,
CHANNEL_PRINTS,
SLASH_COMMAND,
2024-09-02 21:48:24 -04:00
};
2023-02-14 13:14:18 -05:00
class DrivenEngine;
class PlayLogfile;
class ReplayLogfile;
class World;
2023-02-14 13:14:18 -05:00
struct EngineWrapper {
char error[DRV_ERRMSG_SIZE];
char databuffer[DRV_SHORTSTRING_SIZE];
DrivenEngine *engine;
World *world;
2023-02-14 13:14:18 -05:00
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);
// 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 'have prints' flag. If true, then the engine
// wants the driver to use CHANNEL_PRINTS to obtain prints.
//
bool (*get_have_prints)(EngineWrapper *w);
2023-02-14 13:14:18 -05:00
// 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
// 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);
// 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.
//
// Returns a count and a pointer to an array of tangible IDs. The returned
// pointer is valid until the next call to get_tangibles_near.
//
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
// Get the animation queues for the specified tangibles.
2023-07-24 17:20:45 -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.
//
void (*get_animation_queues)(EngineWrapper *w, uint32_t count, const int64_t *ids, uint32_t *lengths, const char **strings);
2023-02-14 13:14:18 -05:00
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// MUTATORS USED ONLY IN PLAY MODE
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// 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
//
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-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.
//
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);
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
//
// 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.
//
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