The C version will not be two times faster than the C# version. I'm not sure that the C version would be faster at all.
Warning: the stuff below is my own opinion and other people might not agree with me.
This isn't really a question of optimisation it's a question of having good coding practices. The whole "premature optimisation is the root of all evil" thing is a misquote lazy programmers come out with as an excuse for writing bad code.
There are three kinds of optimisation:
Optimisation that comes from good coding practices (like above)
Optimisation that comes from having a good design
Optimisation that comes from measuring performance and focusing on the slowest areas
Only the third item can be considered a premature optimisation if you do it too early, the first is something you should be thinking about all the time and the second you should be thinking about before you write a line of code. Now all this is not to say that you should sacrifice readability for performance, first and foremost you should write code that's easy to read, but if you are finding it hard to optimise your code while maintaining legibility that would suggest that there is something wrong with your design or your algorithms.
So basically I would not consider the (C/C#) code examples above to be a symptom of premature optimisation, I consider them to be examples of fundamental good coding practice.
Yes you can refer to it as a reference, as it's a reference to an object on the heap. You are making a copy of the reference and storing it inside a variable.
It is a common mistake many programmers make to perform expensive operations multiple times. It is however dependent on your domain knowledge, that is, your knowledge of what is happening beneath the covers in a language. Take these two programs that both take a string and print out each character on a separate line.
string str = "Hello, world!";
for (int i = 0; i < str.Length; i++) { Console.WriteLine(str[i]); }
int i; char str[] = "Hello, world!";
for (i = 0; i < strlen(str); i++) { printf("%c\n", str[i]); }
The first program is C# and the second is C. Both of these programs look similar and both have fundamentally the same code, except that the C# version will run many times faster than the C version (yes even through C is C and supposed to be SUPER FAST OMG!)
The reason for this is how they each handle strings internally. In both languages string are just arrays of chars, but what differs is how each language determines the length of the string. In C strings are NULL terminated, meaning that the last character of each string is NULL (or '\0'). In the example above that fact is hidden from you, as the compiler is smart enough to add that NULL character automatically.
The actual array of chars that the compiler initialises looks like this, with a NULL char appended on the end:
So how does strlen figure out the length of a string?
int strlen(char* str) { int i = 0; while (str[++i]); return i; }
It loops through the str counting each character until it finds a NULL (which is the same as false in C) and then returns the count. So each time the for loop in the example calls strlen is has to loop through the entire string to find the NULL. What if the string was thousands of characters long? That would take a long time.
C# however is a different beast. The .NET framework doesn't use NULL terminating characters to deliminate strings, instead it uses a system known as PASCAL strings, or length-prefixed strings. What that means is that each string in .NET is prefixed with a hidden int that contains the the length of the string that follows it. You can imagine it like this:
This is a gross simplification as .NET actually uses 16-bit wide unicode strings to store text and the header is way more complicated, but anyway... So how does the .NET framework get the string length? Simple, it just returns the header. So as you can see, two pieces of code which appear to do the same thing, actually have massively different consequences depending on how the underlying function calls are implemented.
The basic point is that there is no "right-way" to do these kinds of things, it depends on the language, the framework and the implementation. The only way you can decide whether its OK to call a function or a property in a loop or multiple times is by having as much domain knowledge of the underlying architecture as possible.
(Note: In the .NET Framework library as rule of thumb properties such as length are almost always pretty efficient and expensive operations are normally wrapped in function calls).
if (Connections[GetConnIdx(CPR.UCID)].Stat == StatType.Officer) { // Do something. }
This makes the code easier to read and also safer, as you now get compile-time checking of the stat property.
While I'm at it this sort of code is incredibly inefficent:
if (Connections[[b]GetConnIdx(CPR.UCID)[/b]].Stat == 2) { InSim.Send_MTC_MessageToConnection("^2•^7 You are a On-Duty cop so FOLLOW THE RULES!", CPR.UCID, 0); Connections[[b]GetConnIdx(CPR.UCID)[/b]].IsOfficer = 1; } else { InSim.Send_MST_Message("/spec " + Connections[[b]GetConnIdx(CPR.UCID)[/b]].Username); InSim.Send_MTC_MessageToConnection("^1You are Not a Officer!", CPR.UCID, 0); Connections[[b]GetConnIdx(CPR.UCID)[/b]].IsOfficer = 0; }
GetConnIdx() iterates through the entire connection list each time you call it and in this short section of code it's being called four times! Instead you should do this:
if ([b]conn[/b].Stat == 2) { InSim.Send_MTC_MessageToConnection("^2•^7 You are a On-Duty cop so FOLLOW THE RULES!", CPR.UCID, 0); [b]conn[/b].IsOfficer = [b]true[/b]; // Make IsOfficer a bool!! } else { InSim.Send_MST_Message("/spec " + [b]conn[/b].Username); InSim.Send_MTC_MessageToConnection("^1You are Not a Officer!", CPR.UCID, 0); [b]conn[/b].IsOfficer = false; }
Not only is this much much faster it also makes the code easier to read. Of course a better solution is to make Connections a hash table, then you don't need to loop through the list at all.
Yeah, I think that was what it was supposed to do originally, not sure why I didn't update it. Anyway I uploaded a new version that exports only the filtered packet list. There is a option in the options dialog to revert back to the old functionality.
I imagine the UI would be flooded with packets if you left it on for days. Still it's heartening to know it still works after running for so long. Maybe a version that wrote packets to log files would be better?
I don't really know PHP (as I'm sure everyone has worked out ), but I think your syntax is a bit mixed up. I think you have the registerPacket parameters the wrong way round. Also in PHP you don't need to specify the type of the param (maybe it's optional though, I dunno). Try this:
public function __construct() { $this->registerPacket('ConConnects', ISP_NCN); }
public function ConConnects($NCN) { $MTC = new IS_MTC(); $MTC->UCID($NCN->$UCID)->Msg(sprintf('%s ^7Welcome to %s', self::PreMsgStl, self::GameName))->Send(); return PLUGIN_CONTINUE; }
It's basically just about setting the bits to turn the colours on and off. For instance if you wanted to make a button that was clickable, had a light background and used the title colour (colour 1), you would do this:
BStyle = ISB_CLICK | ISB_LIGHT | [b]1[/b]
Or if you wanted to use the cancel colour (colour 5):
BStyle = ISB_CLICK | ISB_LIGHT | [b]5[/b]
Here is a pyinsim example which sends a button with one of those bits set:
Japanese, Korean, Traditional and Simplified Chinese are double-byte (or really multi-byte) character sets. You can check by typing a Japanese character into LFS and comparing the lead and tail bytes to the CP932 codepage.
I realised the other day that the codepage for each language is listed at the top that language's translation file in the LFS directory. Using this source I can confirm that these are correct. I see no reason to presume that the translation files within LFS would specify anything other than the correct codepage.
[B]tx_codepage 932[/B] tx_langname “ú–{Œê tx_noun_adj an 3g_tr_selct TRAINING 3g_tr_title Select Lesson
...
I've been messing around with the encodings over the last few days and to be honest I've learned more about single-byte and double-byte character sets than I can stand .
I've noticed some people are still downloading the old version of the library. The old < 2.0 version has been left for archive purposes only. For all new pyinsim programs you should use the most recent stable version, which is always available on CodePlex. The only reason you would ever need to download the old version of library is if you need to work with legacy code.
To summarise: do not download the old version of pyinsim unless you have a very good reason to. In almost all cases the latest stable release is what you want.