summaryrefslogtreecommitdiffhomepage
path: root/src/engineapi.c
blob: 5a78a92d0a241f969025f15aaf4116c4c56c452d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * Copyright © 2024 Michael Smith <mikesmiffy128@gmail.com>
 * Copyright © 2023 Willian Henrique <wsimanbrazil@yahoo.com.br>
 *
 * Permission to use, copy, modify, and/or distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 *
 * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 */

#include <stdlib.h> // used in generated code
#include <string.h> // "

#include "con_.h"
#include "engineapi.h"
#include "gamedata.h"
#include "gameinfo.h"
#include "gametype.h"
#include "intdefs.h"
#include "langext.h"
#include "mem.h" // "
#include "os.h"
#include "vcall.h"
#include "x86.h"

u64 _gametype_tag = 0; // declared in gametype.h but seems sensible enough here

ifacefactory factory_client = 0, factory_server = 0, factory_engine = 0,
		factory_inputsystem = 0;

struct VEngineClient *engclient;
struct VEngineServer *engserver;

void *srvdll;

DECL_VFUNC(void *, GetGlobalVars, 1) // seems to be very stable, thank goodness
void *globalvars;

void *inputsystem, *vgui;
struct CServerPlugin *pluginhandler;

DECL_VFUNC_DYN(void *, GetAllServerClasses)

#include <entpropsinit.gen.h> // generated by build/mkentprops.c

bool engineapi_init(int pluginver) {
	if_cold (!con_detect(pluginver)) return false;
	pluginhandler = factory_engine("ISERVERPLUGINHELPERS001", 0);

	if (engclient = factory_engine("VEngineClient015", 0)) {
		_gametype_tag |= _gametype_tag_Client015;
	}
	else if (engclient = factory_engine("VEngineClient014", 0)) {
		_gametype_tag |= _gametype_tag_Client014;
	}
	else if (engclient = factory_engine("VEngineClient013", 0)) {
		_gametype_tag |= _gametype_tag_Client013;
	}
	else if (engclient = factory_engine("VEngineClient012", 0)) {
		_gametype_tag |= _gametype_tag_Client012;
	}

	if (engserver = factory_engine("VEngineServer021", 0)) {
		_gametype_tag |= _gametype_tag_Server021;
	}
	else if (engserver = factory_engine("VEngineServer022", 0)) {
		//_gametype_tag |= _gametype_tag_Server022; // not needed yet
	}
	// else if (engserver = others as needed...) {
	// }

	void *pim = factory_server("PlayerInfoManager002", 0);
	if (pim) globalvars = GetGlobalVars(pim);

	vgui = factory_engine("VEngineVGui001", 0);

	// TODO(compat): add this back when there's gamedata for 009 (no point atm)
	/*if (srvdll = factory_server("ServerGameDLL009", 0)) {
		_gametype_tag |= _gametype_tag_SrvDLL009;
	}*/
	if (srvdll = factory_server("ServerGameDLL005", 0)) {
		_gametype_tag |= _gametype_tag_SrvDLL005;
	}

	// detect p1 for the benefit of specific features
	if (!GAMETYPE_MATCHES(Portal2)) {
		if (con_findcmd("upgrade_portalgun")) {
			_gametype_tag |= _gametype_tag_Portal1;
			if (!con_findvar("tf_escort_score_rate")) {
				_gametype_tag |= _gametype_tag_Portal1_3420;
			}
		}
		else if (con_findcmd("phys_swap")) {
			_gametype_tag |= _gametype_tag_HL2series;
		}
	}

	if (GAMETYPE_MATCHES(L4D2)) {
		if (con_findvar("sv_zombie_touch_trigger_delay")) {
			_gametype_tag |= _gametype_tag_L4D2_2147plus;
		}
		if (con_findvar("director_cs_weapon_spawn_chance")) {
			_gametype_tag |= _gametype_tag_TheLastStand;
		}
	}

	gamedata_init();
	con_init();
	if_cold (!gameinfo_init()) { con_disconnect(); return false; }
	return true;
}

void engineapi_lateinit(void) {
	// from AM L4D2 SDK headers:
	// > SENDPROP_VECTORELEM makes [the offset] negative to start with so we
	// > can detect that and set the SPROP_IS_VECTOR_ELEM flag.
	// by doing this at the deferred stage, we avoid having to abs() everything
	if (srvdll && has_vtidx_GetAllServerClasses && has_sz_SendProp &&
			has_off_SP_varname && has_off_SP_type && has_off_SP_offset &&
			has_DPT_DataTable) {
		initentprops(GetAllServerClasses(srvdll));
	}
}

// vi: sw=4 ts=4 noet tw=80 cc=80