tModLoader WireMod

So, as the ninja mouse I am I played with the WireMod source while the cat was away, and ended up with a new device meant to store values.
(It might be hard to see, but yes, the yellow led gets turned off. )

It would be usefull in plenty of places, such as storing the result of a mathematic addition to then use it later, store the name of a player somewhere to then being able to check if he is the one using the same mechanic stuff at a later time, and I'm wondering about how to use time values (To prevent, for example, a player from using one mechanic stuff twice in a row in less than [1/5/3600/ any constant time value / depending on other variables] seconds. )



This variable device has one issue that I can't fix (lack of knowledge).
If this variable is connected to other variable, it might lead to a loop changing its value once per frame, nothing exceptionally problematic so far, unless it is connected to math devices and to a sensor to create a logic such as this one :

The variable gets incremented by one every frame =>
It stops being incremented once a player gets close =>
It displays its value on text display tiles.

As the framerate is computer dependent, one client might run a bit faster than another one (I don't have the necessary setup right now to test it properly).
Example, one player with a nice computer will see that 7500 frames happened before the end of the loop.
Another one had a few framedrops because some explosions happened and lots of mobs were killed or whatever: He will see that only 7430 frames happened.


I believe those variables should be server-sided only, and should be sent to clients only during the frames where something really happened, such as the variable actually opening a door, changing the value of a torch, but also once in a while (lets say once per second) so a client might watch if the value gets modified. But I have no clue on how to create this behavior, and I'm not even sure if it's actually a good way of doing it, or even if it's worth being considered as there might only be a few cases where such kind of bug might break something .
 
Last edited:
Thanks a lot! I've merged in your pull request, but I've changed a fair bit, and renaming files squashes changes, so take a look over what I did here.

So I decided to see what happens when I create a loop, adding 1 to the output and feeding it back into the input. As it turns out, my rudimentary circular logic protection stopped me from doing it. But no problem, because adding another 0 to the output works fine - check out the result here:

enTBna1.gif


On-screen it goes up by one, the GIF was just recorded at a lower FPS so here it jumps by more than that.

I'll have to test what happens if multiple players with differing FPS all debug the same value. I'll set a hard limit on how often the input can be updated, which will alleviate some problems. That's why I moved the write logic to the Update(GameTime) method in preparation.

I've also just pushed today's offering: auto-detected data types! The variable device also now uses this, so no need for additional devices for booleans, strings etc.

I've also bumped the version number to v0.9.4 and updated on ModBrowser.
 
I think i've got the perfect lab mouse to test it, as a friend of mine have both a bad computer and a high-ping internet connection. I'll make some tests with both him as a server owner and him as a client, and will check if there are ways of creating real desync, or if it will just be stuffs happening seconds later.
 
Currently only the following actions send sync messages:
  • Placing a device
  • Removing a device
  • Connecting pins
  • Disconnecting pins
  • Manually changing a setting (currently only when right-clicking one of the 4 constants to set its value)
  • TripWire (Flip/Flop device)
  • Request all data (on player entering world)
All of these are designed to send minimal data, usually just a few numbers, so with only these messages there's little chance of overloading the server - the only one that sends 'lots' of data is the Request, but that's also the least frequent.

During my earlier testing of MP, there was an occasional bug where different players would sometimes see a device in a slightly different place (one tile higher or lower), so the connections didn't line up, leading to differing behaviours. I could never replicate it reliably, so I have no idea if my attempts to fix it actually did anything. Rejoining requests all the data from the server, which has the definitive list, so at least the desyncs aren't permanent.

I guess the clients could occassionally request all the data from the server again to force synchronization, but that seems like a dodgy workaround rather than actually fixing anything.
 
Last edited:
I've pushed a small change to the NPC distance sensor to output the NPC name as well as the distance (to match the player distance sensor), so you can do this:

bQ4cDZ0.png


I'm currently working on getting pins by name (it works, I just need to convert it all over), so you can use e.g.
Code:
this.GetPin("Reset")
instead of
Code:
this.Pins["In"][1]
for named pins, or
Code:
this.GetPinIn(1)
for all pins.
 
1566418766-texttile.png


(Just in case it'd be needed to create wood/stone/whatever alternate for such tiles, I made a separate png for the text only)
1566418773-latin1text.png


I made that quickly (well, almost quickly) (not really proud of the font :().
Combined with something close to this :

Code:
private static int GetStyle(string inputChar)
        {
            Encoding ccc = Encoding.GetEncoding("ISO-8859-1");
            byte[] by = ccc.GetBytes(inputChar);
            return String.Equals(inputChar, ccc.GetString(by)) ? by[0] : 0;
        }

It should be able to display all 191 Latin1 characters (actually 189,RIP french ç and upper ç, the "cédille" can't fit in), but i'm not sure how to really implement all the steps required to make it work. Alternates are a mystery to me.
 
Woah, thank you! This is miles better than my paltry efforts - I'm really not much for sprite design (as you may have already guessed :p). Also, good call making the characters bigger, I was starting to regret my decision around the letter G, and definitely regretting it by Q.

I'll need a bit to get what I'm working on now (to be revealed later!) somewhat stable, then I'll move branch and implement this.
 
Well that was remarkably easy. All I had to do was paste in the code snippet you gave and change
Code:
tiles[i].frameX = (short)(style * 18);
to
Code:
tiles[i].frameX = (short)((style % 16) * 18);
tiles[i].frameY = (short)((style / 16) * 18);
and hey presto, new font and more (and bigger) characters!

7kVQLxr.png
 
And now for the reveal...

dbcR4Bv.gif


Tile copy / paste devices!

This is still very much under development, and copies a lot more data than any other device BY FAR, so be careful with how big you make the copy area.
I also need to figure out how to get tiles to 'glue' back to each other nicely instead of it looking like it does now.

This obviously has a lot of potential for misuse, so I've added a tile ID blacklist - that way you can't spawn more Demon Altars and the like - and I'll possibly also add an area size limiter.

EDIT: I found an easier way that requires less data and copies everything correctly:

HbrvePp.png


I've tested it in conjunction with a TileCounter, and it's simple enough to make a building regenerate when it loses enough blocks.

This is also begging for a permission system, as it can very easily be abused to endlessly mine a tile for resources.
 
Last edited:
Devices with access to chests, or Magic-Storage equivalent / integration, might make the mod able to force people to put in storage devices the tiles required to build the copy ? (Access to chests would be fun somehow as maybe they could also lead to some interesting future features , inside the "maybe one day" category, or as a "95% of the stuffs required is there, you only need to make a mod depending on WireMod to make it in half a minute" category, to make stuffs such as player stores, some kind of complex factories...

Some buildings might be stored in binary files and somehow accessible from your devices ? This way, you could export / import your creations from one world to another ?

The feature is really amazing, it was worth the suspense :pinky:. It could even end up working on a randomly generated labyrinth ...

I'll start searching on ways to hijack the moment when players hit/destroy/place tiles, and try to find a way to prevent some areas from having tiles destroyed, having tiles placed, dropping items when tiles gets destroyed (If a tile is set to "auto respawn" with your device, and if it doesn't cost any item to make them respawn, then it feels alright for them not to drop the item).

Or i could try to learn how to build UI. Or do some binary files / stream serialization snippets. Or something else. Your call actually, I just want to help properly, as at the rate your mod goes, most of the ideas I had for my own mods either become obsolete or would become instantly way cooler if it could be used along your devices.
 
Also, maybe i'm overthinking, but wouldn't those devices require some more "secure" implementation? Like maybe a new "Method,function, dostuff" device family, that would do their stuff once they are called with something such as a special pulse, then return a special pulse once they are finished doing their business? Along with a "big" device with a lot of pins, being able to handle methods, and being able to ensure the operation order of those methods is defined?

Right now, if there are multiple copy and paste devices in the same area, it is complex to make sure the right device is called before the wrong one, i believe the last device you place will do its stuff last.

I believe both of the implementations could fit in the device, that shouldn't force poeple to use that "big device" if there is no need for it in one area.
 
I love the idea of a labyrith that changes as you navigate it, and it would combine well with some mob trap rooms as in the examples on the wiki.

Chest access devices are another 'kinda planned' feature, but I don't think I'd go as far as requiring the items before pasting them. It may cut down on individual users misusing them, but would hinder larger constructions which may need to be used many times and without an 'admin' there to top up the chests.

Compatibility with other mods is a massive unknown right now as I have zero experience with such things. I can already think of a few places in the code where it may cause problems, but that's yet another problem for later.

The TilePaster is activated by a Trigger device, which is a bit different from all the others in that it calls the Trigger method on the TilePaster directly (because it implements the ITriggered interface). Which device it triggers depends on its TriggerType setting - All, Sequential or Random. All and Sequential are based on the order in which the devices are connected to the Trigger, which is also the order in which they appear in the debug UI panel. It's not the most robust ordered system, but it ought to do for 99% of use cases.

I did some digging into making tiles indestructible, and I found an annoying lack of hooks for tile events, and the way the tiles are built from TileObjectData makes them much harder to modify after the fact. My best idea for adding it is to use IL Editing to add a property to the Tile class (e.g. called Destructible) and modify the WorldGen.CanKillTile(x, y) method to check that new property. I have no idea if IL Editing can even add properties, but that's as far as I got as I didn't want to start diving into that level of madness.

The classic answer to 'what needs doing?' is 'fix bugs', but if I can't bring myself to really dig into them, then I can hardly expect you to do so. That being said, if you ever feel the urge to squash some bugs, you can check out the GitHub Issues page. Otherwise, just start creating whatever you imagine will fit / be useful. I don't really have more than that at the moment I'm afraid. Personally I need to fix at least two of the bugs before I can release v1.0, so I'm going to have to force myself to tackle them before making more under-the-hood changes.
 
So I've (mostly) fixed two big bugs: Zooming and Textboxes.

Zooming now works at any scale, as long as Zoom and UI Scale are identical. I may one day remove the device rendering from the UI rendering system, but for now this enough of an improvement for me to be happy with it.

Textboxes now no longer propogate user inputs - other than numbers, which will still cause the player to switch to the item in that number slot. No idea why.

I think my next big job will be to generally improve performance. I do most of my development on a laptop, and with my test world slowly filling up with devices there's now a noticable performance difference when devices are visible vs. when hidden. I've narrowed down the culprit to the ElectronicsVisionUI.DrawWires method (it draws all the wires, go figure :p) but I'll be damned if I know how to improve performance. Either I'm doing something really heinous (probable), or it just doesn't want to draw a few dozen thin rectangles without taking a ton of resources (improbable).
 
Last edited:
I've pushed a small update to improve performance when drawing wires. On my not-a-gaming-laptop, this has reduced the FPS drop from 50-60% down to only 10-20%, which seems far more reasonable.
 
I saw in the tile copy / paste example that you were using a lever to toggle it, although there doesn't seem to be a feature that lets me convert a vanilla pulse to a modded one. Can you post the wiring behind it or show me how? It's the only thing holding me back at the moment - I'm very good with vanilla wires and logic gates.
 
@Haku Here's the schematic for it. The circuit on the right is to regenerate (re-paste) the building when it drops below a given number of blocks.
w4WLKrR.png

It's not at all clear from the image, but the vanilla wire is actually connected to the Trigger device connected to the TilePaster, not to the TilePaster itself.

Right now the Trigger device is the only one to receive vanilla wire pulses. This will change in future, it was just the most logical place to test what is still a very new feature.
 
So, i found something interesting while trying to make a "gold coins shower" for a showcase video.

Tiles Paster doesn't Update its tiles nor nearby tiles, I don't know if it's a good or a bad thing:

1567163264-capture.png


Gold coins can only be placed on solid tiles, and when there isn't solid tiles under those, they fall. As seen on the picture, they don't. Placing a tile near them, or hitting one coin with a pickaxe will make them all fall.
It could be a feature, but thing is, it might lead to poeple being able to place [crafting benches/teleporters/whatever] flying in the air, which is weird. Calling the Update on all tiles in the area and all tiles around the area might hit performances if it's a big area. I don't know if it should be fixed entirely, or if it should maybe be a thing like "Right click on the device to choose if it should call Update".
 
Well now, that is unexpected.

I would much rather the pasted tiles follow normal rules such as gravity, and while it could lead to some neat results, it would probably result in more confusion than anything else if left in / given as an option. Maybe in the future, but for now it should definitely be fixed.

Real-life work is still ongoing, so I won't have time to take a look at it until this evening at the earliest.
 
I've pushed a small fix to the TilePaster to update the placed tiles, so coins now fall as expected. I haven't noticed any performance issues with it, but as always be careful of how big of an area you copy and paste. Still untested in MP.

I've also noticed a small bug with activating a device via a vanilla wire: it only works if there's a tile or something (but not a wall?) behind the device, otherwise the GlobalTile.HitWire method doesn't get called for those tile coordinates. Kind of annoying, and I'm not sure how to get around that one. Also, the HitWire method gets called twice every time - no idea why.
 
Back
Top Bottom