I have just started a new version of my Crysis Wars Server Side Modification called InfinityX. For better management, I have put the functions inside tables as it looks neater and I can group functions together (like Core.PlayerHandle:GetIp(player)), but I have ran into a problem.
The problem is that the specified method to get the players' name, player:GetName() is being seen as an invalid method, when the method actually is completely valid.
I would like to know if using the below structure is causing a problem and if so, how to fix it. This is the first time I've used this structure for functions, but it is already proving easier than the old method I was using.
The Code:
Event =
{
PlayerConnect = function(player)
Msg.All:CenteredConsole("$4Event$8 (Connect)$9: $3"..player:GetName().." on channel "..player.actor:GetChannel());
System.LogAlways(Default.Tag.."Incoming Connect on Channel "..player.actor:GetChannel());
Event:Log("Connect", player);
end;
};
The below code works when I bypass the function and put the code directly where it's needed:
Msg.All:CenteredConsole("$4Event$8 (Connect)$9: $3"..player:GetName().." on channel "..player.actor:GetChannel());
System.LogAlways(Default.Tag.."Incoming Connect on Channel "..player.actor:GetChannel());
The Error:
[Warning] [Lua Error] infinityx/main/core.events.lua:23: attempt to call method 'GetName' (a nil value)
PlayerConnect, (infinityx/main/core.events.lua: 23)
ConnectScript, (infinityx/main/core.main.lua: 52)
OnClientEnteredGame, (scripts/gamerules/instantaction.lua: 511)
(null) (scripts/gamerules/teaminstantaction.lua: 520)
Any clarification would be appreciated.
Thanks :)
Well, as PlayerConnect is inside the table Event, and you are calling with a ":", add self as first arg in the function, like:
PlayerConnect = function(self, player)
Clearly, player in the first block of code is not the same as player in the second block of code. The problem must be that the caller of Event.PlayerConnect is not passing the same value.
To test that your Event.PlayerConnect function works, try this in the same place as your second block of code:
Event.PlayerConnect(player)
That should work as you expect.
So, the problem comes down to how Event.PlayerConnect is called without the second block of code. I'm not familiar with that game engine so I don't know how it is done. Perhaps reviewing the documentation and/or debugging that area would help. If you print(player) or call the equivalent log function in both cases, you should see they are different. If you can't run in a debugger, you can still get a stack trace with print(debug.traceback("Accessing player, who's value is: "..player)). If there is indeed some kind of table-based player object in both cases, you can try comparing their fields to see how they are different. You might need to write a simple dumping function to help with that.
Related
I've a function which is called from different components, .cfms or remotely. It returns the results of a query.
Sometimes the response from this function is manually inspected - a person may want to see the ID of a specific record so they can use it elsewhere.
The provided return formats, being wddx, json, plain all aren't very easily readable for a layman.
I'd love to be able to create a new return format: dump, where the result first writeDumped and then returned to the caller.
I know there'd be more complicated ways of solving this, like writing a function dump, and calling that like a proxy by providing the component, function and parameters so it can call that function and return the results.
However I don't think it's worth going that far. I figured it'd be great if I could just write a new return format, because that's just... intuitive and nice, and I may also be able to use that technique to solve different problems or improve various workflows.
Is there a way to create custom function returnFormats in ColdFusion 10 or 11?
(From comments)
AFAIK, you cannot add a custom returntype to a cffunction, but take a look at OnCFCRequest. Might be able to use it to build something more generic that responds differently whenever a custom URL parameter is passed, ie url.returnformat=yourType. Same net effect as dumping and/or manipulating the result manually, just a little more automated.
From the comments, the return type of the function is query. That being the case, there is simply no need for a custom return format. If you want to dump the query results, do so.
queryVar = objectName.nameOfFunction(arguments);
writeDump (queryVar);
I'm using the World of warcraft API. And I want to find an EventMessageFilter. I can do so by calling
ChatFrame_GetMessageEventFilters("event")
And to do this I have to pass a chat event, in my case CHAT_MSG_WHISPER_INFORM.
So according to the API located over at
http://wowprogramming.com/docs/api/ChatFrame_GetMessageEventFilters
This function will return a table. So I named the table and tried to print its content with this code
local myNewTable = filterTable = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
for i in pairs(myNewTable) do
print(asd[i])
end
And this then prints out something like
function: 00000312498vn27842934c4
I have checked with
type(asd[i])
and it really is a function. But how can I get the content of it? How do I handle it?
I want to find an EventMessageFilter
Can you elaborate? Whose filter are you looking for and what do you intend to do with it?
it really is a function.
That's what this API does: returns a list of functions that are registered as filters for a particular message type (via ChatFrame_AddMessageEventFilter).
But how can I get the content of it?
You can't. The WoW API doesn't offer you any facilities for decompiling functions.
If your intention is to filter chat messages yourself, you don't need to call this function at all. Just call ChatFrame_AddMessageEventFilter to add your filter.
So I managed to solve my problem by removing to current filters that have been put in place by another addon and then just add my own filter. As Mud pointed out. GMEF was supposed to return functions. I now see how this makes sense. But now I have made the code to remove the functions. If you want to re-add them later on, just store them in a variable until you are done but I won't include this in my answer. I also feel like my answer is kinda half off-topic ish. But to answer my own question. It is supposed to return functions and you can't see the contents of these functions. This is the code I used to remove the functions that were put in there by another addon.
function rekkFilters()
local myFilters = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
for i in pairs(myFilters) do
ChatFrame_RemoveMessageEventFilter("CHAT_MSG_WHISPER_INFORM", myFilters[i])
end
end
local myFilters = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
rekkFilters()
local myFilters = ChatFrame_GetMessageEventFilters("CHAT_MSG_WHISPER_INFORM")
if myFilters[1] ~= nil then
rekkFilters()
end
I'm having a problem with my code and I don't know what's up, I've searched online and the _Gx method was suggested as the best way over ones like loadstring(x)... although I would be happy with either, can't get either one to work. What I want to do is, in ComputerCraft, send a function name and argument to a turtle, which I'm doing by saving both values to a table and sending across the table, and then on the turtle's program, have a big list of functions, and using a command, call them from the string sent and insert the arg as well. My error is "attempt to call nil", which I don't quite understand why it's saying that... Thanks in Advance!
EDIT
I've edited my code down, as asked, to show that even stripping all else away, this still fails. I could even strip it down even more by taking the variable completely out, and putting the string straight into the _G. This still fails even doing it like that. I've decided to keep it in because that's how I am actually going to be using it later. Calling the function normally works fine. I'm using version Luaj-jse 2.0.3
function foo ()
print ("HI!")
end
print (_VERSION)
I don't know what rednet is, but it seems like you passes name of function to another Lua VM, which doesn't know anything about this function (this function is absent in that VM's globals table).
So, passing function definition as string and executing it by receiver with loadstring is the only solution.
I am trying to do something like:
String.prototype.print=function(){trace(??????)}
I can't for the life of me figure out a way to get at the string! Yes I know there are other ways to approach this etc. but...
Not sure what the problem is, using this works fine in anonymous functions.
String.prototype.print=function():String{return "printed "+this;}
var o:Object = "foo";
trace(o.print()); // traces: printed foo
I just tricked the compiler to use an object, because "foo".print() causes
Error: Call to a possibly undefined method print through a reference with static type String.
It looks like you are mixing ActionScript 2 into your ActionScript 3 code. As kapep said, using "this" will work in your example. That is, this is perfectly valid code:
String.prototype.print=function(){trace(this)}
Of course, you are missing a semi-colon but that shouldn't matter:
String.prototype.print=function(){trace(this);} //semi-colon after 'trace(this)'
Depending on your development environment, you might be having trouble viewing trace statements, in general. In Flex Builder, for example, trace statements don't show up at all unless you are in Debug mode. Insert another call to trace to verify that you can see trace statements.
As you said, there are many other ways to approach this, such as extending the String class and adding your "Print" function. If you really can't get this to work, then trying an ActionScript 3 (i.e. Object-Oriented) approach might be your best option.
Do you check for data validity in every constructor, or do you just assume the data is correct and throw exceptions in the specific function that has a problem with the parameter?
A constructor is a function too - why differentiate?
Creating an object implies that all the integrity checks have been done. It's perfectly reasonable to check parameters in a constructor and throw an exception once an illegal value has been detected.
Among all this simplifies debugging. When your program throws exception in a constructor you can observe a stack trace and often immediately see the cause. If you delay the check you'll then have to do more investigation to detect what earlier event causes the current error.
It's always better to have a fully-constructed object with all the invariants "satisfied" from the very beginning. Beware, however, of throwing exceptions from constructor in non-managed languages since that may result in a memory leak.
I always coerce values in constructors. If the users can't be bothered to follow the rules, I just silently enforce them without telling them.
So, if they pass a value of 107%, I'll set it to 100%. I just make it clear in the documentation that that's what happens.
Only if there's no obvious logical coercion do I throw an exception back to them. I like to call this the "principal of most astonishment to those too lazy or stupid to read the documentation".
If you throw in the constructor, the stack trace is more likely to show where the wrong values are coming from.
I agree with sharptooth in the general case, but there are sometimes objects that can have states in which some functions are valid and some are not. In these situations it's better to defer checks to the functions with these particular dependencies.
Usually you'll want to validate in a constructor, if only because that means your objects will always be in a valid state. But some kinds of objects need function-specific checks, and that's OK too.
This is a difficult question. I have changed my habit related to this question several times in the last years, so here are some thoughts coming to my mind :
Checking the arguments in the constructor is like checking the arguments for a traditional method... so I would not differentiate here...
Checking the arguments of a method of course does help to ensure parameters passed are correct, but also introduces a lot of more code you have to write, which not always pays off in my opinion... Especially when you do write short methods which delegate quite frequently to other methods, I guess you would end up with 50 % of your code just doing parameter checks...
Furthermore consider that very often when you write a unit test for your class, you don't want to have to pass in valid parameters for all methods... Quite often it does make sense to only pass those parameters important for the current test case, so having checks would slow you down in writing unit tests...
I think this really depends on the situation... what I ended up is to only write parameter checks when I know that the parameters do come from an external system (like user input, databases, web services, or something like that...). If data comes from my own system, I don't write tests most of the time.
I always try to fail as early as possible. So I definitively check the parameters in the constructor.
In theory, the calling code should always ensure that preconditions are met, before calling a function. The same goes for constructors.
In practice, programmers are lazy, and to be sure it's best to still check preconditions. Asserts come in handy there.
Example. Excuse my non-curly brace syntax:
// precondition b<>0
function divide(a,b:double):double;
begin
assert(b<>0); // in case of a programming error.
result := a / b;
end;
// calling code should be:
if foo<>0 then
bar := divide(1,0)
else
// do whatever you need to do when foo equals 0
Alternatively, you can always change the preconditions. In case of a constructor this is not really handy.
// no preconditions.. still need to check the result
function divide(a,b:double; out hasResult:boolean):double;
begin
hasResult := b<>0;
if not hasResult then
Exit;
result := a / b;
end;
// calling code:
bar := divide(1,0,result);
if not result then
// do whatever you need to do when the division failed
Always fail as soon as possible. A good example of this practice is exhibited by the runtime ..
* if you try and use an invalid index for an array you get an exception.
* casting fails immediately when attempted not at some later stage.
Imagine what a disaster code be if a bad cast remained in a reference and everytime you tried to use that you got an exception. The only sensible approach is to fail as soon as possible and try and avoid bad / invalid state asap.