ID:265921
 
Since there is little-to-no documentation on the proper way to define and handle things on an interface, etc... I was hoping someone with proper knowledge could clear a few things up for me (and anyone else unaware).

First off: Any tips on how to reduce lag (aside from connection, the host, etc..) would be great! I am already familiar with mirrored resource(.RSC) files taking the strain off of the host machine when new clients log in, and to limit and allow pauses/breaks in loops, but I honestly have no clue how to be efficient.

The use of interface objects seems too easy, and from past experience with BYOND, too easy = bad results. I have no real way of testing the client-side experience of my programming first hand, since I am always hosting my files, but is there a negative impact on having a good-sized amount of interface objects to handle most things? IE: I have 10 different 32x32 grids that handle each equipment piece the player has, one output box, one input box, one grid that serves 4 different purposes based on the 6 buttons clicked, over a dozen graphical labels, 3 bars, one map, a few browsers, and a little more. Some of them are invisible unless toggled, but all seem necessary to me.

I want my game design to be as well oiled as possible before release, while not sacrificing the necessary representation it serves so far. I've known that too many screen objects can bog down a player and I am hoping that this is not the case with interfaces.

Aside from that any other tips would be wonderful, share your knowledge and hopefully some day there will be proper instructions on game design efficiency with BYOND.
The interface is like a double edged sword. Every time you call winset(), the entire interface is sent over! You need to be careful with winset()*, preferably by lumping a couple of winset()'s together as need be (winset(src,null,"input.text=YES;output.color=#FFFFFF;morestu ff")). You can also send associated lists as through winset(). Also, winget() is rather laggy because of how client transfer data (or something like that), so it's best to lump winget()'s together (also takes lists).

*To the extent that you aren't calling it every tick when it isn't necessary. For example, health bars shouldn't be winset()ing every tick if the user's health percentage didn't change.
In response to Jeff8500 (#1)
Last I knew, grouping winset and winget calls is indeed a good idea. However, the reason was because of the way successive calls are buffered and sent each tick. I'm not sure where the idea that "the entire interface is sent over" came from. (Of course, I'm getting my information from a part of an old, private thread. "Little-to-no documentation" is right.)

As for the number of interface controls mentioned in the original post, I don't believe they have an effect. One should be concerned with how often controls are updated rather than how many exist at all.
In response to ACWraith (#2)
Lummox brought that, or something similar, up when I asked about sending winget()'s each tick.
In response to Jeff8500 (#1)
Thanks, I knew about grouping parameters but I had no idea about the entire interface being sent each time a relative object is called. Is there any way you can dig up this post? It may contain a little more information on what I'm getting into.

For me, the only time an interface object is updated is when an action makes it update, otherwise it's stationary. But during combat that could happen quite often. So I should probably move a few of the objects on the interface into the client screen... or is it still more efficient than screen objects?

I do wish there were some sort of general information on how some things work behind the scenes.. :S
In response to ACWraith (#2)
ACWraith wrote:
Last I knew, grouping winset and winget calls is indeed a good idea. However, the reason was because of the way successive calls are buffered and sent each tick. I'm not sure where the idea that "the entire interface is sent over" came from.

That must have been a misunderstanding. Calls to winset() only affect the specified controls. It is best to group them for two reasons:
1) each winset() call is a separate server->client packet that has to be constructed, sent, and processed.
2) each winset() call results in a refresh of the corresponding interface elements, which can result in flicker if done more frequently than needed.

Winset() and winget() should be reasonably efficient- the packets themselves are small and the overhead is low. They should update as fast as the map does, within the tick. While the system wasn't really designed for frequent real-time updates, I think they'll work ok. You could always test by running, say, a skinned countdown-timer that updates every tick and see how it does hosted remotely.
In response to ACWraith (#2)
winset() should process as soon as it is received by the client, so in effect the only real gain is that you're processing fewer commands and sending fewer network packets. It is more efficient to group those for that reason.

winget() is processed in much the same way as input(). That has one disadvantage in that while I believe more than one input prompt (alert, input, winget, etc.) can be processed in a tick, the reply usually won't be handled until the following tick unless communication is very fast. When an input or such is called, it puts the current proc on hold, and when the reply comes in the proc goes back onto the to-do list; if the tick is already done going through that list, the to-do list won't be processed until the next tick. So for efficiency's sake, winget() is definitely best to group together and parse after the fact. I recommend using the new grouping abilities of winget() whenever possible.
In response to Tom (#5)
Tom wrote:
You could always test by running, say, a skinned countdown-timer that updates every tick and see how it does hosted remotely.

A project of mine already does this; the timer runs pretty smoothly, but I remain an efficiency freak and for the sake of it I'd still like a way for the client to perform the countdown without extensive network traffic being involved. =P
In response to Android Data (#7)
What? Like full fat-client side functioning? That'd be odd because the server would still need to send a packet to the client alerting it to start the ticker/counterdown-timer, but yeah, it's better than sending a packet every tick.
In response to Jeff8500 (#1)
Jeff8500 wrote:
The interface is like a double edged sword. Every time you call winset(), the entire interface is sent over! You need to be careful with winset()*, preferably by lumping a couple of winset()'s together as need be (winset(src,null,"input.text=YES;output.color=#FFFFFF;morestu ff")). You can also send associated lists as through winset(). Also, winget() is rather laggy because of how client transfer data (or something like that), so it's best to lump winget()'s together (also takes lists).

*To the extent that you aren't calling it every tick when it isn't necessary. For example, health bars shouldn't be winset()ing every tick if the user's health percentage didn't change.

Why do that when you could use a browser designed for HP display? In fact, how /would/ you use winset for a health bar? Maybe 2 images at the same position that are 200x16 and the one on top green, the one on bottom red, and changing the width of the green bar to HP*2 whenever the player is damaged. You could generate a simular thing with a brower, though. I've done it with text instead of mages, though the concept's the same.
In response to Guy Hendricks (#9)
Simply because we have bar controls now.
In response to Guy Hendricks (#9)
Because it was a misunderstanding, the entire interface isn't sent over. It does have a negligible 0.5 second delay, though, so you just have to string your calls together wisely.