<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LimeTech</title>
	<atom:link href="http://limetech.org/feed/" rel="self" type="application/rss+xml" />
	<link>http://limetech.org</link>
	<description>Better Code For Everyone</description>
	<lastBuildDate>Wed, 24 Oct 2012 13:59:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
		<title>Free2BeKicked &#8211; The Complete Interview</title>
		<link>http://limetech.org/blog/edrama/free2bekicked-the-complete-interview/</link>
		<comments>http://limetech.org/blog/edrama/free2bekicked-the-complete-interview/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 21:09:19 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[E-Drama]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=408</guid>
		<description><![CDATA[UPDATE: This post is still much in need of an introduction and some background regarding the event, for now though, I&#8217;m allocating time elsewhere &#8211; post in the comments below if you&#8217;d like to see this added to.]]></description>
				<content:encoded><![CDATA[<p><strong>UPDATE</strong>: This post is still much in need of an introduction and some background regarding the event, for now though, I&#8217;m allocating time elsewhere &#8211; post in the comments below if you&#8217;d like to see this added to.</p>
<div class='et-box et-shadow'>
					<div class='et-box-content'><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>Patrick Klepek</strong></td>
<td align="right"><strong>Wed, Jun 29, 2011 at 7:42 PM</strong></td>
</tr>
<tr>
<td colspan="2">
<div>To: Asher Baker</div>
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%" border="0" cellspacing="0" cellpadding="12">
<tbody>
<tr>
<td>Hey man,</p>
<p>I&#8217;m the news editor over at Giant Bomb.</p>
<p>Someone linked me towards your anti-F2P mod for TF2 and I was hoping to send you a few questions about it and your reasons for releasing it, if you don&#8217;t mind. Are you up for it?</p>
<p>Thanks,<br/>
Patrick Klepek<br/>
News Editor, Giant Bomb</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table></div></div>
<div class='et-box et-shadow'>
					<div class='et-box-content'><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>Asher Baker</strong></td>
<td align="right"><strong>Wed, Jun 29, 2011 at 10:02 PM</strong></td>
</tr>
<tr>
<td colspan="2">
<div>To: Patrick Klepek</div>
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%" border="0" cellspacing="0" cellpadding="12">
<tbody>
<tr>
<td>Hey Patrick,</p>
<p>Yeah, sure. Fire some questions my way and I&#8217;ll get back to you with
the answers as soon as possible.
Just keep in mind that it was made because there was demand for it
rather than because I have a personal vendetta against F2P users,
which a large amount of people seem to be trying to imply.</p>
<p>Regards,<br/>
Asher.</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table></div></div>
<div class='et-box et-shadow'>
					<div class='et-box-content'><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>Patrick Klepek</strong></td>
<td align="right"><strong>Wed, Jun 29, 2011 at 10:26 PM</strong></td>
</tr>
<tr>
<td colspan="2">
<div>To: Asher Baker</div>
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%" border="0" cellspacing="0" cellpadding="12">
<tbody>
<tr>
<td>Hey Asher,</p>
<p>That&#8217;s precisely why I wanted to talk to you, since the knee-jerk reaction is that someone who makes a mod like that is someone who&#8217;s having a knee-jerk reaction to this change in the community.</p>
<p>So walk me through it&#8230;how did you decide to make this mod? How difficult was it to make?</p>
<p>Has the response from the community been what you expected?</p>
<p>If you don&#8217;t have a &#8220;vendetta&#8221; against F2P users, how do you feel about them?</p>
<p>Do you expect Valve to disable your plugin? Have you heard any response from them?</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table></div></div>
<div class='et-box et-shadow'>
					<div class='et-box-content'><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>Asher Baker</strong></td>
<td align="right"><strong>Thu, Jun 30, 2011 at 1:10 AM</strong></td>
</tr>
<tr>
<td colspan="2">
<div>To: Patrick Klepek</div>
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%" border="0" cellspacing="0" cellpadding="12">
<tbody>
<tr>
<td>Hey Patrick,</p>
<p>Firstly, let me apologise for length. I promise it&#8217;s a good read, even if it does get a bit technical in places.</p>
<p>Well, there is quite a bit of background related to why it was made, so let me start with a conversation I had on IRC with the owner of <a href="http://www.alliedmods.net/" target="_blank">AlliedModders</a> after the first day or so:</p>
<blockquote><p style="font-family: 'courier new', monospace;">&lt;dvander&gt; personally i put it in the same category as banning high ping people which i hate</p>
<p style="font-family: 'courier new', monospace;">&lt;dvander&gt; but valve has created a problem</p>
<p style="font-family: 'courier new', monospace;">&lt;dvander&gt; a community needs a barrier to entry and it needs a way to heal itself if there is a misbehaving member</p>
<p style="font-family: 'courier new', monospace;">&lt;dvander&gt; if there is no barrier to entry &#8211; and no recourse against those people &#8211; it could be bad</p>
<p style="font-family: 'courier new', monospace;">&lt;dvander&gt; but its too early to tell</p>
<p style="font-family: 'courier new', monospace;">&lt;asherkin&gt; there are also a large number of tf2 servers aimed specifically at trading, the non-premium players can&#8217;t start trades and therefore just end up in these servers taking up a slot and begging for items</p>
<p style="font-family: 'courier new', monospace;">&lt;asherkin&gt; (it&#8217;s a trade server owner that originally asked me for the plugin)</p>
<p style="font-family: 'courier new', monospace;">&lt;asherkin&gt; and yeah, I also dislike high ping kickers, that silly cross-game vac ban detector, and even this one</p>
<p style="font-family: 'courier new', monospace;">&lt;asherkin&gt; but I figured it was better to do it myself properly before someone released something that did something silly like parse their backpack page to see how many slots they had etc.</p>
</blockquote>
<p>So yeah, basically it just boils down to there being a demand for it, yet there being very few developers who had the necessary background knowledge to do it without &#8220;hacks&#8221;. I was in a unique position due to my work on <a href="https://bitbucket.org/VoiDeD/open-steamworks" target="_blank">Open Steamworks</a> (I&#8217;m afraid our regular web site with a description of the  is offline due to a series of attacks and threats against anyone that hosts it, so I&#8217;ll give you the short version: It&#8217;s a series of scrounged, leaked and reverse engineered headers that allow the usage of the client-side portions of Valve&#8217;s <a href="http://steampowered.com/steamworks/" target="_blank">Steamworks</a> API), using OSW I created a <a href="http://www.sourcemod.net/" target="_blank">SourceMod</a> (a popular and well-known server administration and plugin system for the Source engine) Extension called <a href="http://forums.alliedmods.net/showthread.php?t=129763" target="_blank">SteamTools</a> to expose all the game server functionality to other plugins, this has allowed some amazing things to be written, including: a plugin to <a href="http://forums.alliedmods.net/showthread.php?p=1352434" target="_blank">manage server administrators using Steam Community Groups</a>, a <a href="http://forums.alliedmods.net/showthread.php?p=1301757" target="_blank">patch for the server rules listing bug in the Linux version of SrcDS</a>, a plugin to <a href="http://forums.alliedmods.net/showthread.php?t=132853" target="_blank">allow VAC-banned people into a Secure server</a> (arguably the most controversial plugin in my portfolio, but hardly as well-known as Free2BeKicked, also now <a href="http://forums.alliedmods.net/showpost.php?p=1496575&amp;postcount=72" target="_blank">includes some fixes for more bugs</a> Valve introduced in the engine), and of course <a href="https://forums.alliedmods.net/showthread.php?t=160049" target="_blank">Free2BeKicked</a>.</p>
<p>As for the demands aspect, a few days before the Free2Play announcement was made, Valve made some changed to the CDR (Content Description Record, simply a large database detailing all the content on Steam that is distributed to all the clients) that were noticed by another Open Steamworks developer that strongly hinted that TF2 would soon by F2P. After discovering this I was talking with a good friend of mine who runs the <a href="http://www.xomby.org/" target="_blank">Xomby.org</a> gaming community (which at the time ran a single TF2 trading server) and he asked me if I could look into a way to detect F2P players. When Free2Play was publicly announced and it was made known that they would be unable to trade he of course asked me again to make a plugin to outright prevent them from joining the server, this coupled with a thread made to request it on AlliedModders and some other requests directly to me on IRC persuaded me to create and release the plugin.</p>
<p>Regarding the difficulty of creating it, it&#8217;s quite hard to put a fixed value on it. I had already done a large amount of work required in SteamTools, and of course more was put into OSW by the Open Steamworks team (3 other people and I). I&#8217;ll try and go into a bit more detail (and also cover your later question about Valve) by explaining the technical details of how it works: When the game client wants to connect to a game server, it requests an authentication ticket from Steam and sends it to the server which then passes it onto the Steam backend in order to verify it and the client (check it&#8217;s from a valid account, the account owns the game, the client is already playing in another server, the client isn&#8217;t VAC-banned, etc.). SteamTools hooks into the server and &#8220;listens in&#8221; on the server&#8217;s request to Steam and does it&#8217;s own parsing of the auth ticket, this ticket contains (amongst other information) the subscription(s) the game was bought in (simply the &#8220;pack&#8221;, for example TF2, TF2 + GMod, Valve Complete Pack, etc.) and the DLC associated with the game. With this and some information about how Steam functions, it became easy to identify Free2Player players: They own TF2 in subscription 0 and no others (0 = Steam = owned by everyone) and they don&#8217;t have DLC 459 (&#8220;Team Fortress 2 - Premium DLC&#8221;). While Valve can implement the latter using other methods available to them (and would have the side-effect of needing other methods to detect F2P players who later upgraded to premium), stopping the subscription check would require rewriting whole the entire Steam game authentication system functions (please don&#8217;t take this as &#8220;taunting&#8221; Valve, it&#8217;s just an observation as to how the system operates). So while Valve may wish to prevent the plugin from operating, it would only end up with a large amount of work and worse methods being used to the same effect. As long as there is demand a version of the plugin will exist, although probably not written by myself.</p>
<p>Finally, yes, I anticipated a negative response from the general player base and a positive response from the server operators. I hadn&#8217;t anticipated it to be this strong either way, even including receiving death threats (but who doesn&#8217;t expect that online these days). In the end my loyalty is to the server operators and other developers trying to fight with the Source engine, so I&#8217;m glad of the outcome there. I don&#8217;t really have a personal opinion about TF2 going free to play, it&#8217;s brought in lots of new players, but I&#8217;m not sure it&#8217;s worth the long-term cost. I think that once the droves of inexperienced players dies down, we&#8217;re going to be left with a (slow) steady stream of new players (good), but primarily just cheaters and people evading server bans. I suppose you could say my plugin was ahead of it&#8217;s time. I did propose a possible solution to the latter on the Steam Powered User Forums, so I&#8217;ll just include that here:</p>
<blockquote><p>I think the best way would be a hardware identifier exposed as part of the authentication ticket (covering the whole system, so that changing an individual component does change the ID, but this is still &#8220;stronger&#8221; than going after individual IDs). This would mean that and individual server could ban that computer, lasting only on that server. This would be saner than IP bans (the only solution to multiple accounts other than my plugin) as it wouldn&#8217;t affect multiple people as in the case of a dynamic IP, but it would also be harder to change for that individual hacker.</p>
<p>Hardware bans work fine on a per-server case like this, they just fall apart when used by an invasive global system like VAC, because they are inherently &#8220;unfair&#8221; since someone who just &#8220;tried&#8221; a cheat (or someone used their computer) could get that computer permanently banned. Previously, this did work fine with SteamIDs because the limitation was to get a new Steam account. Since, with my idea, if it&#8217;s just a per-server ban you can join another server, where if a user continued to cheat they would just get banned again or if they didn&#8217;t they wouldn&#8217;t have any issue.</p></blockquote>
<p>Hope that answers all your questions and gives you plenty of content, just let me know if you have anything else you wish to ask.</p>
<p>Regards,<br/>
Asher.</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table></div></div>
<div class='et-box et-shadow'>
					<div class='et-box-content'><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>Patrick Klepek</strong></td>
<td align="right"><strong>Thu, Jun 30, 2011 at 11:22 PM</strong></td>
</tr>
<tr>
<td colspan="2">
<div>To: Asher Baker</div>
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%" border="0" cellspacing="0" cellpadding="12">
<tbody>
<tr>
<td>Hey Asher,</p>
<p>Thanks for getting back to me so quickly, and for going so in-depth technically, even if much of it goes over my head. <img src='http://limetech.org/wp-content/plugins/tango-smileys-extended/tango/smile.png' alt='Smile' title='Smile' class='tse-smiley' height='16' width='16' /></p>
<p>Let me see if I&#8217;m getting this straight. Basically, you&#8217;ve created a sever filter for free-to-play users without doing anything crazy&#8211;you&#8217;re working within the tools that Valve&#8217;s okay with? If they were to squash your plugin, it would only lead to people going to more extreme measures for the same aim?</p>
<p>A couple of follow-ups&#8230;</p>
<p>What does this mean? &#8220;like parse their backpack page to see how many slots they had etc.&#8221; Basically, you guys decided to make this plugin in the cleanest way possible, so that someone wouldn&#8217;t create something more sadistic?</p>
<p>How popular has the plugin been so far?</p>
</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table></div></div>
<div class='et-box et-shadow'>
					<div class='et-box-content'><table width="100%" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td><strong>Asher Baker</strong></td>
<td align="right"><strong>Fri, Jul 1, 2011 at 3:38 AM</strong></td>
</tr>
<tr>
<td colspan="2">
<div>To: Patrick Klepek</div>
</td>
</tr>
<tr>
<td colspan="2">
<table width="100%" border="0" cellspacing="0" cellpadding="12">
<tbody>
<tr>
<td>Hey Patrick,</p>
<p>No problem. Sorry about the technical stuff, needed to write a post up for my personal site as well, so figured I&#8217;d kill two birds with one stone <img src='http://limetech.org/wp-content/plugins/tango-smileys-extended/tango/razz.png' alt='Razz' title='Razz' class='tse-smiley' height='16' width='16' />.</p>
<p>I would doubt Valve are okay with the method. While it uses data that is sent to the server as part of the authentication process, it&#8217;s packed into a proprietary structure (which was reverse-engineered) and not actually exposed by any official API, it&#8217;s only meant to be passed through the server for processing on the Steam backend, the game server isn&#8217;t meant to look at the data inside.</p>
<p>Well, F2P players only get 50 slots in their TF2 backpack, Valve expose this slot count via their web API. However, accessing this would require making a costly request to the Steam Community website (which is often very slow), parsing the large amount of data returned to look for the number, and then kicking based on the number of available slots, which of course could change at any time (not that that would be much different from how making plugins for the Source engine normally is <img src='http://limetech.org/wp-content/plugins/tango-smileys-extended/tango/razz.png' alt='Razz' title='Razz' class='tse-smiley' height='16' width='16' />). My method uses data that is already sent to the server, and therefore requires no calls to outside data sources, making it a lot more efficient.</p>
<p>Well it&#8217;s certainly seen a lot of publicity, but getting an accurate number of server&#8217;s running it is almost impossible due to a bug I mentioned in my previous email. There are at least <a href="http://www.sourcemod.net/stats.php?mod_id=0&amp;addon_id=1577" target="_blank">17</a> server&#8217;s running my plugin, but since rules querying is broken on Linux (and the majority of TF2 server&#8217;s seem to be hosted on Linux machines), this number could be significantly higher. There have also been about 7 plugins based on mine posted on AlliedModders by various authors, that each performs a different action upon F2P players. As for the actual players, the author of the <a href="http://forums.steampowered.com/forums/showthread.php?t=1947269" target="_blank">main thread</a> covering the plugin on SPUF gained over 250 reputation points because of his post.</p>
<p>Regards,<br/>
Asher.</td>
</tr>
</tbody>
</table>
</td>
</tr>
</tbody>
</table></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/blog/edrama/free2bekicked-the-complete-interview/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Steam and CD Keys</title>
		<link>http://limetech.org/blog/programming/steam-and-cd-keys/</link>
		<comments>http://limetech.org/blog/programming/steam-and-cd-keys/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 13:37:52 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=368</guid>
		<description><![CDATA[]]></description>
				<content:encoded><![CDATA[<pre class="brush: cpp; title: ; notranslate">
int main(int argc, char* argv[])
{
	CSteamAPILoader loader;
	CreateInterfaceFn steamclientFn = loader.Load();
	IClientEngine *clientEngine = (IClientEngine *)steamclientFn(CLIENTENGINE_INTERFACE_VERSION, NULL);

	HSteamPipe pipe = clientEngine-&gt;CreateSteamPipe();
	HSteamUser user = clientEngine-&gt;ConnectToGlobalUser(pipe);

	IClientBilling *clientBilling = clientEngine-&gt;GetIClientBilling(user, pipe, CLIENTBILLING_INTERFACE_VERSION);
	IClientUser *clientUser = clientEngine-&gt;GetIClientUser(user, pipe, CLIENTUSER_INTERFACE_VERSION);
	IClientApps *clientApps = clientEngine-&gt;GetIClientApps(user, pipe, CLIENTAPPS_INTERFACE_VERSION);

	uint32 numLicenses = clientBilling-&gt;GetNumLicenses();
	for (uint32 licenseID = 0; licenseID &lt; numLicenses; licenseID++)
	{
		PackageId_t packageID = clientBilling-&gt;GetLicensePackageID(licenseID);

		if (packageID == 0)
			continue;

		uint32 numApps;
		clientBilling-&gt;GetPackageInfo(packageID, &amp;numApps, NULL, NULL, NULL, NULL, NULL, NULL, NULL);

		AppId_t *apps = new AppId_t[numApps];
		clientBilling-&gt;GetAppsInPackage(packageID, apps, numApps, true);

		for (AppId_t appIndex = 0; appIndex &lt; numApps; appIndex++)
		{
			AppId_t appID = apps[appIndex];

			bool hasCDKey = clientUser-&gt;HasLegacyCDKey(appID);
			if (!hasCDKey)
			{
				clientUser-&gt;RequestLegacyCDKey(appID);

				while (true)
				{
					CallbackMsg_t callback;
					if (!Steam_BGetCallback(pipe, &amp;callback))
						continue;

					if (callback.m_iCallback != LegacyCDKeyRegistered_t::k_iCallback)
					{
						Steam_FreeLastCallback(pipe);
						continue;
					}

					LegacyCDKeyRegistered_t *data = (LegacyCDKeyRegistered_t *)callback.m_pubParam;

					if (data-&gt;m_eResult != k_EResultOK)
					{
						Steam_FreeLastCallback(pipe);
						break;
					}

					char name[512];
					clientApps-&gt;GetAppData(appID, &quot;name&quot;, name, 512);

					cout &lt;&lt; name &lt;&lt; &quot; (&quot; &lt;&lt; appID &lt;&lt; &quot;)&quot; &lt;&lt; &quot; = &quot; &lt;&lt;  data-&gt;m_rgchCDKey &lt;&lt; endl;
				
					Steam_FreeLastCallback(pipe);
					break;
				}

				continue;
			}

			char CDKey[64];
			clientUser-&gt;GetLegacyCDKey(appID, CDKey, 64);

			char name[512];
			clientApps-&gt;GetAppData(appID, &quot;name&quot;, name, 512);

			cout &lt;&lt; name &lt;&lt; &quot; (&quot; &lt;&lt; appID &lt;&lt; &quot;)&quot; &lt;&lt; &quot; = &quot; &lt;&lt;  CDKey &lt;&lt; endl;
		}

		delete apps;
	}

	clientEngine-&gt;ReleaseUser(pipe, user);
	clientEngine-&gt;BReleaseSteamPipe(pipe);

	cout &lt;&lt; &quot;Press any key to continue . . . &quot; &lt;&lt; endl;
	while (!_kbhit()) {}
	return 0;
}
</pre>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/blog/programming/steam-and-cd-keys/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Interfaces and Listeners in C++</title>
		<link>http://limetech.org/blog/programming/interfaces-and-listeners/</link>
		<comments>http://limetech.org/blog/programming/interfaces-and-listeners/#comments</comments>
		<pubDate>Tue, 05 Apr 2011 11:53:59 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=277</guid>
		<description><![CDATA[So, time for my first ever tutorial/guide/whatever, let me know in the comments what you think and/or if you have any suggestions for future posts. Now, on with the main event. When I started writing VoiceHook I realised that I needed a way to keep the &#8216;core&#8217; (provider) closed-source, while allowing Metamod:Source plugins and SourceMod [...]]]></description>
				<content:encoded><![CDATA[<p>So, time for my first ever tutorial/guide/whatever, let me know in the comments what you think and/or if you have any suggestions for future posts. Now, on with the main event.</p>
<p>When I started writing <a title="VoiceHook" href="http://limetech.org/projects/sourcemm-plugins/voicehook/">VoiceHook</a> I realised that I needed a way to keep the &#8216;core&#8217; (provider) closed-source, while allowing Metamod:Source plugins and SourceMod extensions (consumer) to interface with it.</p>
<p>Now, I already had an idea how to implement the consumer → provider portion of it (interface) thanks to Voogru&#8217;s work on Attachables, but the provider → consumer part was still a mystery. Here I turned to the SourceMod core and it&#8217;s PlayerHelpers interface, this gave me an idea where to start and I managed to complete it.</p>
<p>So here is how you implement an interface in a Metamod:Source plugin (in this case, the sample one):</p>
<p>First things first, let&#8217;s define a simple interface:</p>
<pre class="brush: cpp; title: ; notranslate">
class IMyInterface
{
public:
	virtual int AddFive(int input) = 0;
}

#define MY_INTERFACE_VERSION &quot;MY_INTERFACE_001&quot;
</pre>
<p>This is what goes in the public header to be provided to consumers.</p>
<p>Interface classes generally start with the letter &#8216;<code>I</code>&#8216;, with the implementation in the provider having the same name but starting with &#8216;<code>C</code>&#8216;. This interface exposes a single function called <code>AddFive</code> which takes an integer as a parameter and returns another integer.</p>
<p>The string defined as <code>MY_INTERFACE_VERSION</code> is passed by the consumer into the providers factory (covered later) to instruct it on what interface to return. A version number is packed into this so that if the interface is changed and the provider and consumer&#8217;s copies are incompatible it fails to get the interface rather than crashing when trying to use it. With extra work it is also possible for a provider to return all previous versions of an interface.</p>
<p>Now, lets implement this interface. I&#8217;m going to do the function implementation inline with the class definition as it&#8217;s simpler that way, you can (and will probably want to) split this up.</p>
<pre class="brush: cpp; title: ; notranslate">
class CMyInterface: public IMyInterface
{
public:
	int AddFive(int input)
	{
		return (input + 5);
	}
} g_MyInterface;
</pre>
<p>As you can see, it&#8217;s very simple. The implementation derives from the public version of the interface class and implements the functions exposed. <code>g_MyInterface</code> acts as a global singleton for the interface, and will be covered shortly.</p>
<p>Next we&#8217;ll make it so other plugins can get this interface, ensure that your main class derives from <code>IMetamodListener</code> and add the prototype for <code>OnMetamodQuery</code> to your class definition.</p>
<pre class="brush: cpp; title: ; notranslate">
class SamplePlugin: public ISmmPlugin, public IMetamodListener
{
...
public: //IMetamodListener
	void *OnMetamodQuery(const char *iface, int *ret);
}
</pre>
<p>Need to hook up the <code>IMetamodListener</code> next, add the following line to the end of <code>SamplePlugin::Load</code>.</p>
<pre class="brush: cpp; title: ; notranslate">
g_SMAPI-&gt;AddListener(g_PLAPI, this);
</pre>
<p>Now we&#8217;re hooked up to Metamod:Source&#8217;s factory (I&#8217;m not going to cover implementing your own factory from scratch in this post), lets implement <code>OnMetamodQuery</code> so other plugins can get our new interface.</p>
<pre class="brush: cpp; title: ; notranslate">
void *SamplePlugin:: OnMetamodQuery(const char *iface, int *ret)
{
	if (strcmp(iface, MY_INTERFACE_VERSION) == 0)
	{
		if (ret)
			*ret = IFACE_OK;
		return static_cast&lt;void *&gt;(&amp;g_MyInterface);
	}
	if (ret)
		*ret = IFACE_FAILED;

	return NULL;
}
</pre>
<p>Again, really simple. Just return your singleton if the interface requested matches the string you defined.</p>
<p>Here is how you can get the interface in the consumer. This part is very simple, it&#8217;s just like getting any HL2 SDK interface, just with a different factory.</p>
<pre class="brush: cpp; title: ; notranslate">
int ifaceerror;
g_pInterface = (IMyInterface *)g_SMAPI-&gt;MetaFactory(MY_INTERFACE_VERSION, &amp;ifaceerror, NULL);
if (!g_pInterface )
{
	snprintf(error, maxlen, &quot;Could not find interface %s (error %d)&quot;, MY_INTERFACE_VERSION, ifaceerror);
	return false;
}
</pre>
<p>That&#8217;s it for just a simple interface, let&#8217;s add a listener so that the provider can trigger callbacks in the consumer.</p>
<p>Firstly, add an extra class to your public header to define your listener.</p>
<pre class="brush: cpp; title: ; notranslate">
class IMyListener
{
public:
	virtual void OnCallbackFired(void)
	{
	}
};
</pre>
<p>The empty <code>OnCallbackFired</code> implementation will be overridden with the clients if they implement it, you can use <code>= 0;</code> here to force them to.</p>
<p>Now, add Add and Remove functions to your interface, these will (de)register the listener with the provider. If Add is called but Remove isn&#8217;t called on unload, the server will crash due to accessing non-executable memory if one of the callbacks is fired.</p>
<pre class="brush: cpp; title: ; notranslate">
class IMyInterface
{
public:
	virtual int AddFive(int input) = 0;

public:
	virtual void AddListener(IMyListener *pListener) = 0;
	virtual void RemoveListener(IMyListener *pListener) = 0;
}
</pre>
<p>As before, these need to be implemented. We&#8217;ll be using the List structure provided with SourceHook to store all the added interfaces. An important point to note is that all calls to the listener&#8217;s functions need to take place from inside the interface implementation, or errors will occur.</p>
<pre class="brush: cpp; title: ; notranslate">
class CMyInterface: public IMyInterface
{
public:
	int AddFive(int input)
	{
		return (input + 5);
	}

public:
	void AddListener(IMyListener *pListener)
	{
		m_pPluginHooks.push_back(pListener);
	}

	void RemoveListener(IMyListener *pListener)
	{
		m_pPluginHooks.remove(pListener);
	}

	void NotifyListeners(void)
	{
		SourceHook::List&lt;IMyListener *&gt;::iterator iter;
		IMyListener *pListener = NULL;
		for (iter = m_pPluginHooks.begin(); iter != m_pPluginHooks.end(); iter++)
		{
			pListener = (*iter);
			pListener-&gt;OnCallbackFired();
		}
	}

private:
	SourceHook::List&lt;IMyListener *&gt; m_pPluginHooks;
} g_MyInterface;
</pre>
<p>All they are doing is adding and removing from the <code>SourceHook::List</code>. The <code>NotifyListeners</code> function is a simple one that loops all added listeners and fires the <code>OnCallbackFired</code> callback for each.</p>
<p>The provider can use</p>
<pre class="brush: cpp; title: ; notranslate">
g_MyInterface-&gt;NotifyListeners();
</pre>
<p>to call <code>NotifyListeners</code> from anywhere else in the plugin.</p>
<p>I think that pretty much covers everything, have fun implementing interfaces and listeners in your plugins!</p>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/blog/programming/interfaces-and-listeners/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>BackpackHook</title>
		<link>http://limetech.org/projects/backpackhook/</link>
		<comments>http://limetech.org/projects/backpackhook/#comments</comments>
		<pubDate>Thu, 14 Oct 2010 20:16:51 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=644</guid>
		<description><![CDATA[BackpackHook is a SourceMod extension that exposes some internals of the Team Fortress 2 item system, including exposing details such as renamed item names, equipped state and global ids.]]></description>
				<content:encoded><![CDATA[<div class='et-box et-warning'>
					<div class='et-box-content'>This project is no longer maintained, significant changes to Team Fortress 2&#8242;s internals removed functionality it was built upon.</div></div>
<p>BackpackHook is a SourceMod extension that exposes some internals of the Team Fortress 2 item system, including exposing details such as renamed item names, equipped state and global ids.<br />
<span id="more-644"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'><a href="https://forums.alliedmods.net/showthread.php?t=140614" target="_blank">See this project&#8217;s topic on AlliedModders for more info and discussion.</a></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/projects/backpackhook/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>RulesFix</title>
		<link>http://limetech.org/projects/rulesfix/</link>
		<comments>http://limetech.org/projects/rulesfix/#comments</comments>
		<pubDate>Fri, 17 Sep 2010 16:43:25 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=639</guid>
		<description><![CDATA[RulesFix is a very simple SourceMod plugin utilising designed to fix an issue affecting external information queries on Linux OrangeBox servers.]]></description>
				<content:encoded><![CDATA[<div class='et-box et-warning'>
					<div class='et-box-content'>This project is no longer maintained, the bug it corrected was fixed in an update to the engine.</div></div>
<p>RulesFix is a very simple SourceMod plugin utilising http://limetech.org/projects/steamtools/ designed to fix an issue affecting external information queries on Linux OrangeBox servers.<br />
<span id="more-639"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'><a href="https://forums.alliedmods.net/showthread.php?t=138375" target="_blank">See this project&#8217;s topic on AlliedModders for more info and discussion.</a></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/projects/rulesfix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>VPhysics</title>
		<link>http://limetech.org/projects/vphysics/</link>
		<comments>http://limetech.org/projects/vphysics/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 16:55:24 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=569</guid>
		<description><![CDATA[VPhysics is a SourceMod Extension to expose the API of the Source game server&#8217;s physics library of the same name to SourceMod Plugins. VPhysics is an extremely comprehensive physical simulation library built by Valve around the Havok and Ipion physics libraries, with an extensive C++ API.]]></description>
				<content:encoded><![CDATA[<p>VPhysics is a SourceMod Extension to expose the API of the Source game server&#8217;s physics library of the same name to SourceMod Plugins.</p>
<p>VPhysics is an extremely comprehensive physical simulation library built by Valve around the Havok and Ipion physics libraries, with an extensive C++ API.<br />
<span id="more-569"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'><a href="https://forums.alliedmods.net/showthread.php?t=136350" target="_blank">See this project&#8217;s topic on AlliedModders for more info and discussion.</a></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/projects/vphysics/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ZombieFix</title>
		<link>http://limetech.org/projects/zombiefix/</link>
		<comments>http://limetech.org/projects/zombiefix/#comments</comments>
		<pubDate>Fri, 06 Aug 2010 03:34:12 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=564</guid>
		<description><![CDATA[ZombieFix is a very simple SourceMod extension designed to fix a crash issue with Half-Life 2: Deathmatch game servers running on Windows when spawning NPC zombies, caused by an unfixed bug in the server code.]]></description>
				<content:encoded><![CDATA[<p>ZombieFix is a very simple SourceMod extension designed to fix a crash issue with Half-Life 2: Deathmatch game servers running on Windows when spawning NPC zombies, caused by an unfixed bug in the server code.<br />
<span id="more-564"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'><a href="https://forums.alliedmods.net/showthread.php?t=134536" target="_blank">See this project&#8217;s topic on AlliedModders for more info and discussion.</a></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/projects/zombiefix/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>UnVAC</title>
		<link>http://limetech.org/projects/unvac/</link>
		<comments>http://limetech.org/projects/unvac/#comments</comments>
		<pubDate>Mon, 19 Jul 2010 16:37:40 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=560</guid>
		<description><![CDATA[UnVAC is a Metamod:Source Plugin that allows server owners to whitelist specific players from Valve Anti-Cheat checks on connect, allowing them to let currently banned players into their servers. It was created as a proof-of-concept, but released when Valve started VAC-banning non-cheaters.]]></description>
				<content:encoded><![CDATA[<p>UnVAC is a Metamod:Source Plugin that allows server owners to whitelist specific players from Valve Anti-Cheat checks on connect, allowing them to let currently banned players into their servers.</p>
<p>It was created as a proof-of-concept, but released when Valve started VAC-banning non-cheaters.<br />
<span id="more-560"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'><a href="https://forums.alliedmods.net/showthread.php?t=132853" target="_blank">See this project&#8217;s topic on AlliedModders for more info and discussion.</a></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/projects/unvac/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SteamTools</title>
		<link>http://limetech.org/projects/steamtools/</link>
		<comments>http://limetech.org/projects/steamtools/#comments</comments>
		<pubDate>Wed, 16 Jun 2010 17:56:24 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=555</guid>
		<description><![CDATA[SteamTools is a SourceMod Extension that exposes the server-side portion of Valve&#8217;s Steamworks API to SourceMod plugins, utilizing the headers from the OpenSteamworks project.]]></description>
				<content:encoded><![CDATA[<p>SteamTools is a SourceMod Extension that exposes the server-side portion of Valve&#8217;s <a href="http://www.steampowered.com/steamworks/" target="_blank">Steamworks</a> API to SourceMod plugins, utilizing the headers from the <a href="http://opensteamworks.org/" target="_blank">OpenSteamworks</a> project.<br />
<span id="more-555"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'><a href="https://forums.alliedmods.net/forumdisplay.php?f=147" target="_blank">See this project&#8217;s sub-forum on AlliedModders for more info and discussion.</a></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/projects/steamtools/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>TFDodgeball</title>
		<link>http://limetech.org/projects/tfdodgeball/</link>
		<comments>http://limetech.org/projects/tfdodgeball/#comments</comments>
		<pubDate>Sun, 16 May 2010 12:33:57 +0000</pubDate>
		<dc:creator>Asher</dc:creator>
				<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://limetech.org/?p=546</guid>
		<description><![CDATA[TFDodgeball is a combination of a SourceMod Plugin and Extension that together provide an implementation of the popular Team Fortress 2 gamemode known as Dodgeball. It was the first open source implementation available and is highly configurable.]]></description>
				<content:encoded><![CDATA[<p>TFDodgeball is a combination of a SourceMod Plugin and Extension that together provide an implementation of the popular Team Fortress 2 gamemode known as Dodgeball.</p>
<p>It was the first open source implementation available and is highly configurable.<br />
<span id="more-546"></span></p>
<div class='et-box et-download'>
					<div class='et-box-content'><a href="https://forums.alliedmods.net/forumdisplay.php?f=145" target="_blank">See this project&#8217;s sub-forum on AlliedModders for more info and discussion.</a></div></div>
]]></content:encoded>
			<wfw:commentRss>http://limetech.org/projects/tfdodgeball/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Performance optimized by W3 Total Cache. Learn more: http://www.w3-edge.com/wordpress-plugins/

Minified using apc
Page Caching using apc
Database Caching using apc
Object Caching 980/1031 objects using apc

 Served from: limetech.org @ 2013-05-20 13:55:30 by W3 Total Cache -->