Crushers: a small platformer arcade game I started developing quite a few years ago. Last year, I did a flurry of updating and fixing, bringing it to a presentable state. Though I won't have much time for doing silly stuff like that this year, I do want to keep expanding Crushers, which has earned a place in my heart as my best work in the genre.
Today, I did a bunch of tweaking to allow block spawn rates to adjust for arbitrary room dimensions. Also, I did a lot of refactoring to ensure the GUI works properly no matter where the player is in the arena. It took quite a bit of doing, especially the parts where I did my own rendering, but everything works again and I successfully tripled the size of the room without sacrificing scale. Expansion time, guys!
Various technical articles, IT-related tutorials, software information, and development journals
Saturday, August 31, 2013
Friday, August 30, 2013
Forcing Disabled Web Controls with Chrome
So you've been poking around some website and you've noticed some web control that supposedly can change a property of your browsing experience, but is disabled. There's a relatively simple way to force the state of pretty much any standard web forms control, disabled or hidden.
First, get to the page that displays the control you want to force in Google Chrome. Press the F12 key to open the developer's client-side page editor. This will display a tree of the HTML elements Chrome is aware of. Mousing over one of these elements will highlight the area of the page contained in the technical element; expand all the things until only the control is highlighted.
Scroll to the right to find something like "hidden" or "disabled". Double-click that text area to enter editing mode and delete the restricting keywords. After you press Enter, Chrome will do another set of render passes, reflecting the changes you just made. Set the state of your control how you normally would and press the appropriate submit button. It's not guaranteed that the server is programmed to respect any state on that control, but there's a decent chance they weren't expecting this.
First, get to the page that displays the control you want to force in Google Chrome. Press the F12 key to open the developer's client-side page editor. This will display a tree of the HTML elements Chrome is aware of. Mousing over one of these elements will highlight the area of the page contained in the technical element; expand all the things until only the control is highlighted.
Scroll to the right to find something like "hidden" or "disabled". Double-click that text area to enter editing mode and delete the restricting keywords. After you press Enter, Chrome will do another set of render passes, reflecting the changes you just made. Set the state of your control how you normally would and press the appropriate submit button. It's not guaranteed that the server is programmed to respect any state on that control, but there's a decent chance they weren't expecting this.
Wednesday, August 28, 2013
Blackbaud Passwords
Rivermont just switched its online academic portal to Blackbaud, also known as NetClassroom. Being me, I forgot my password the second day and therefore requested that it be reset. I was sent to the Dean of Students, who administrates the portal. She logged into her administrative interface, found my account, and... read my password to me out loud. Blackbaud stores user passwords in plain text. Administrators can read all students' passwords. That's not really a concern for me, since I rarely reuse passwords, but it allows said admins to possibly compromise that student's account in other services. Also, if Blackbaud's authentication database gets hacked, that hacker will have easy (read: instant) access to the student's account. IT directors considering a new academic portal: Don't use Blackbaud; not only is its interface difficult, but it has no consideration for password safety. (Also, curious fact: It makes you set three security questions but doesn't let you use them to reset your password and, as far as I can tell, they don't do anything at all anywhere.)
Tuesday, August 27, 2013
HigherPower - Failure Reason Understood
I feel pretty silly now for spending hours on the silverfish block and the Configurable Switch. I was trying to use these huge (well, medium-sized) numbers as metadata, but only four bits are stored in the chunk. That definitely explains the strange failures of a few sides of the CS and the limitations of the silverfish block. So, I guess I won't be using metadata to store complicated information. I don't know what I'm going to do about the silverfish block (besides disable it), but I did change the CS to only be configurable on the horizontal sides; the top and bottom are inert. Though inconvenient, it has the advantage of looking cool in the inventory.
♫ I'm gonna save meta
Only got four bits of storage
I, I, I'm packing, trying to compact it
Why doesn't Forge fix this? ♪
♫ I'm gonna save meta
Only got four bits of storage
I, I, I'm packing, trying to compact it
Why doesn't Forge fix this? ♪
Sunday, August 25, 2013
HigherPower - Packet Switch
I ran into more Silverfish issues (Silverfissues if you will), so the Silverfish implanting machine is probably not going to work out. For some reason, the cage blocks never take into account the posing metadata. But I did start adding a new data processing machine, the Configurable Switch. It will allow the player to choose which faces of a router-like block are inputs, outputs, or inert sides. I don't want to use the tile entity to store the state of the faces, so I need to pack six two-bit numbers into the 16-bit metadata. It's definitely possible, but I'm having a difficult time making it work.
Saturday, August 24, 2013
HigherPower - Silverfish Failures
I'm considering a new machine that will allow players to shove Silverfish into any block and then place that block in the world. I have run into a strange problem with the silverfish-containing block: It looks as I want it to in the inventory (using the first 12 bits for block ID and the rest for metadata), but when it is placed it is the missing-texture block. I did some experiments that showed that the issue was somewhere in the ItemBlock instance. I saw that the metadata of the placed block is not the same as the block is in the inventory -- in fact, after being placed, its metadata becomes zero. I think that is because the normal ItemBlock class does not respect metadata. I tried to set the appropriate entry in Item.itemsList to an instance of ItemBlockWithMetadata, but that seemed to have no effect. So, I guess I'll do some more meddling and if I can't fix the issue, I'll make the player inject the Silverfish in-world by placing the machine above each block.
I also added a possible sword aspect and a bow aspect. Piercing (for swords) does extra damage to enemy armor, increasing exponentially per level. Channeling (for bows) gathers Sharpness and Fire Aspect effects from swords in the shooter's inventory and applies them to the target, multiplying the effects by the level of aspect.
I also added a possible sword aspect and a bow aspect. Piercing (for swords) does extra damage to enemy armor, increasing exponentially per level. Channeling (for bows) gathers Sharpness and Fire Aspect effects from swords in the shooter's inventory and applies them to the target, multiplying the effects by the level of aspect.
Friday, August 23, 2013
Tech Tree Expansion
Game designers who are working on constantly-updating games (like Minecraft) have a tendency to expand something in the middle of the tech tree when they don't have any other creative ideas. This tendency is what creates tedium and unnecessary complication. Occasionally, it is good to provide a little fork in the tree that provides better efficiency after an investment, but rejoins the existing tree quickly. For example, I just whipped up an "Inert Pearl" for HigherPower which is now required to make the Sign Pearl and Painting Pearl in the Ender Modifier. The normal crafting recipe still uses standard Ender Pearls, so the change will only affect teched-up users that have an Ender Modifier. The advantage to using Inert Pearls is that two IPs can be made for the price of one EP, given the player has access to the End. However, HigherPower has not been publicly released, so nobody will notice that I made the Ender Modifier slightly more annoying (though that obviously was not my intent). The point is, don't just add detail to the tech tree for the sake of pushing an update. Offshoots that accomplish cool little tasks are great, but inserting processes in the tree just annoys the players.
Sunday, August 18, 2013
HigherPower - More Superclassing
Once I started moving all directional functionality into a common superclass, I couldn't stop. Today, I ripped out a few more instances of onPlacedBy and determineOrientation from new subclasses of _HPBlockContainer. I might have caused some issues with the furnace sensor, but I need to do more testing to make sure everything's OK. I also added the possibility of a nonorientable block to the constructor of _HPBlockContainer for the Lawn Mower and Absorber. Unfortunately, my recent modifications to the Lawn Mower's Container results in the client being able to open a blank GUI for it when it's moving. I'm thinking about using block metadata to determine whether the GUI can be opened by right-clicking.
Saturday, August 17, 2013
HigherPower - Sync Optimization
As I looked back on my networking code today, I thought that there must be a better way of synchronizing progress and energy data for machines; after all, vanilla doesn't do any such thing. I looked at some vanilla machines' containers and saw the mysterious methods addCraftingToCrafters, updateProgressBar, and detectAndSendChanges. Previously, I had assumed I could do better than that strange stuff, but I now see that my mess of dirty block lists, alternate networking channels, and constant updating. Today, I went and ripped out that mess, replacing it with vanilla's style of keeping the sides in sync. Also, I added a table of recipes and multiplications for the Absorber that includes all ores I know about.
Friday, August 16, 2013
HigherPower - Absorber
After school today, I added another machine to HigherPower! It's a tier 1 (Fleexium) machine, so I used some existing code for combustion-driven machines. This one, however, is a lot more complicated than any other machine. It has five inputs: drill tip, left drill reinforcement, right drill reinforcement, solvent, and fuel. The ore block to be processed is placed in the world under the Absorber. The solvent increases the chance of getting extra materials out of the ore block. Though it is considerably more expensive to produce and operate, the Absorber has the advantages of producing more materials, automatically smelting, leaving behind a stone block, and being able to run on Nether Impurities. While coding this machine, I discovered that my method of keeping the server and client synchronized is extremely overcomplicated. I will be ripping out most of my networking code and replacing it with the built-in onInventoryChanged calls.
Thursday, August 15, 2013
iTechnology
My school has issued iPads to all high school students, which includes me. They will be used as eBook readers in class, but students are free to use them as personal iPads as long as the devices are not damaged. I went to Best Buy and purchased a case, cover, and some screen cleaner for it. It seems that the screen is very easily smudged, so I'll need to wash my hands before using the device and occasionally apply the cleaner. I'm really not a fan of how Apple makes sure all my data goes through them; I can't do anything without an Apple ID with a verified e-mail address. I do like how they require passwords to do important things, but sometimes I'll get two password boxes in a row for the same account. I'll just have to get used to the Apple way before making any more judgement.
Wednesday, August 14, 2013
HigherPower - Superclassing
I decided to finally clean up a lot of HigherPower's classes by moving copy-pasted functionality to a common superclass. That new class was _HPMachineTE, containing methods for ejecting items, performing NBT operations, giving information about the IInventory to Forge, and hooking HigherPower machines to slot-related events. I did something similar with the Block classes that represented machines, creating _HPBlockContainer. That class provides methods for orienting the block (with four or six directions), opening GUIs, creating and managing TileEntity instances, and spawning contents into the world when broken. It really feels good to eliminate hundreds of lines of unnecessary code from a project.
Tuesday, August 13, 2013
HigherPower - Bi-Modal Ejector
Well, I finally added a tier 2 machine that's actually a machine to HigherPower. This machine is the "bi-modal ejector", a combination of the dispenser and dropper that sports a few bonuses. Instead of being triggered by redstone, it can only be fired with an appropriate packet coming in on the input face. Changing between the two modes (dispenser and dropper) is accomplished by sending a different kind of packet. A firing packet can specify which slot from which to draw the ammunition. In addition to creating that machine, I wrote up the Technical Manual articles for all existing Eethur machines and fixed some bugs. Soon, I want to absorb a lot of copy-pasted functionality of my tile entities into some HPTileEntity superclass.
Monday, August 12, 2013
HigherPower - Data Repeater & YouTube Dev Log
I didn't really do much with HigherPower today, but I did add a new data block, the Data Repeater. Since I'm just using the call stack to transmit packets along a wire, it's entirely possible for a StackOverflowError to halt transmission. To make exceedingly long lengths of data cable possible, I made the Data Repeater queue up all received packets for transmission on the next tick. Because the data is not transmitted on the same stack that it is received, the call stack is reset.
Also, I started a small YouTube series in which I will document HigherPower from a developer's perspective. I just uploaded the first episode, "Slightly Broken", today. This series will also help me find and fix bugs!
Also, I started a small YouTube series in which I will document HigherPower from a developer's perspective. I just uploaded the first episode, "Slightly Broken", today. This series will also help me find and fix bugs!
Sunday, August 11, 2013
HigherPower - Damage Counter
In addition to doing some mundane tweaks to Noir generation, I added a new item to HigherPower. This item is the Damage Counter, a card that keeps track of how much damage the holding player receives and deals. It works by catching Forge's LivingHurtEvent, checking to see if the holder (or holder's attacker) is a player, looking for a Damage Counter in the player's inventory, and adding the base damage. The DC does not take into account armor, potions, or other mods' interference in the damage process. The DC is crafted with some redstone, an iron ingot, some Fleexium, and a tiny bit of Eethur. Originally, I was using reflection to access the protected entityDamageSource field, but then I discovered the public getter getSourceOfDamage.
Friday, August 9, 2013
HigherPower - Back in Business!
I suddenly got the urge to do some more work on HigherPower, my Minecraft mod. Since Minecraft updated, Forge also has a new version that of course breaks everything. The most common issues were that instances of EntityLiving are replaced with the new EntityLivingBase and that the name of "isStackValid" changed to "isItemValid." The technical name of glowstone dust finally became "glowstone" and the texture binding function got reverted to one of the confusing SRG names. They did make a very nice change though: dimension IDs are now more easily accessible between mods, so my machines will work in the Twilight Forest and Mystcraft worlds. To be honest, I don't recall what I was working on before I took this hiatus, but I think I should work on adding more block sensors or that sonic piston idea.
Thursday, August 8, 2013
Refactoring by Compiler Errors
The class that holds information about running games for a game server I'm developing had separate boolean fields to keep track of things like "is the game open to new players", "has everyone selected their character", and "has gameplay actually started". I realized that I could replace these variables with a single enum value because the statuses always follow the same order. There are quite a few places in the application that check those fields, so it would have taken me a long time to find and update them all. However, I just went ahead and deleted those fields, causing compiler errors when I attempted to build. With the list of compile-time issues, I was able to quickly navigate through the project and make minor changes to use the enum. So, instead of creating a list of things that you'll need to fix before an update, just go ahead and change the fields. You'll see exactly what needs changing.
Wednesday, August 7, 2013
Check Static Fields
Static fields are immensely useful things. However, they can also cause a lot of headaches if used without thinking. Due to the JIT compiler's way of not making things until necessary, using static fields to keep important constant references is dangerous, especially when the declaration involves a constructor. I was using something like this to define characters for NetBLAM:
Class Characters
...
Public Shared SidKetchum As Character = New Character(5)
...
End Class
The constructor of Character added it and its ID (the 5) to a static dictionary. However, when I accessed that dictionary, it contained zero entries because none of the fields in Characters had ever been directly accessed and thus threw a NullReferenceException. To solve this situation, I removed the automatic registering from the Character class and had CharacterRegistry (a manager for the in-use characters) add them to the dictionary with reflection in its constructor.
Class Characters
...
Public Shared SidKetchum As Character = New Character(5)
...
End Class
The constructor of Character added it and its ID (the 5) to a static dictionary. However, when I accessed that dictionary, it contained zero entries because none of the fields in Characters had ever been directly accessed and thus threw a NullReferenceException. To solve this situation, I removed the automatic registering from the Character class and had CharacterRegistry (a manager for the in-use characters) add them to the dictionary with reflection in its constructor.
Sunday, August 4, 2013
Minecraft - The SFMI Official Family-Friendly Language Pack
As of beta 1.9, Minecraft contains an item called the "enchantment table." I recently constructed one of these in my Minecraft LP, "Search for Mushroom Island", to improve my tools. However, I am a little bit conflicted over whether I should be using it due to the slight reference to the occult. To remedy this situation and make the series completely family-friendly, I created a language pack that changes a few possibly objectionable texts. I figured some parents might want to use it for their younger children, so I put up a download with some instructions to install it with Minecraft 1.6's Resource Pack system.
Download the official Search for Mushroom Island Family-Friendly Resix
Installation Instructions for Non-Technical Parents
Download the official Search for Mushroom Island Family-Friendly Resix
Installation Instructions for Non-Technical Parents
Saturday, August 3, 2013
Batch YouTube Video Renamer
There really needs to be an application that, given a set of YouTube credentials and a set of videos to affect, renames the videos according to some set of rules. I'm surprised there's nothing like this on Google Code (that I could find). I think it would help my YouTube channel to shift away from my current episode numbering system to a more intuitive one -- why did I think it was a good idea to start counting at 0? I guess it would be difficult to remove the brackets, truncate the leading zeros, and change the number, but it would be immensely helpful to have such a program.
Friday, August 2, 2013
Get the Dust Out!
Withing Folding@home running at full power, my computer is fully utilized all the time. This morning, I checked Speccy and was shocked to see that both my CPU and GPU were running at unsafe temperatures. Later, I blew out the computer with compressed air. After setting it back up, I ran Speccy with FAH again. The temperature went down about 5 degrees Celsius, back into the upper areas of the safe temperature zone. So, I recommend you frequently take off your computer's cover and get all the dust out of the fans. It's also a good idea to make sure that the fans are spinning easily.
Thursday, August 1, 2013
NetBLAM - All the Pre-Game
Amid recording, editing, and uploading YouTube videos, I actually finished all the pre-game stuff for NetBLAM. Only 11 different types of packets have been defined so far (though one of them is kind of has two purposes and a different two could easily be merged). Today, I added functionality to give players a choice of which of two characters to be. The server can also randomly assign roles based on the number of players. I still need to work out some glitches that cause InvalidOperationException when a client writes a bad packet. Also, the pre-game status label tends to only update for game admins.
The PreGame dialog and player list |
Subscribe to:
Posts (Atom)