Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/radian-software/TerrariaClone
🔥 An incomprehensible hellscape of spaghetti code.
https://github.com/radian-software/TerrariaClone
Last synced: 2 months ago
JSON representation
🔥 An incomprehensible hellscape of spaghetti code.
- Host: GitHub
- URL: https://github.com/radian-software/TerrariaClone
- Owner: radian-software
- License: mit
- Created: 2016-10-15T16:58:14.000Z (over 8 years ago)
- Default Branch: main
- Last Pushed: 2023-06-22T14:37:05.000Z (over 1 year ago)
- Last Synced: 2024-11-04T03:03:18.363Z (3 months ago)
- Language: Java
- Homepage:
- Size: 527 KB
- Stars: 1,796
- Watchers: 31
- Forks: 134
- Open Issues: 18
-
Metadata Files:
- Readme: README.md
- License: LICENSE.md
Awesome Lists containing this project
README
# TerrariaClone
*Discussed on: [Hacker
News](https://news.ycombinator.com/item?id=15460851),
[/r/programming](https://www.reddit.com/r/programming/comments/760kqv/terrariaclone_an_incomprehensible_hellscape_of/),
[/r/programminghorror](https://www.reddit.com/r/programminghorror/comments/7hhe9h/a_clone_of_terraria_defined_by_the_author_as_an/),
[/r/shittyprogramming](https://www.reddit.com/r/shittyprogramming/comments/761gbr/terrariaclone_an_incomprehensible_hellscape_of/).*Back when I was first learning to program in Java, I decided to try to
make a clone of the excellent PC game [Terraria]. Of course, I was
convinced that my version would have many more features than the
official one.But before I realized how silly that idea was, I produced 11,000 lines
of, to date, the most atrocious code I have ever seen in my life. I
make it available here mostly as a cautionary tale of what can happen
if you don't pay attention to the quality of your code. (Lesson
learned, in my case!) Here are some of the highlights:* Blocks and items, among many other things, are represented by magic
numbers instead of enums. There are 417 lines of block comments at
the top of `TerrariaClone.java` that serve as manual translation
tables.
* There are no access modifiers. Everything is package-private.
* So as to avoid needing to declare local variables and loop indices,
all of the variables for everything are declared globally at the
class level. Here is one of the several hundred lines of
declarations in `TerrariaClone.java`:```
int x, y, i, j, k, t, wx, wy, lx, ly, tx, ty, twx, twy, tlx, tly, ux, uy, ux2, uy2, uwx, uwy, uwx2, ulx, uly, ulx2, uly2, ucx, ucy, uclx, ucly, pwx, pwy, icx, icy, n, m, dx, dy, dx2, dy2, mx, my, lsx, lsy, lsn, ax, ay, axl, ayl, nl, vc, xpos, ypos, xpos2, ypos2, x2, y2, rnum, mining, immune, width, height, xmin, xmax, ymin, ymax, intpercent, ground;
```* Although there are a few other classes, the bulk of the code is in
the God Class `TerrariaClone`, which spans over 6,500 lines of code.* The `TerrariaClone.init()` method, which is over 1,300 lines long,
actually grew so large that it hit the limit hardcoded into the Java
compiler for the maximum memory that can be taken up by a single
function! The solution? Copy half of the `init()` code into a new
method, called `codeTooLarge()`, and call that from `init()`.* Frankly horrifying inline data tables:
```
static boolean[] solid = {false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, true, true, true, false, false, false, true, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
static boolean[] ltrans = {false, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, false, false, false, false, false, false, false, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false};
static boolean[] wirec = {false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true};
```* Over 1,000 lines of filling globally declared HashMaps and
ArrayLists with magic numbers and strings one by one.* The control flow is so labyrinthine that some of the code is
actually indented by 23 tabs. Forget the 80-column rule -- these
lines don't even *start* until column 92! Even if we discard the inline
data tables, then the longest line in the codebase is still a
whopping *387 characters* long (you'll have to scroll to the right
to read it):```
blocks[l][y2][x2] >= 137 && blocks[l][y2][x2] <= 168 && y > y2 && blocks[l][y2][x2] != 140 && blocks[l][y2][x2] != 144 && blocks[l][y2][x2] != 148 && blocks[l][y2][x2] != 152 && blocks[l][y2][x2] != 156 && blocks[l][y2][x2] != 160 && blocks[l][y2][x2] != 164 && blocks[l][y2][x2] != 168) &&
```* Did I mention that *everything is global*, including *loop indexing
variables*?* There are random print statements scattered throughout the codebase,
with helpful messages like `[DEBUG2R]` and `[DEBUG2A]`.* Why use a pre-existing GUI framework for your text boxes when you
can easily roll your own?```
char c = 0;
if (key.getKeyCode() == key.VK_Q) c = 'q';
...
if (queue[5]) {
if (c == 'q') c = 'Q';
...
}
```Now, when importing this project into version control (you thought I
was using version control when I wrote this??), I did fix a few of the
most blatantly horrible style violations -- for instance, I normalized
the whitespace, although other improvements (for example, removing the
over 500 cases of unnecessary boxing) have been reverted by popular
demand in the name of historical integrity. I also tried to get the
main game actually working, which meant fixing a few resource path
issues. Unfortunately, it's only working in the academic sense, since
it's so slow that you only get about 0.03 FPS and it crashes when you
click the mouse button. But, somewhere in there is a working game. You
know, sort of.#### Build and run
```
$ mkdir -p out
$ javac -d out src/*.java
$ java -cp out:textures TerrariaClone
```As mentioned previously, although it runs, it fails to run very well.
See [this pull request][fix-bugs].#### TerraFrame?
This project was originally called TerraFrame (back when I created it
in 2011). I believe the reasoning was that it was a *Terra*ria clone,
and it was in a J*Frame*. Yes, it's stupid, much like every other part
of this project. Meanwhile, there is a completely unrelated company
called TerraFrame. This led to an unfortunate misunderstanding wherein
somebody thought that this garbage heap of a codebase was associated
in some way with TerraFrame, the company. After receiving a very
polite email pointing out the issue, I've changed the name to
something that makes more sense (TerrariaClone).#### Python?
You may notice a subdirectory named `python`. What is this, you ask?
Why, nothing other than the *original* version of TerrariaClone, from
before I rewrote it into Java! And yes, it's even more primitive,
although I at least had a bit more understanding of idiomatic
programming in Python than in Java.[fix-bugs]: https://github.com/radian-software/TerrariaClone/pull/12
[terraria]: https://terraria.org/