I've seen the three-word story game (you know, the game where each person extends the collaborative story by three words?) played on multiple online forums. Every time, someone misunderstands the English language (or intentionally messes up the structure) and, since the forum's admins aren't responsible for the content of those posts, the people actually wanting to advance the story have a problem.
So, I'd like to use my knowledge of ASP .NET to create a website just for this game! I'd like to name it "Logofrag" because everyone contributes a fragment of the the logos. People could start different stories with different subjects and rules -- and then moderate their own threads! Since different people might have different ideas of what counts as a word, how many people must post between two posts of the same person, and other things, there would have to be many options for everyone to get what they want. It seems pretty simple and I'm willing to dedicate a tiny slice of my free time to creating this.
Various technical articles, IT-related tutorials, software information, and development journals
Saturday, September 14, 2013
Thursday, September 12, 2013
Do Not Use - Blackbaud (NetClassroom)
New series time! In "Do Not Use", I will talk about applications that should not be considered when setting up a new system. This time, it's Blackbaud, also known as NetClassroom. Blackbaud is a school management system, so its purpose is to keep track of student grades, assignments, attendance, and other school stuff that only teachers need to worry about. It does keep track of those things fine, but its interface is just not good. Turning in an assignment is painful; it requires going through a menu with "Advanced" in the title and other steps. The authentication system seems to have some sort of problem: the program has forgotten my password at least two times now. Yes, I am certain I remember it. Yes, I am certain I am typing it correctly. Blackbaud forgets user passwords. In addition to that, it throws some sort of COM error when I try to log in with Chrome on my home computer. It's impossible to upload files from a Mac because it requires the client to use a Windows common dialog. Submission of files is done through a strange pop-up window that forces you to navigate through a variety of classification levels before letting you even see the list of things eligible to be turned in. The teachers also report annoyances with it, which I haven't seen in person but I believe. Please spare your students and teachers a major hassle and use something like Canvas, Blackboard, Moodle, or even Focus for your SIS.
Wednesday, September 11, 2013
Reading from Streams
Instead of trying to passionately comment on the 9/11 attack, I'll leave that to everyone else and do my normal thing.
I've recently been curious about streams in .NET and why the documentation on it is so terrifying. Since Jim Mischel did an article on it just today, I'll hand it over to him. (I'm busy with schoolwork and very very tired.) Mr. Mischel is amazing, go read his article and follow his blog.
I've recently been curious about streams in .NET and why the documentation on it is so terrifying. Since Jim Mischel did an article on it just today, I'll hand it over to him. (I'm busy with schoolwork and very very tired.) Mr. Mischel is amazing, go read his article and follow his blog.
Monday, September 9, 2013
Quark - Browser with a Formally Verified Kernel
Everyone knows that the Internet can be a terrible place. Hackers, phishers, and general baddies lurk around every proverbial corner. Some incredibly smart people at the University of California have created a web browser based on Google Chrome whose core is formally proven (using mind-blowingly advanced theorems and logicy stuff) to be secure. Different tabs cannot interfere with each other, the address bar cannot be hijacked, and no files will be placed on your computer without your consent. This browser is called Quark. It's still in experimental stages, but it has been tested on advanced web sites such as Facebook. Currently, you can download its source code or read about all the logic. Guess which blogger will be using Quark soon.
Friday, September 6, 2013
Forge - Correct Use of ResourceLocation
After Minecraft updated to version 1.6, Forge did some changes to the GUI texture loading. Thankfully, it's considerably easier to bundle all manner of resources, but unfortunately more complicated to set up the addresses. They reverted bindTexture to func_110577_a and changed its argument to a ResourceLocation instance. Such an instance can be easily created with one or two strings. Important note: You should use only the one-string constructor; the two-string one will only work when launching from Eclipse. That string is of the format "modname:textures/gui/filename.png". So, for my Absorber, I would create the ResourceLocation like so: "new ResourceLocation("higherpower:textures/gui/absorber.png)". Notice that the mod ID is now required to be in all lowercase. While developing, place your mod's assets folder under the src folder.
Wednesday, September 4, 2013
HigherPower - Improving /genhere
After noticing the setRandomHeight method of the StructureStart class, I decided to look into it. It appears to be the way normal Minecraft provides variation in the height of Nether fortresses, strongholds, and abandoned mineshafts. I used the location of the command sender to make the structure generate at a similar Y level to the player. It has the unfortunate side effect of making villages fail to generate, which I will fix somehow sometime.
Tuesday, September 3, 2013
Forge - Sync Progress Bars
At the time you read this, I'll be thoroughly enjoying myself in a camp in northern Wisconsin. Enjoy this scheduled post!
Synchronizing GUI progress bars between server and client may seem complicated at first, but it's actually very simple. If you've set up a GUI renderer and container already, you're ready for this tutorial.
First, make sure the client-side tile entity isn't doing anything with progress bars besides having a variable for it. Open up the container class and create some variables for the previous state of all the progress bars (like burn time and cooking progress). Let's use ContainerFurnace to explain stuff.
public void addCraftingToCrafters(ICrafting par1ICrafting)
{
super.addCraftingToCrafters(par1ICrafting);
par1ICrafting.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime);
par1ICrafting.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime);
par1ICrafting.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime);
}
The super call is necessary to sync inventory; the sendProgressBarUpdate calls are more interesting. This is where the server tells the client what it knows about the GUI. The numbers (0, 1, 2) are IDs of the progress bars and the final argument is the value of the progress bar as an integer (taken from the represented tile entity).
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for (int i = 0; i < this.crafters.size(); ++i)
{
ICrafting icrafting = (ICrafting)this.crafters.get(i);
if (this.lastCookTime != this.furnace.furnaceCookTime)
{
icrafting.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime);
}
if (this.lastBurnTime != this.furnace.furnaceBurnTime)
{
icrafting.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime);
}
if (this.lastItemBurnTime != this.furnace.currentItemBurnTime)
{
icrafting.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime);
}
}
this.lastCookTime = this.furnace.furnaceCookTime;
this.lastBurnTime = this.furnace.furnaceBurnTime;
this.lastItemBurnTime = this.furnace.currentItemBurnTime;
}
The loop iterates through all the crafters (the players viewing this container) and sends an update on any progress bars that have changed. The calls are exactly the same as in addCraftingToCrafters. After informing all the crafters, it updates its cache of the progress bar states from the tile entity.
@SideOnly(Side.CLIENT)
public void updateProgressBar(int par1, int par2)
{
if (par1 == 0)
{
this.furnace.furnaceCookTime = par2;
}
if (par1 == 1)
{
this.furnace.furnaceBurnTime = par2;
}
if (par1 == 2)
{
this.furnace.currentItemBurnTime = par2;
}
}
This is where the client fixes its progress bars. It receives the ID of the bar to update and the value. With that, it decides which tile entity variable to set.
So there you go! The GUI class does not need to be changed, it will reflect the tile entity's opinion on the progress bars, which is now in sync with the server.
Synchronizing GUI progress bars between server and client may seem complicated at first, but it's actually very simple. If you've set up a GUI renderer and container already, you're ready for this tutorial.
First, make sure the client-side tile entity isn't doing anything with progress bars besides having a variable for it. Open up the container class and create some variables for the previous state of all the progress bars (like burn time and cooking progress). Let's use ContainerFurnace to explain stuff.
public void addCraftingToCrafters(ICrafting par1ICrafting)
{
super.addCraftingToCrafters(par1ICrafting);
par1ICrafting.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime);
par1ICrafting.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime);
par1ICrafting.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime);
}
The super call is necessary to sync inventory; the sendProgressBarUpdate calls are more interesting. This is where the server tells the client what it knows about the GUI. The numbers (0, 1, 2) are IDs of the progress bars and the final argument is the value of the progress bar as an integer (taken from the represented tile entity).
public void detectAndSendChanges()
{
super.detectAndSendChanges();
for (int i = 0; i < this.crafters.size(); ++i)
{
ICrafting icrafting = (ICrafting)this.crafters.get(i);
if (this.lastCookTime != this.furnace.furnaceCookTime)
{
icrafting.sendProgressBarUpdate(this, 0, this.furnace.furnaceCookTime);
}
if (this.lastBurnTime != this.furnace.furnaceBurnTime)
{
icrafting.sendProgressBarUpdate(this, 1, this.furnace.furnaceBurnTime);
}
if (this.lastItemBurnTime != this.furnace.currentItemBurnTime)
{
icrafting.sendProgressBarUpdate(this, 2, this.furnace.currentItemBurnTime);
}
}
this.lastCookTime = this.furnace.furnaceCookTime;
this.lastBurnTime = this.furnace.furnaceBurnTime;
this.lastItemBurnTime = this.furnace.currentItemBurnTime;
}
The loop iterates through all the crafters (the players viewing this container) and sends an update on any progress bars that have changed. The calls are exactly the same as in addCraftingToCrafters. After informing all the crafters, it updates its cache of the progress bar states from the tile entity.
@SideOnly(Side.CLIENT)
public void updateProgressBar(int par1, int par2)
{
if (par1 == 0)
{
this.furnace.furnaceCookTime = par2;
}
if (par1 == 1)
{
this.furnace.furnaceBurnTime = par2;
}
if (par1 == 2)
{
this.furnace.currentItemBurnTime = par2;
}
}
This is where the client fixes its progress bars. It receives the ID of the bar to update and the value. With that, it decides which tile entity variable to set.
So there you go! The GUI class does not need to be changed, it will reflect the tile entity's opinion on the progress bars, which is now in sync with the server.
Subscribe to:
Posts (Atom)
