1.12.2-6.0.1 16898e7451f1 cached
150 files
587.0 KB
168.9k tokens
669 symbols
1 requests
Download .txt
Showing preview only (633K chars total). Download the full file or copy to clipboard to get everything.
Repository: WildBamaBoy/minecraft-comes-alive
Branch: 1.12.2-6.0.1
Commit: 16898e7451f1
Files: 150
Total size: 587.0 KB

Directory structure:
gitextract_9ljofwy4/

├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug-report.md
│       └── feature-change-request.md
├── .gitignore
├── CHANGELOG
├── LICENSE
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── src/
    └── main/
        ├── java/
        │   └── mca/
        │       ├── api/
        │       │   ├── API.java
        │       │   └── types/
        │       │       ├── APIButton.java
        │       │       ├── Gift.java
        │       │       └── SkinsGroup.java
        │       ├── blocks/
        │       │   └── BlockVillagerSpawner.java
        │       ├── client/
        │       │   ├── MCAGuiFactory.java
        │       │   ├── gui/
        │       │   │   ├── GuiConfigPage.java
        │       │   │   ├── GuiInteract.java
        │       │   │   ├── GuiNameBaby.java
        │       │   │   ├── GuiStaffOfLife.java
        │       │   │   ├── GuiVillagerEditor.java
        │       │   │   ├── GuiWhistle.java
        │       │   │   └── component/
        │       │   │       └── GuiButtonEx.java
        │       │   ├── model/
        │       │   │   ├── ModelGrimReaper.java
        │       │   │   └── ModelVillagerMCA.java
        │       │   ├── network/
        │       │   │   └── ClientMessageQueue.java
        │       │   └── render/
        │       │       ├── RenderGrimReaper.java
        │       │       ├── RenderReaperFactory.java
        │       │       ├── RenderVillagerFactory.java
        │       │       └── RenderVillagerMCA.java
        │       ├── command/
        │       │   ├── CommandAdminMCA.java
        │       │   └── CommandMCA.java
        │       ├── core/
        │       │   ├── Config.java
        │       │   ├── Constants.java
        │       │   ├── Localizer.java
        │       │   ├── MCA.java
        │       │   ├── MCAServer.java
        │       │   ├── forge/
        │       │   │   ├── ClientProxy.java
        │       │   │   ├── EventHooks.java
        │       │   │   ├── GuiHandler.java
        │       │   │   ├── NetMCA.java
        │       │   │   └── ServerProxy.java
        │       │   └── minecraft/
        │       │       ├── BlocksMCA.java
        │       │       ├── ItemsMCA.java
        │       │       ├── ProfessionsMCA.java
        │       │       ├── RoseGoldOreGenerator.java
        │       │       ├── SoundsMCA.java
        │       │       ├── VillageHelper.java
        │       │       └── WorldEventListenerMCA.java
        │       ├── entity/
        │       │   ├── EntityGrimReaper.java
        │       │   ├── EntityVillagerMCA.java
        │       │   ├── ai/
        │       │   │   ├── AbstractEntityAIChore.java
        │       │   │   ├── EntityAIAgeBaby.java
        │       │   │   ├── EntityAIChopping.java
        │       │   │   ├── EntityAIDefendFromTarget.java
        │       │   │   ├── EntityAIFishing.java
        │       │   │   ├── EntityAIGoHangout.java
        │       │   │   ├── EntityAIGoWorkplace.java
        │       │   │   ├── EntityAIHarvesting.java
        │       │   │   ├── EntityAIHunting.java
        │       │   │   ├── EntityAIMoveState.java
        │       │   │   ├── EntityAIProcreate.java
        │       │   │   ├── EntityAIProspecting.java
        │       │   │   └── EntityAISleeping.java
        │       │   ├── data/
        │       │   │   ├── ParentData.java
        │       │   │   ├── PlayerHistory.java
        │       │   │   ├── PlayerSaveData.java
        │       │   │   └── SavedVillagers.java
        │       │   └── inventory/
        │       │       └── InventoryMCA.java
        │       ├── enums/
        │       │   ├── EnumAgeState.java
        │       │   ├── EnumChore.java
        │       │   ├── EnumConstraint.java
        │       │   ├── EnumDialogueType.java
        │       │   ├── EnumGender.java
        │       │   ├── EnumMarriageState.java
        │       │   ├── EnumMoveState.java
        │       │   └── EnumReaperAttackState.java
        │       ├── items/
        │       │   ├── ItemBaby.java
        │       │   ├── ItemEngagementRing.java
        │       │   ├── ItemGuideBook.java
        │       │   ├── ItemMatchmakersRing.java
        │       │   ├── ItemSpawnEgg.java
        │       │   ├── ItemSpecialCaseGift.java
        │       │   ├── ItemStaffOfLife.java
        │       │   ├── ItemVillagerEditor.java
        │       │   ├── ItemWeddingRing.java
        │       │   └── ItemWhistle.java
        │       ├── server/
        │       │   └── ServerMessageHandler.java
        │       └── util/
        │           ├── ItemStackCache.java
        │           ├── ResourceLocationCache.java
        │           └── Util.java
        └── resources/
            ├── assets/
            │   └── mca/
            │       ├── api/
            │       │   ├── gifts.json
            │       │   ├── gui/
            │       │   │   ├── debug.json
            │       │   │   ├── editor.json
            │       │   │   ├── interact.json
            │       │   │   ├── location.json
            │       │   │   ├── main.json
            │       │   │   └── work.json
            │       │   └── skins.json
            │       ├── blockstates/
            │       │   ├── rose_gold_block.json
            │       │   ├── rose_gold_ore.json
            │       │   └── villager_spawner.json
            │       ├── lang/
            │       │   ├── en_us.lang
            │       │   └── names.lang
            │       ├── models/
            │       │   ├── block/
            │       │   │   ├── rose_gold_block.json
            │       │   │   ├── rose_gold_ore.json
            │       │   │   └── villager_spawner.json
            │       │   └── item/
            │       │       ├── baby_boy.json
            │       │       ├── baby_girl.json
            │       │       ├── book_death.json
            │       │       ├── book_family.json
            │       │       ├── book_infection.json
            │       │       ├── book_romance.json
            │       │       ├── book_rose_gold.json
            │       │       ├── egg_female.json
            │       │       ├── egg_male.json
            │       │       ├── engagement_ring.json
            │       │       ├── engagement_ring_rg.json
            │       │       ├── gold_dust.json
            │       │       ├── matchmakers_ring.json
            │       │       ├── rose_gold_block.json
            │       │       ├── rose_gold_dust.json
            │       │       ├── rose_gold_ingot.json
            │       │       ├── staff_of_life.json
            │       │       ├── villager_editor.json
            │       │       ├── wedding_ring.json
            │       │       ├── wedding_ring_rg.json
            │       │       └── whistle.json
            │       ├── recipes/
            │       │   ├── engagement_ring.json
            │       │   ├── engagement_ring_rg.json
            │       │   ├── gold_dust.json
            │       │   ├── gold_nugget_from_dust.json
            │       │   ├── matchmakers_ring.json
            │       │   ├── rose_gold_block.json
            │       │   ├── rose_gold_dust_from_ingot.json
            │       │   ├── rose_gold_ingot_from_dust.json
            │       │   ├── wedding_ring.json
            │       │   ├── wedding_ring_rg.json
            │       │   └── whistle.json
            │       ├── sounds/
            │       │   ├── reaper-block.ogg
            │       │   ├── reaper-death.ogg
            │       │   ├── reaper-idle.ogg
            │       │   ├── reaper-scythe-out.ogg
            │       │   ├── reaper-scythe-swing.ogg
            │       │   └── reaper-summon.ogg
            │       └── sounds.json
            ├── mcmod.info
            └── pack.mcmeta

================================================
FILE CONTENTS
================================================

================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.md
================================================
---
name: Bug Report
about: Found a bug that you wish to tell us about? Start here. [MCA 6.0.0+ ONLY]
title: ''
labels: needs review
assignees: ''

---

**Describe the bug**
A clear and concise description of what the bug is.

**Steps to Reproduce**
Please include steps we can take to reproduce the bug:
1. Launch Minecraft
2. Create a World
3. etc...

**Minecraft Information (please complete all questions entirely):**
 - Minecraft Version: [e.g. 1.12.2]
 - Forge Version: [e.g. 14.23.5.2838]
 - MCA Version: [e.g. 6.0.0] **Any version below 6.0.0 is NOT supported. Do not submit an issue for these versions.**
 - Launcher: [e.g. Standard, Twitch, MultiMC]

**Modpack Information**
Complete this section if you are using a modpack.
 - Modpack Name: [e.g. FTB Infinity]
 - Modpack Version: [e.g 3.1.0]

**Mods List**
Complete this section if you are NOT using a modpack but have other mods installed alongside MCA.
 - Please list the other mods you have installed

**Additional context**
Add any other context about the problem here that you feel is useful. Screenshots, world files, logs, etc.


================================================
FILE: .github/ISSUE_TEMPLATE/feature-change-request.md
================================================
---
name: Feature Change Request
about: Suggest your idea for MCA relating to a current problem in the mod.
title: "[REQUEST] "
labels: ''
assignees: ''

---

**Please describe the problem you are experiencing and requesting a change for**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

**Describe the solution you'd like to see**
A clear and concise description of what you ideally want to happen.

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you have considered, if applicable. For example, if you're able to do what you want with a simple in-game workaround, include how to do that here.

**Additional context**
Add any other context or screenshots about the feature request here.


================================================
FILE: .gitignore
================================================
# eclipse
bin
*.launch
.settings
.metadata
.classpath
.project

# idea
out
*.ipr
*.iws
*.iml
.idea

# gradle
build
.gradle

# other
eclipse
run
classes


================================================
FILE: CHANGELOG
================================================
6.0.1
Feature: Whistle to call your family has been added back into the game.
Feature: Special skins for naming your children certain names (secret!)
Feature: Improved the villager editor with the ability to specify desired careers and textures.
Feature: Villager health is now configurable.

Fixed: Guards not properly defending villagers when injured.
Fixed: Potential crash client-side when exiting the game.
Fixed: Career names and IDs were not matching in the Trade GUI.
Fixed: Inability to interact with villagers when using some other mods.

6.0.0
Feature: In-game notifications for updates.
Feature: Modified female bodies have been added back.
Feature: Player children now take a profession on growing to an adult.
Feature: Rose Gold generation can now be disabled.

Changed: "Romantic" interaction constraint changed to "Adults".

Fixed: You are now notified of your child's death.
Fixed: Interaction fatigue was not applying properly.
Fixed: Crashes resulting from using the Villager Spawner block.
Fixed: Inability to interact with some villagers.
Fixed: Guards now behave more like normal villagers.
Fixed: Villagers from eggs will no longer spawn with the Nitwit or Child profession.
Fixed: Negative gifts will no longer be taken from the player.
Fixed: Engagement ring now works properly.
Fixed: Automatic crash reporting wasn't working properly.
Fixed: Inability to procreate with Guards.
Fixed: Crash when a villager dies of fall damage.
Fixed: Villagers wandering away from their homes.
Fixed: The villager editor will no longer produce Pillagers.
Fixed: The force child growth command now works properly.
Fixed: Romantic actions appearing on non-adults.
Fixed: Crashes with other mods referencing onPlaySoundAtEntityEvent.
Fixed: Overspawn of guards in villagers. Now limited to 10 guards at a time.
Fixed: Missing message for riding horses on spouses.

6.0.0-beta
This version of MCA has been fully rewritten from the ground up to be more user, server, and mod friendly with a streamlined and robust codebase. Compatibility with previous saves should not be expected.

Major: RadixCore is no longer a required dependency.

Feature: Villagers performing a chore or movement action show their status below their name.
Feature: Player marriage has been shifted to the /mca command.
Feature: Added /mca-admin commands for operators and server administrators.
Feature: GUI and API elements have been externalized and may be customized as you please with a constraints system.
Feature: More configuration options for server administrators.
Feature: Children now grow in stages - baby, toddler, child, teen, adult.
Feature: Added Guard careers: Hero, Archer, Warrior.
Feature: All skins are now 64x64 and additional skins of this size are now supported.

Changed: Chores are now smarter, require no configuration before running, and should play more nicely with modded items.
Changed: Mining is now called Prospecting.
Changed: Villager personalities and moods no longer affect interactions.
Changed: The crystal ball and setup menu is no longer required.
Changed: Reaper battle has been tweaked for fairness.
Changed: Reviving villagers no longer requires a memorial item.
Changed: Engagement ring now allows marriage with only 50% of the required hearts.

Fixed: Random crashing on servers due to java.lang.ClassCastException when approaching villages.
Fixed: Villagers all have their proper vanilla trades based on their profession.
Fixed: Married to "?" will no longer occur on LAN.
Fixed: Health display issues have been fixed.
Fixed: Lost/forgotten player histories on servers.
Fixed: Villagers should trend towards their home points and not wander too far away.
Fixed: Crashes related to null item stacks.

================================================
FILE: LICENSE
================================================
                    GNU GENERAL PUBLIC LICENSE
                       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

                            Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

                       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.

  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.

  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

                     END OF TERMS AND CONDITIONS

            How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <https://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.


================================================
FILE: README.md
================================================
Minecraft Comes Alive
=====================
Minecraft Comes Alive (MCA) is a Minecraft mod that replaces Minecraft's villagers with normal player-like NPCs. It works in single player, LAN, and SMP.

Villagers can be interacted with - you can talk to them, ask them to follow you, set their home, give them gifts, etc. Interacting with people builds relationships. Get your relationship high enough and you will be able to marry someone.

After getting married, you will be able to have children who will do many chores for you such as: Farming, Fishing, Woodcutting, Hunting, and Mining.

Children will eventually grow up into adults. Adults can get married and have children of their own, and this cycle can repeat indefinitely!

## Dependencies
At runtime, MCA has no external dependencies other than Minecraft Forge.

For development, MCA depends on Lombok. It will be installed automatically when you set up your development environment. Install the Lombok plugin for your relevant IDE if you have trouble building in your IDE.

## Contributing
Any contributions to are welcome. Simply clone into your workspace, set it up, make your changes, and submit a pull request for review.

## Credits
These individuals made substantial contributions to MCA - without them, continued progress may have been impossible.
 - SheWolfDeadly
 - ntzrmtthihu777
 - ko2fan
 - Akjosch
 - Innectic


================================================
FILE: build.gradle
================================================
buildscript {
    repositories {
        mavenCentral()
        jcenter()
        maven { url = "http://files.minecraftforge.net/maven" }
    }
    dependencies {
        classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
    }
}
apply plugin: 'net.minecraftforge.gradle.forge'
//Only edit below this line, the above code adds and enables the necessary things for Forge to be setup.

version = "6.0.1"
group = "com.minecraftcomesalive" // http://maven.apache.org/guides/mini/guide-naming-conventions.html
archivesBaseName = "MCA-1.12.2"

sourceCompatibility = targetCompatibility = '1.8' // Need this here so eclipse task generates correctly.
compileJava {
    sourceCompatibility = targetCompatibility = '1.8'
}

minecraft {
    version = "1.12.2-14.23.5.2768"
    runDir = "run"
    
    // the mappings can be changed at any time, and must be in the following format.
    // snapshot_YYYYMMDD   snapshot are built nightly.
    // stable_#            stables are built at the discretion of the MCP team.
    // Use non-default mappings at your own risk. they may not always work.
    // simply re-run your setup task after changing the mappings to update your workspace.
    mappings = "snapshot_20171003"
    // makeObfSourceJar = false // an Srg named sources jar is made by default. uncomment this to disable.
}

dependencies {
    provided 'org.projectlombok:lombok:1.16.4'
    // you may put jars on which you depend on in ./libs
    // or you may define them like so..
    //compile "some.group:artifact:version:classifier"
    //compile "some.group:artifact:version"
      
    // real examples
    //compile 'com.mod-buildcraft:buildcraft:6.0.8:dev'  // adds buildcraft to the dev env
    //compile 'com.googlecode.efficient-java-matrix-library:ejml:0.24' // adds ejml to the dev env

    // the 'provided' configuration is for optional dependencies that exist at compile-time but might not at runtime.
    //provided 'com.mod-buildcraft:buildcraft:6.0.8:dev'

    // the deobf configurations:  'deobfCompile' and 'deobfProvided' are the same as the normal compile and provided,
    // except that these dependencies get remapped to your current MCP mappings
    //deobfCompile 'com.mod-buildcraft:buildcraft:6.0.8:dev'
    //deobfProvided 'com.mod-buildcraft:buildcraft:6.0.8:dev'

    // for more info...
    // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html
    // http://www.gradle.org/docs/current/userguide/dependency_management.html

}

processResources {
    // this will ensure that this task is redone when the versions change.
    inputs.property "version", project.version
    inputs.property "mcversion", project.minecraft.version

    // replace stuff in mcmod.info, nothing else
    from(sourceSets.main.resources.srcDirs) {
        include 'mcmod.info'
                
        // replace version and mcversion
        expand 'version':project.version, 'mcversion':project.minecraft.version
    }
        
    // copy everything else except the mcmod.info
    from(sourceSets.main.resources.srcDirs) {
        exclude 'mcmod.info'
    }
}

jar {
    classifier = 'universal'
}

================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Tue Jun 18 00:42:38 PDT 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14-all.zip


================================================
FILE: gradle.properties
================================================
# Sets default memory used for gradle commands. Can be overridden by user or command line properties.
# This is required to provide enough memory for the Minecraft decompilation process.
org.gradle.jvmargs=-Xmx3G


================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: src/main/java/mca/api/API.java
================================================
package mca.api;

import com.google.common.base.Charsets;
import mca.api.types.APIButton;
import mca.api.types.Gift;
import mca.api.types.SkinsGroup;
import mca.client.gui.component.GuiButtonEx;
import mca.core.Constants;
import mca.core.MCA;
import mca.entity.EntityVillagerMCA;
import mca.enums.EnumConstraint;
import mca.enums.EnumGender;
import mca.util.Util;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.StringUtils;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.fml.common.registry.VillagerRegistry;
import org.apache.commons.io.IOUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.io.InputStream;
import java.util.*;

/**
 * Class API handles interaction with MCA's configurable options via JSON in the resources folder
 */
public class API {
    private static Map<String, Gift> giftMap = new HashMap<>();
    private static Map<String, APIButton[]> buttonMap = new HashMap<>();
    private static List<String> maleNames = new ArrayList<>();
    private static List<String> femaleNames = new ArrayList<>();
    private static List<SkinsGroup> skinGroups = new ArrayList<>();
    private static Random rng;

    /**
     * Performs initialization of the API
     */
    public static void init() {
        rng = new Random();

        // Load skins
        SkinsGroup[] skins = Util.readResourceAsJSON("api/skins.json", SkinsGroup[].class);
        Collections.addAll(skinGroups, skins);

        // Load names
        InputStream namesStream = StringUtils.class.getResourceAsStream("/assets/mca/lang/names.lang");
        try {
            // read in all names and process into the correct list
            List<String> lines = IOUtils.readLines(namesStream, Charsets.UTF_8);
            lines.stream().filter((l) -> l.contains("name.male")).forEach((l) -> maleNames.add(l.split("\\=")[1]));
            lines.stream().filter((l) -> l.contains("name.female")).forEach((l) -> femaleNames.add(l.split("\\=")[1]));
        } catch (Exception e) {
            MCA.getLog().fatal(e);
            throw new RuntimeException("Failed to load all NPC names from file", e);
        }

        // Read in buttons
        buttonMap.put("main", Util.readResourceAsJSON("api/gui/main.json", APIButton[].class));
        buttonMap.put("interact", Util.readResourceAsJSON("api/gui/interact.json", APIButton[].class));
        buttonMap.put("debug", Util.readResourceAsJSON("api/gui/debug.json", APIButton[].class));
        buttonMap.put("editor", Util.readResourceAsJSON("api/gui/editor.json", APIButton[].class));
        buttonMap.put("work", Util.readResourceAsJSON("api/gui/work.json", APIButton[].class));
        buttonMap.put("location", Util.readResourceAsJSON("api/gui/location.json", APIButton[].class));

        // Load gifts and assign to the appropriate map with a key value pair and print warnings on potential issues
        Gift[] gifts = Util.readResourceAsJSON("api/gifts.json", Gift[].class);
        for (Gift gift : gifts) {
            if (!gift.exists()) {
                MCA.getLog().warn("Could not find gift item or block in registry: " + gift.getName());
            } else {
                giftMap.put(gift.getName(), gift);
            }
        }
    }

    /**
     * Returns a random skin based on the profession and gender provided.
     *
     * @param villager The villager who will be assigned the random skin.
     * @return String location of the random skin
     */
    public static String getRandomSkin(EntityVillagerMCA villager) {
        VillagerRegistry.VillagerProfession profession = villager.getProfessionForge();
        EnumGender gender = EnumGender.byId(villager.get(EntityVillagerMCA.GENDER));
        String name = villager.get(EntityVillagerMCA.VILLAGER_NAME);

        //Special-case skins
        if (gender == EnumGender.MALE) {
            switch (name.toLowerCase()) {
                case "pewdiepie": return "mca:skins/male/special/pewdiepie_boy.png";
                case "sven": return "mca:skins/male/special/sven.png";
                case "noob":
                case "noober":
                case "neeber": return "mca:skins/male/special/noob.png";
                case "shepard": return "mca:skins/male/special/shepard.png";
                case "minsc": return "mca:skins/male/special/minsc.png";
            }
        } else if (gender == EnumGender.FEMALE) {
            switch (name.toLowerCase()) {
                case "pewdiepie": return "mca:skins/female/special/pewdiepie_girl.png";
            }
        }

        //Default skin behavior
        Optional<SkinsGroup> group = skinGroups.stream()
                        .filter(g -> g.getGender() == gender && profession.getRegistryName() != null && g.getProfession().equals(profession.getRegistryName().toString()))
                        .findFirst();

        return group.map(g -> g.getPaths()[rng.nextInt(g.getPaths().length - 1)]).orElseGet(() -> {
            MCA.getLog().warn("No skin found for profession: `" + profession.getRegistryName() + "`. A random skin will be generated.");
            SkinsGroup randomGroup = null;
            while (randomGroup == null || randomGroup.getGender() != gender) {
                randomGroup = skinGroups.get(rng.nextInt(skinGroups.size() - 1));
            }
            return randomGroup.getPaths()[rng.nextInt(randomGroup.getPaths().length)];
        });
    }

    /**
     * Returns an API button based on its ID
     *
     * @param id String id matching the targeted button
     * @return Instance of APIButton matching the ID provided
     */
    public static Optional<APIButton> getButtonById(String key, String id) {
        return Arrays.stream(buttonMap.get(key)).filter(b -> b.getIdentifier().equals(id)).findFirst();
    }

    /**
     * Returns the value of a gift from an ItemStack
     *
     * @param stack ItemStack containing the gift item
     * @return int value determining the gift value of a stack
     */
    public static int getGiftValueFromStack(ItemStack stack) {
        if (stack.getItem().getRegistryName() == null) return 0;

        String name = stack.getItem().getRegistryName().toString();
        return giftMap.containsKey(name) ? giftMap.get(name).getValue() : -5;
    }

    /**
     * Returns the proper response type based on a gift provided
     *
     * @param stack ItemStack containing the gift item
     * @return String value of the appropriate response type
     */
    public static String getResponseForGift(ItemStack stack) {
        int value = getGiftValueFromStack(stack);
        return "gift." + (value <= 0 ? "fail" : value <= 5 ? "good" : value <= 10 ? "better" : "best");
    }

    /**
     * Gets a random name based on the gender provided.
     *
     * @param gender The gender the name should be appropriate for.
     * @return A gender appropriate name based on the provided gender.
     */
    public static String getRandomName(@Nonnull EnumGender gender) {
        if (gender == EnumGender.MALE) return maleNames.get(rng.nextInt(maleNames.size()));
        else if (gender == EnumGender.FEMALE) return femaleNames.get(rng.nextInt(femaleNames.size()));
        return "";
    }

    /**
     * Adds API buttons to the GUI screen provided.
     *
     * @param guiKey   String key for the GUI's buttons
     * @param villager Optional EntityVillagerMCA the GuiScreen has been opened on
     * @param player   EntityPlayer who has opened the GUI
     * @param screen   GuiScreen instance the buttons should be added to
     */
    public static void addButtons(String guiKey, @Nullable EntityVillagerMCA villager, EntityPlayer player, GuiScreen screen) {
        List<GuiButton> buttonList = ObfuscationReflectionHelper.getPrivateValue(GuiScreen.class, screen, Constants.GUI_SCREEN_BUTTON_LIST_FIELD_INDEX);
        for (APIButton b : buttonMap.get(guiKey)) {
            GuiButtonEx guiButton = new GuiButtonEx(screen, b);
            buttonList.add(guiButton);

            // Ensure that if a constraint is attached to the button
            if (villager == null && b.getConstraints().size() > 0) {
                MCA.getLog().error("No villager provided for list of buttons with constraints! Button ID:" + b.getIdentifier());
                continue;
            }

            // Remove the button if we specify it should not be present on constraint failure
            // Otherwise we just mark the button as disabled.
            boolean isValid = b.isValidForConstraint(villager, player);
            if (!isValid && b.getConstraints().contains(EnumConstraint.HIDE_ON_FAIL)) buttonList.remove(guiButton);
            else if (!isValid) guiButton.enabled = false;
        }
    }

    /**
     * Returns an instance of the button linked to the given ID on the provided GuiScreen
     *
     * @param id     String id of the button desired
     * @param screen GuiScreen containing the button
     * @return GuiButtonEx matching the provided id
     */
    public static Optional<GuiButtonEx> getButton(String id, GuiScreen screen) {
        List<GuiButton> buttonList = ObfuscationReflectionHelper.getPrivateValue(GuiScreen.class, screen, Constants.GUI_SCREEN_BUTTON_LIST_FIELD_INDEX);
        Optional<GuiButton> button = buttonList.stream().filter(
                (b) -> b instanceof GuiButtonEx && ((GuiButtonEx) b).getApiButton().getIdentifier().equals(id)).findFirst();

        return button.map(guiButton -> (GuiButtonEx) guiButton);
    }
}


================================================
FILE: src/main/java/mca/api/types/APIButton.java
================================================
package mca.api.types;

import lombok.AllArgsConstructor;
import lombok.Getter;
import mca.entity.EntityVillagerMCA;
import mca.enums.EnumConstraint;
import net.minecraft.entity.player.EntityPlayer;

import java.util.List;

/**
 * APIButton is a button defined in assets/mca/api/gui/*
 * <p>
 * These buttons are dynamically attached to a GuiScreen and include additional instruction/constraints for building
 * and processing interactions.
 */
@AllArgsConstructor
public class APIButton {
    @Getter private int id;             // numeric id
    @Getter private String identifier;  // string identifier for the button in the .lang file
    @Getter private int x;              // x position
    @Getter private int y;              // y position
    @Getter private int width;          // button width
    @Getter private int height;         // button height
    @Getter private boolean notifyServer;   // whether the button press is sent to the server for processing
    @Getter private boolean targetServer;   // whether the button is processed by the villager or the server itself
    private String constraints;     // list of EnumConstraints separated by a pipe character |
    @Getter private boolean isInteraction;  // whether the button is an interaction that generates a response and boosts/decreases hearts

    public List<EnumConstraint> getConstraints() {
        return EnumConstraint.fromStringList(constraints);
    }

    /**
     * Determines if the given villager and player match the constraints for this button, allowing the action to be performed
     *
     * @param villager Instance of the EntityVillagerMCA the button would perform the action on
     * @param player   Instance of the EntityPlayer performing the action
     * @return boolean whether the button is valid for a constraint
     */
    public boolean isValidForConstraint(EntityVillagerMCA villager, EntityPlayer player) {
        List<EnumConstraint> constraints = getConstraints();

        if (constraints.contains(EnumConstraint.ADULTS) && !villager.isChild()) {
            return true;
        } else if (constraints.contains(EnumConstraint.SPOUSE) && villager.isMarriedTo(player.getUniqueID())) {
            return true;
        } else if (constraints.contains(EnumConstraint.NOT_SPOUSE) && !villager.isMarriedTo(player.getUniqueID())) {
            return true;
        } else if (constraints.contains(EnumConstraint.FAMILY) && (villager.playerIsParent(player) || villager.isMarriedTo(player.getUniqueID()))){
            return true;
        } else if (constraints.contains(EnumConstraint.NOT_FAMILY) && !(villager.playerIsParent(player) || villager.isMarriedTo(player.getUniqueID()))) {
            return true;
        } else if (constraints.isEmpty()) {
            return true;
        }
        return false;
    }
}


================================================
FILE: src/main/java/mca/api/types/Gift.java
================================================
package mca.api.types;

import lombok.AllArgsConstructor;
import lombok.Getter;
import mca.core.MCA;
import net.minecraft.block.Block;
import net.minecraft.item.Item;

@AllArgsConstructor
@Getter
public class Gift {
    private String type;
    private String name;
    private int value;

    /**
     * Used for verifying if a given gift exists in the game's registries.
     * @return True if the item/block exists.
     */
    public boolean exists() {
        if (getType().equals("block")) {
            return Block.getBlockFromName(getName()) != null;
        } else if (getType().equals("item")) {
            return Item.getByNameOrId(getName()) != null;
        } else {
            MCA.getLog().warn("Could not process gift '" + getName() + "'- bad type name of '" + getType() + "'. Must be 'item' or 'block'");
            return false;
        }
    }
}


================================================
FILE: src/main/java/mca/api/types/SkinsGroup.java
================================================
package mca.api.types;

import lombok.AllArgsConstructor;
import lombok.Getter;
import mca.enums.EnumGender;

@AllArgsConstructor
public class SkinsGroup {
    private String gender;
    @Getter private String profession;
    @Getter private String[] paths;

    public EnumGender getGender() {
        return EnumGender.byName(gender);
    }
}


================================================
FILE: src/main/java/mca/blocks/BlockVillagerSpawner.java
================================================
package mca.blocks;

import com.google.common.base.Optional;
import mca.core.MCA;
import mca.entity.EntityVillagerMCA;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;

import java.util.Random;

public class BlockVillagerSpawner extends Block {

    public BlockVillagerSpawner() {
        super(Material.IRON);
        setTickRandomly(true);
        setBlockUnbreakable();
    }

    @Override
    public void updateTick(World world, BlockPos pos, IBlockState state, Random random) {
        super.updateTick(world, pos, state, random);

        int nearbyVillagers = world.getEntitiesWithinAABB(EntityVillagerMCA.class, new AxisAlignedBB(pos).expand(32D, 32D, 32D)).size();
        if (nearbyVillagers < MCA.getConfig().villagerSpawnerCap) {
            int yMod = 0;

            // Start from the current point possible and count up until air is hit. This allows the spawner to
            // be placed anywhere below ground and still spawn a villager on a top level.
            while (pos.getY() + yMod < 256) {
                BlockPos current = pos.add(0, yMod, 0);
                BlockPos above = pos.add(0, yMod + 1, 0);

                if (world.isAirBlock(current) && world.isAirBlock(above)) {
                    EntityVillagerMCA villager = new EntityVillagerMCA(world, Optional.absent(), Optional.absent());
                    villager.setPosition(current.getX(), current.getY(), current.getZ());
                    world.spawnEntity(villager);
                    break;
                }

                yMod++;
            }
        }

        world.scheduleUpdate(pos, this, MCA.getConfig().villagerSpawnerRateMinutes * 72000);
    }
}

================================================
FILE: src/main/java/mca/client/MCAGuiFactory.java
================================================
package mca.client;

import mca.client.gui.GuiConfigPage;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.IModGuiFactory;

import java.util.Set;

public class MCAGuiFactory implements IModGuiFactory
{
    @Override
    public void initialize(Minecraft minecraftInstance) {}

    @Override
    public GuiScreen createConfigGui(GuiScreen screen) {
        return new GuiConfigPage(screen);
    }

    @Override
    public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() {
        return null;
    }

    @Override
    public boolean hasConfigGui() {
        return true;
    }
}

================================================
FILE: src/main/java/mca/client/gui/GuiConfigPage.java
================================================
package mca.client.gui;

import mca.core.MCA;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.client.config.GuiConfig;
import net.minecraftforge.fml.client.config.IConfigElement;

import java.util.List;

public class GuiConfigPage extends GuiConfig {
    public GuiConfigPage(GuiScreen parent) {
        this(parent,
                MCA.getConfig().getCategories(),
                MCA.MODID, false, false, GuiConfig.getAbridgedConfigPath(MCA.getConfig().getInstance().toString()));
    }

    public GuiConfigPage(GuiScreen parentScreen, List<IConfigElement> configElements, String modID, boolean allRequireWorldRestart, boolean allRequireMcRestart, String title) {
        super(parentScreen, configElements, modID, allRequireWorldRestart, allRequireMcRestart, title);
    }
}

================================================
FILE: src/main/java/mca/client/gui/GuiInteract.java
================================================
package mca.client.gui;

import mca.api.API;
import mca.client.gui.component.GuiButtonEx;
import mca.core.Constants;
import mca.core.MCA;
import mca.core.forge.NetMCA;
import mca.entity.EntityVillagerMCA;
import mca.entity.data.ParentData;
import mca.entity.data.PlayerHistory;
import mca.enums.EnumMarriageState;
import mca.enums.EnumMoveState;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.GL11;

import java.io.IOException;
import java.util.Optional;

@SideOnly(Side.CLIENT)
public class GuiInteract extends GuiScreen {
    private static final ResourceLocation ICON_TEXTURES = new ResourceLocation("mca:textures/gui.png");
    private static boolean displaySuccessChance;
    private final EntityVillagerMCA villager;
    private final EntityPlayer player;

    private boolean inGiftMode;

    private int timeSinceLastClick;

    private int marriedIconU = 0;
    private int engagedIconU = 64;
    private int notMarriedIconU = 16;
    private int parentsIconU = 32;
    private int giftIconU = 48;
    private int redHeartIconU = 80;
    private int blackHeartIconU = 96;
    private int goldHeartIconU = 112;

    private int mouseX;
    private int mouseY;

    // Tracks which page we're on in the GUI for sending button events
    private String activeKey;

    public GuiInteract(EntityVillagerMCA villager, EntityPlayer player) {
        super();
        this.villager = villager;
        this.player = player;
        this.activeKey = "main";
    }

    @Override
    public void initGui() {
        drawMainButtonMenu();
    }

    @Override
    public void onGuiClosed() {
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false;
    }

    @Override
    public void updateScreen() {
        if (timeSinceLastClick < 100) {
            timeSinceLastClick++;
        }
    }

    @Override
    public void drawScreen(int i, int j, float f) {
        super.drawScreen(i, j, f);
        drawIcons();
        drawTextPopups();

        mouseX = Mouse.getEventX() * width / mc.displayWidth;
        mouseY = height - Mouse.getEventY() * height / mc.displayHeight - 1;
    }

    @Override
    public void handleMouseInput() throws IOException {
        super.handleMouseInput();

        if (Mouse.getEventDWheel() < 0) {
            player.inventory.currentItem = player.inventory.currentItem == 8 ? 0 : player.inventory.currentItem + 1;
        } else if (Mouse.getEventDWheel() > 0) {
            player.inventory.currentItem = player.inventory.currentItem == 0 ? 8 : player.inventory.currentItem - 1;
        }
    }

    @Override
    protected void mouseClicked(int posX, int posY, int button) throws IOException {
        super.mouseClicked(posX, posY, button);

        // Right mouse button
        if (inGiftMode && button == 1) NetMCA.INSTANCE.sendToServer(new NetMCA.ButtonAction(activeKey, "gui.button.gift", villager.getUniqueID()));
    }

    @Override
    protected void keyTyped(char keyChar, int keyCode) {
        // Hotkey to leave gift mode
        if (keyCode == Keyboard.KEY_ESCAPE) {
            if (inGiftMode) {
                inGiftMode = false;
                enableAllButtons();
            } else {
                this.mc.displayGuiScreen(null);
            }
        } else if (keyCode == Keyboard.KEY_LCONTROL) {
            displaySuccessChance = !displaySuccessChance;
        } else {
            try {
                int intInput = Integer.parseInt(String.valueOf(keyChar));

                if (intInput > 0) {
                    player.inventory.currentItem = intInput - 1;
                }
            } catch (NumberFormatException ignored) {
                // When a non numeric character is entered.
            }
        }
    }

    private void drawIcons() {
        PlayerHistory history = villager.getPlayerHistoryFor(player.getUniqueID());
        EnumMarriageState marriageState = EnumMarriageState.byId(villager.get(EntityVillagerMCA.MARRIAGE_STATE));
        int marriageIconU =
                marriageState == EnumMarriageState.MARRIED ? marriedIconU :
                        marriageState == EnumMarriageState.ENGAGED ? engagedIconU :
                                notMarriedIconU;
        int heartIconU =
                history.getHearts() < 0 ? blackHeartIconU :
                        history.getHearts() >= 100 ? goldHeartIconU :
                                redHeartIconU;

        GL11.glPushMatrix();
        {
            GL11.glColor3f(255.0F, 255.0F, 255.0F);
            GL11.glScalef(2.0F, 2.0F, 2.0F);

            this.mc.getTextureManager().bindTexture(ICON_TEXTURES);
            this.drawTexturedModalRect(5, 15, heartIconU, 0, 16, 16);
            this.drawTexturedModalRect(5, 30, marriageIconU, 0, 16, 16);

            if (canDrawParentsIcon()) this.drawTexturedModalRect(5, 45, parentsIconU, 0, 16, 16);

            if (canDrawGiftIcon()) this.drawTexturedModalRect(5, 60, giftIconU, 0, 16, 16);
        }
        GL11.glPopMatrix();
    }

    private void drawTextPopups() {
        EnumMarriageState marriageState = EnumMarriageState.byId(villager.get(EntityVillagerMCA.MARRIAGE_STATE));
        String marriageInfo;

        if (hoveringOverHeartsIcon()) {
            int hearts = villager.getPlayerHistoryFor(player.getUniqueID()).getHearts();
            this.drawHoveringText(hearts + " hearts", 35, 55);
        }

        if (hoveringOverMarriageIcon()) {
            String spouseName = villager.get(EntityVillagerMCA.SPOUSE_NAME);
            if (marriageState == EnumMarriageState.MARRIED) marriageInfo = MCA.getLocalizer().localize("gui.interact.label.married", spouseName);
            else if (marriageState == EnumMarriageState.ENGAGED) marriageInfo = MCA.getLocalizer().localize("gui.interact.label.engaged", spouseName);
            else marriageInfo = MCA.getLocalizer().localize("gui.interact.label.notmarried");

            this.drawHoveringText(marriageInfo, 35, 85);
        }
        if (canDrawParentsIcon() && hoveringOverParentsIcon()) {
            ParentData data = ParentData.fromNBT(villager.get(EntityVillagerMCA.PARENTS));
            this.drawHoveringText(MCA.getLocalizer().localize("gui.interact.label.parents", data.getParent1Name(), data.getParent2Name()), 35, 115);
        }

        if (canDrawGiftIcon() && hoveringOverGiftIcon()) this.drawHoveringText(MCA.getLocalizer().localize("gui.interact.label.gift"), 35, 145);
    }

    private boolean hoveringOverHeartsIcon() {
        return mouseX <= 32 && mouseX >= 16 && mouseY >= 32 && mouseY <= 48;
    }

    private boolean hoveringOverMarriageIcon() {
        return mouseX <= 32 && mouseX >= 16 && mouseY >= 66 && mouseY <= 81;
    }

    private boolean hoveringOverParentsIcon() {
        return mouseX <= 32 && mouseX >= 16 && mouseY >= 100 && mouseY <= 115;
    }

    private boolean hoveringOverGiftIcon() {
        return mouseX <= 32 && mouseX >= 16 && mouseY >= 124 && mouseY <= 148;
    }

    private boolean canDrawParentsIcon() {
        ParentData data = ParentData.fromNBT(villager.get(EntityVillagerMCA.PARENTS));
        return !data.getParent1UUID().equals(Constants.ZERO_UUID) &&
                !data.getParent2UUID().equals(Constants.ZERO_UUID);
    }

    private boolean canDrawGiftIcon() {
        return villager.getPlayerHistoryFor(player.getUniqueID()).isGiftPresent();
    }

    protected void actionPerformed(GuiButton button) {
        GuiButtonEx btn = (GuiButtonEx) button;
        String id = btn.getApiButton().getIdentifier();

        if (timeSinceLastClick <= 2) {
            return; /* Prevents click-throughs on Mojang's button system */
        }
        timeSinceLastClick = 0;

        /* Progression to different GUIs */
        if (id.equals("gui.button.interact")) {
            activeKey = "interact";
            drawInteractButtonMenu();
            return;
        } else if (id.equals("gui.button.work")) {
            activeKey = "work";
            drawWorkButtonMenu();
            return;
        } else if (id.equals("gui.button.backarrow")) {
            drawMainButtonMenu();
            activeKey = "main";
            return;
        } else if (id.equals("gui.button.location")) {
            activeKey = "location";
            drawLocationButtonMenu();
            return;
        }

        /* Anything that should notify the server is handled here */
        else if (btn.getApiButton().isNotifyServer()) {
            NetMCA.INSTANCE.sendToServer(new NetMCA.ButtonAction(activeKey, id, villager.getUniqueID()));
        } else if (id.equals("gui.button.gift")) {
            this.inGiftMode = true;
            disableAllButtons();
            return;
        }

        this.mc.displayGuiScreen(null);
    }

    private void drawMainButtonMenu() {
        buttonList.clear();
        API.addButtons("main", villager, player, this);

        EnumMoveState moveState = EnumMoveState.byId(villager.get(EntityVillagerMCA.MOVE_STATE));
        if (moveState == EnumMoveState.FOLLOW) disableButton("gui.button.follow");
        else if (moveState == EnumMoveState.STAY) disableButton("gui.button.stay");
        else if (moveState == EnumMoveState.MOVE) disableButton("gui.button.move");
    }

    private void drawInteractButtonMenu() {
        buttonList.clear();
        API.addButtons("interact", villager, player, this);
    }

    private void drawWorkButtonMenu() {
        buttonList.clear();
        API.addButtons("work", villager, player, this);
    }

    private void drawLocationButtonMenu() {
        buttonList.clear();
        API.addButtons("location", villager, player, this);
    }

    private void disableButton(String id) {
        Optional<GuiButtonEx> b = API.getButton(id, this);

        b.ifPresent(guiButtonEx -> guiButtonEx.enabled = false);
    }

    private void enableAllButtons() {
        buttonList.forEach((b) -> b.enabled = true);
    }

    private void disableAllButtons() {
        buttonList.forEach((b) -> b.enabled = false);
    }
}

================================================
FILE: src/main/java/mca/client/gui/GuiNameBaby.java
================================================
package mca.client.gui;

import mca.api.API;
import mca.core.MCA;
import mca.core.forge.NetMCA;
import mca.items.ItemBaby;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.input.Keyboard;

import java.io.IOException;

@SideOnly(Side.CLIENT)
public class GuiNameBaby extends GuiScreen {
    private final EntityPlayer player;

    private GuiTextField babyNameTextField;
    private GuiButton doneButton;
    private GuiButton randomButton;
    private ItemBaby baby;

    public GuiNameBaby(EntityPlayer player, ItemStack babyStack) {
        super();
        this.player = player;

        if (babyStack.getItem() instanceof ItemBaby) this.baby = (ItemBaby) babyStack.getItem();
    }

    @Override
    public void updateScreen() {
        super.updateScreen();

        if (babyNameTextField != null) {
            babyNameTextField.updateCursorCounter();
            doneButton.enabled = !babyNameTextField.getText().isEmpty();
        }
    }

    @Override
    public void initGui() {
        Keyboard.enableRepeatEvents(true);

        buttonList.clear();
        buttonList.add(doneButton = new GuiButton(1, width / 2 - 40, height / 2 - 10, 80, 20, MCA.getLocalizer().localize("gui.button.done")));
        buttonList.add(randomButton = new GuiButton(2, width / 2 + 105, height / 2 - 60, 60, 20, MCA.getLocalizer().localize("gui.button.random")));
        babyNameTextField = new GuiTextField(3, fontRenderer, width / 2 - 100, height / 2 - 60, 200, 20);
        babyNameTextField.setMaxStringLength(32);

        if (this.baby == null) this.mc.displayGuiScreen(null);
    }

    @Override
    public void onGuiClosed() {
        Keyboard.enableRepeatEvents(false);
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false;
    }

    @Override
    protected void actionPerformed(GuiButton button) {
        if (button == doneButton) {
            NetMCA.INSTANCE.sendToServer(new NetMCA.BabyName(babyNameTextField.getText().trim()));
            mc.displayGuiScreen(null);
        } else if (button == randomButton) {
            babyNameTextField.setText(API.getRandomName(baby.getGender()));
        }
    }

    @Override
    protected void keyTyped(char c, int i) {
        babyNameTextField.textboxKeyTyped(c, i);
    }

    @Override
    protected void mouseClicked(int clickX, int clickY, int clicked) throws IOException {
        super.mouseClicked(clickX, clickY, clicked);
        babyNameTextField.mouseClicked(clickX, clickY, clicked);
    }

    @Override
    public void drawScreen(int sizeX, int sizeY, float offset) {
        drawDefaultBackground();
        drawString(fontRenderer, MCA.getLocalizer().localize("gui.title.namebaby"), width / 2 - 100, height / 2 - 70, 0xa0a0a0);
        babyNameTextField.drawTextBox();
        super.drawScreen(sizeX, sizeY, offset);
    }
}

================================================
FILE: src/main/java/mca/client/gui/GuiStaffOfLife.java
================================================
package mca.client.gui;

import mca.core.MCA;
import mca.core.forge.NetMCA;
import mca.entity.EntityVillagerMCA;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.inventory.GuiInventory;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;

@SideOnly(Side.CLIENT)
public class GuiStaffOfLife extends GuiScreen {
    private Map<String, NBTTagCompound> villagerData;
    private GuiButton reviveButton;
    private GuiButton nameButton;
    private GuiButton backButton;
    private GuiButton nextButton;
    private GuiButton closeButton;
    private EntityVillagerMCA dummy;
    private EntityPlayer player;

    // selection fields
    private int index = 0;
    private List<String> keys = new ArrayList<>();

    public GuiStaffOfLife(EntityPlayer player) {
        super();
        this.player = player;
    }

    @Override
    public void initGui() {
        NetMCA.INSTANCE.sendToServer(new NetMCA.SavedVillagersRequest());

        buttonList.clear();
        buttonList.add(backButton = new GuiButton(1, width / 2 - 123, height / 2 + 65, 20, 20, "<<"));
        buttonList.add(nextButton = new GuiButton(2, width / 2 + 103, height / 2 + 65, 20, 20, ">>"));
        buttonList.add(nameButton = new GuiButton(3, width / 2 - 100, height / 2 + 65, 200, 20, ""));
        buttonList.add(reviveButton = new GuiButton(4, width / 2 - 100, height / 2 + 90, 60, 20, MCA.getLocalizer().localize("gui.button.revive")));
        buttonList.add(closeButton = new GuiButton(5, width / 2 + 40, height / 2 + 90, 60, 20, MCA.getLocalizer().localize("gui.button.exit")));
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false;
    }

    @Override
    protected void actionPerformed(GuiButton guibutton) {
        if (guibutton == reviveButton) {
            NetMCA.INSTANCE.sendToServer(new NetMCA.ReviveVillager(UUID.fromString(keys.get(index))));
            mc.displayGuiScreen(null);
        } else if (guibutton == backButton) selectData(index - 1);
        else if (guibutton == nextButton) selectData(index + 1);
        else if (guibutton == closeButton) mc.displayGuiScreen(null);
    }

    @Override
    public void drawScreen(int sizeX, int sizeY, float offset) {
        drawDefaultBackground();
        drawDummy();
        drawCenteredString(fontRenderer, MCA.getLocalizer().localize("gui.title.staffoflife"), width / 2, height / 2 - 110, 0xffffff);
        super.drawScreen(sizeX, sizeY, offset);
    }

    public void setVillagerData(Map<String, NBTTagCompound> data) {
        villagerData = data;

        if (data.size() > 0) {
            dummy = new EntityVillagerMCA(player.world);
            keys.addAll(data.keySet());
            selectData(0);
        } else {
            nameButton.displayString = "No villagers found.";
            backButton.enabled = false;
            nextButton.enabled = false;
            nameButton.enabled = false;
            reviveButton.enabled = false;
        }
    }

    private void updateDummy(NBTTagCompound nbt) {
        dummy.readEntityFromNBT(nbt);
        dummy.setHealth(20.0F);
    }

    private void selectData(int i) {
        if (i < 0) i = keys.size() - 1;
        else if (i > keys.size() - 1) i = 0;

        index = i;
        updateDummy(villagerData.get(keys.get(index)));
        nameButton.displayString = dummy.getDisplayName().getUnformattedText();
    }

    private void drawDummy() {
        int posX = width / 2;
        int posY = height / 2 + 45;

        if (dummy != null) GuiInventory.drawEntityOnScreen(posX, posY, 60, 0, 0, dummy);
    }
}

================================================
FILE: src/main/java/mca/client/gui/GuiVillagerEditor.java
================================================
package mca.client.gui;

import mca.api.API;
import mca.api.types.APIButton;
import mca.client.gui.component.GuiButtonEx;
import mca.core.MCA;
import mca.core.forge.NetMCA;
import mca.entity.EntityVillagerMCA;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import org.lwjgl.input.Keyboard;

import java.awt.*;
import java.awt.datatransfer.StringSelection;
import java.io.IOException;

@SideOnly(Side.CLIENT)
public class GuiVillagerEditor extends GuiScreen {
    private final EntityVillagerMCA villager;
    private final EntityPlayer player;

    private GuiTextField nameTextField;
    private GuiTextField professionTextField;
    private GuiTextField textureTextField;

    public GuiVillagerEditor(EntityVillagerMCA EntityHuman, EntityPlayer player) {
        super();
        this.player = player;
        villager = EntityHuman;
    }

    @Override
    public void updateScreen() {
        super.updateScreen();
        nameTextField.updateCursorCounter();
        professionTextField.updateCursorCounter();
        textureTextField.updateCursorCounter();
    }

    @Override
    public void initGui() {
        Keyboard.enableRepeatEvents(true);
        drawEditorGui();

        nameTextField = new GuiTextField(1, fontRenderer, width / 2 - 205, height / 2 - 95, 150, 20);
        nameTextField.setMaxStringLength(32);
        nameTextField.setText(villager.get(EntityVillagerMCA.VILLAGER_NAME));
        professionTextField = new GuiTextField(2, fontRenderer, width / 2 - 190, height / 2 + 10, 250, 20);
        professionTextField.setMaxStringLength(64);
        professionTextField.setText(villager.getVanillaCareer().getName());
        textureTextField = new GuiTextField(3, fontRenderer, width / 2 - 190, height / 2 - 15, 250, 20);
        textureTextField.setMaxStringLength(128);
        textureTextField.setText(villager.get(EntityVillagerMCA.TEXTURE));
    }

    @Override
    public void onGuiClosed() {
        Keyboard.enableRepeatEvents(false);
    }

    @Override
    protected void actionPerformed(GuiButton guiButton) {
        APIButton btn = ((GuiButtonEx) guiButton).getApiButton();
        if (btn.isNotifyServer()) {
            NetMCA.INSTANCE.sendToServer(new NetMCA.ButtonAction("editor", btn.getIdentifier(), villager.getUniqueID()));
        } else if (btn.getIdentifier().equals("gui.button.done")) {
            mc.displayGuiScreen(null);
        } else if (btn.getIdentifier().equals("gui.button.copyuuid")) {
            Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new StringSelection(villager.getUniqueID().toString()), null);
            Minecraft.getMinecraft().player.sendChatMessage("Villager UUID copied to clipboard.");
        } else if (btn.getIdentifier().equals("gui.button.profession.set")) {
            String profession = professionTextField.getText();
            NetMCA.INSTANCE.sendToServer(new NetMCA.SetProfession(villager.getUniqueID(), profession));
            new java.util.Timer().schedule(new java.util.TimerTask() {
                        @Override
                        public void run() {
                            NetMCA.INSTANCE.sendToServer(new NetMCA.CareerRequest(villager.getUniqueID()));
                        }
                    },500
            );
        } else if (btn.getIdentifier().contains("gui.button.texture")) {
            String texture = btn.getIdentifier().endsWith(".set") ? textureTextField.getText() : API.getRandomSkin(villager);
            NetMCA.INSTANCE.sendToServer(new NetMCA.SetTexture(villager.getUniqueID(), texture));
            textureTextField.setText(texture);
        }
    }

    @Override
    protected void keyTyped(char c, int i) {
        if (i == Keyboard.KEY_ESCAPE) {
            Minecraft.getMinecraft().displayGuiScreen(null);
        } else {
            if (nameTextField.textboxKeyTyped(c, i)) {
                String text = nameTextField.getText().trim();
                NetMCA.INSTANCE.sendToServer(new NetMCA.SetName(text, villager.getUniqueID()));
            }
            textureTextField.textboxKeyTyped(c, i);
            professionTextField.textboxKeyTyped(c, i);
            drawEditorGui();
        }
    }

    @Override
    protected void mouseClicked(int clickX, int clickY, int clicked) throws IOException {
        super.mouseClicked(clickX, clickY, clicked);
        nameTextField.mouseClicked(clickX, clickY, clicked);
        professionTextField.mouseClicked(clickX, clickY, clicked);
        textureTextField.mouseClicked(clickX, clickY, clicked);
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false;
    }

    private void drawEditorGui() {
        buttonList.clear();
        API.addButtons("editor", villager, player, this);
    }

    @Override
    public void drawScreen(int sizeX, int sizeY, float offset) {
        drawGradientRect(0, 0, width, height, -1072689136, -804253680);
        drawString(fontRenderer, "Name:", width / 2 - 205, height / 2 - 110, 0xffffff);
        drawCenteredString(fontRenderer, MCA.getLocalizer().localize("gui.title.editor"), width / 2, height / 2 - 110, 0xffffff);
        nameTextField.drawTextBox();
        professionTextField.drawTextBox();
        textureTextField.drawTextBox();
        super.drawScreen(sizeX, sizeY, offset);
    }
}

================================================
FILE: src/main/java/mca/client/gui/GuiWhistle.java
================================================
package mca.client.gui;

import lombok.NonNull;
import mca.core.forge.NetMCA;
import net.minecraft.nbt.NBTTagCompound;
import org.apache.commons.lang3.StringUtils;

import mca.core.MCA;
import mca.entity.EntityVillagerMCA;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;

import java.util.List;

import static mca.entity.EntityVillagerMCA.*;

@SideOnly(Side.CLIENT)
public class GuiWhistle extends GuiScreen {
    private EntityVillagerMCA dummyHuman;
    private List<NBTTagCompound> villagerDataList;

    private GuiButton selectionLeftButton;
    private GuiButton selectionRightButton;
    private GuiButton villagerNameButton;
    private GuiButton callButton;
    private GuiButton exitButton;
    private int loadingAnimationTicks;
    private int selectedIndex;

    @Override
    public void updateScreen() {
        super.updateScreen();

        if (loadingAnimationTicks != -1) {
            loadingAnimationTicks++;
        }

        if (loadingAnimationTicks >= 20) {
            loadingAnimationTicks = 0;
        }
    }

    @Override
    public void initGui() {
        buttonList.clear();
        buttonList.add(selectionLeftButton = new GuiButton(1, width / 2 - 123, height / 2 + 65, 20, 20, "<<"));
        buttonList.add(selectionRightButton = new GuiButton(2, width / 2 + 103, height / 2 + 65, 20, 20, ">>"));
        buttonList.add(villagerNameButton = new GuiButton(3, width / 2 - 100, height / 2 + 65, 200, 20, ""));
        buttonList.add(callButton = new GuiButton(4, width / 2 - 100, height / 2 + 90, 60, 20, MCA.getLocalizer().localize("gui.button.call")));
        buttonList.add(exitButton = new GuiButton(6, width / 2 + 40, height / 2 + 90, 60, 20, MCA.getLocalizer().localize("gui.button.exit")));
        NetMCA.INSTANCE.sendToServer(new NetMCA.GetFamily());
    }

    @Override
    public boolean doesGuiPauseGame() {
        return false;
    }

    @Override
    protected void actionPerformed(GuiButton guibutton) {
        if (guibutton == exitButton) {
            Minecraft.getMinecraft().displayGuiScreen(null);
        }

        if (villagerDataList != null && villagerDataList.size() > 0) {
            NBTTagCompound data = villagerDataList.get(selectedIndex - 1);

            if (guibutton == selectionLeftButton) {
                if (selectedIndex == 1) {
                    selectedIndex = villagerDataList.size();
                }

                else {
                    selectedIndex--;
                }
            }

            else if (guibutton == selectionRightButton) {
                if (selectedIndex == villagerDataList.size()) {
                    selectedIndex = 1;
                }

                else {
                    selectedIndex++;
                }
            }

            else if (guibutton == callButton) {
                NetMCA.INSTANCE.sendToServer(new NetMCA.CallToPlayer(data.getUniqueId("uuid")));
                Minecraft.getMinecraft().displayGuiScreen(null);
            }

            villagerNameButton.displayString = data.getString("name");
            updateDummyVillagerWithData(data);
        }
    }

    @Override
    public void drawScreen(int sizeX, int sizeY, float offset) {
        drawDefaultBackground();
        drawCenteredString(fontRenderer, MCA.getLocalizer().localize("gui.title.whistle"), width / 2, height / 2 - 110, 0xffffff);

        if (loadingAnimationTicks != -1) {
            drawString(fontRenderer, "Loading" + StringUtils.repeat(".", loadingAnimationTicks % 10), width / 2 - 20, height / 2 - 10, 0xffffff);
        }

        else {
            if (villagerDataList.size() == 0) {
                drawCenteredString(fontRenderer, "No family members could be found in the area.", width / 2, height / 2 + 50, 0xffffff);
            }

            else {
                drawCenteredString(fontRenderer, selectedIndex + " / " + villagerDataList.size(), width / 2, height / 2 + 50, 0xffffff);
            }
        }

        if (dummyHuman != null) {
            drawDummyVillager();
        }

        super.drawScreen(sizeX, sizeY, offset);
    }

    private void drawDummyVillager() {
        final int posX = width / 2;
        int posY = height / 2 + 45;
        net.minecraft.client.gui.inventory.GuiInventory.drawEntityOnScreen(posX, posY, 75, 0, 0, dummyHuman);
    }

    public void setVillagerDataList(@NonNull List<NBTTagCompound> dataList) {
        this.villagerDataList = dataList;
        this.loadingAnimationTicks = -1;
        this.selectedIndex = 1;

        try {
            NBTTagCompound firstData = dataList.get(0);
            villagerNameButton.displayString = firstData.getString("name");
            dummyHuman = new EntityVillagerMCA(Minecraft.getMinecraft().world);
            updateDummyVillagerWithData(firstData);
        }

        catch (IndexOutOfBoundsException e) {
            callButton.enabled = false;
        }
    }

    private void updateDummyVillagerWithData(NBTTagCompound nbt) {
        dummyHuman.set(VILLAGER_NAME, nbt.getString("name"));
        dummyHuman.set(TEXTURE, nbt.getString("texture"));
        dummyHuman.set(GIRTH, nbt.getFloat("girth"));
        dummyHuman.set(TALLNESS, nbt.getFloat("tallness"));
        dummyHuman.set(IS_INFECTED, nbt.getBoolean("infected"));
        dummyHuman.set(AGE_STATE, nbt.getInteger("ageState"));
    }
}

================================================
FILE: src/main/java/mca/client/gui/component/GuiButtonEx.java
================================================
package mca.client.gui.component;

import lombok.Getter;
import mca.api.types.APIButton;
import mca.core.MCA;
import net.minecraft.client.gui.GuiButton;
import net.minecraft.client.gui.GuiScreen;

public class GuiButtonEx extends GuiButton {
    @Getter private APIButton apiButton;

    public GuiButtonEx(GuiScreen gui, APIButton apiButton) {
        super(apiButton.getId(), (gui.width / 2) + apiButton.getX(), (gui.height / 2) + apiButton.getY(), apiButton.getWidth(), apiButton.getHeight(), MCA.getLocalizer().localize(apiButton.getIdentifier()));
        this.apiButton = apiButton;
    }
}


================================================
FILE: src/main/java/mca/client/model/ModelGrimReaper.java
================================================
package mca.client.model;

import mca.entity.EntityGrimReaper;
import mca.enums.EnumReaperAttackState;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.MathHelper;
import org.lwjgl.opengl.GL11;

public class ModelGrimReaper extends ModelBiped {
    private ModelRenderer head;
    private ModelRenderer rightArm;
    private ModelRenderer leftLeg;
    private ModelRenderer cowl;
    private ModelRenderer chest;
    private ModelRenderer leftArm;
    private ModelRenderer rightLeg;

    private ModelRenderer cowlPreAttack;
    private ModelRenderer rightArmPreAttack;
    private ModelRenderer leftLegPreAttack;
    private ModelRenderer headPreAttack;
    private ModelRenderer chestPreAttack;
    private ModelRenderer leftArmPreAttack;
    private ModelRenderer rightLegPreAttack;
    private ModelRenderer scytheHandlePreAttack;
    private ModelRenderer scytheHeadPreAttack;

    private ModelRenderer cowlPostAttack;
    private ModelRenderer rightArmPostAttack;
    private ModelRenderer leftLegPostAttack;
    private ModelRenderer headPostAttack;
    private ModelRenderer chestPostAttack;
    private ModelRenderer leftArmPostAttack;
    private ModelRenderer rightLegPostAttack;
    private ModelRenderer scytheHandlePostAttack;
    private ModelRenderer scytheHeadPostAttack;

    private ModelRenderer cowlBlock;
    private ModelRenderer rightArmBlock;
    private ModelRenderer leftLegBlock;
    private ModelRenderer headBlock;
    private ModelRenderer chestBlock;
    private ModelRenderer leftArmBlock;
    private ModelRenderer rightLegBlock;
    private ModelRenderer scytheHandleBlock;
    private ModelRenderer scytheHeadBlock;

    private ModelRenderer cowlRest;
    private ModelRenderer rightArmRest;
    private ModelRenderer leftLegRest;
    private ModelRenderer chestRest;
    private ModelRenderer leftArmRest;
    private ModelRenderer rightLegRest;
    private ModelRenderer scytheHandleRest;
    private ModelRenderer scytheHeadRest;
    private ModelRenderer headRest;

    public ModelGrimReaper() {
        this.textureWidth = 64;
        this.textureHeight = 64;

        this.leftLeg = new ModelRenderer(this, 0, 16);
        this.leftLeg.mirror = true;
        this.leftLeg.setRotationPoint(1.9F, 12.0F, 0.0F);
        this.leftLeg.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.leftArm = new ModelRenderer(this, 40, 16);
        this.leftArm.mirror = true;
        this.leftArm.setRotationPoint(5.0F, 2.0F, 0.0F);
        this.leftArm.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.rightLeg = new ModelRenderer(this, 0, 16);
        this.rightLeg.setRotationPoint(-1.9F, 12.0F, 0.0F);
        this.rightLeg.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.chest = new ModelRenderer(this, 16, 16);
        this.chest.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.chest.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, 0.0F);
        this.cowl = new ModelRenderer(this, 0, 0);
        this.cowl.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.cowl.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.0F);
        this.head = new ModelRenderer(this, 32, 0);
        this.head.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.head.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.5F);
        this.rightArm = new ModelRenderer(this, 40, 16);
        this.rightArm.setRotationPoint(-5.0F, 2.0F, 0.0F);
        this.rightArm.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);

        this.leftArmPreAttack = new ModelRenderer(this, 40, 16);
        this.leftArmPreAttack.mirror = true;
        this.leftArmPreAttack.setRotationPoint(5.0F, 2.0F, 0.0F);
        this.leftArmPreAttack.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftArmPreAttack, -2.276432943376204F, -1.9577358219620393F, 0.136659280431156F);
        this.cowlPreAttack = new ModelRenderer(this, 32, 0);
        this.cowlPreAttack.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.cowlPreAttack.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.5F);
        this.setRotateAngle(cowlPreAttack, -0.27314402793711257F, 0.18203784098300857F, 0.0F);
        this.rightLegPreAttack = new ModelRenderer(this, 0, 16);
        this.rightLegPreAttack.setRotationPoint(-1.9F, 12.0F, 0.0F);
        this.rightLegPreAttack.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightLegPreAttack, 0.22759093446006054F, -0.22759093446006054F, 0.0F);
        this.leftLegPreAttack = new ModelRenderer(this, 0, 16);
        this.leftLegPreAttack.mirror = true;
        this.leftLegPreAttack.setRotationPoint(1.9F, 12.0F, 0.0F);
        this.leftLegPreAttack.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftLegPreAttack, 0.31869712141416456F, -0.22759093446006054F, 0.0F);
        this.chestPreAttack = new ModelRenderer(this, 16, 16);
        this.chestPreAttack.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.chestPreAttack.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, 0.0F);
        this.setRotateAngle(chestPreAttack, 0.0F, -0.22759093446006054F, 0.0F);
        this.scytheHandlePreAttack = new ModelRenderer(this, 36, 32);
        this.scytheHandlePreAttack.setRotationPoint(7.0F, -12.4F, 17.2F);
        this.scytheHandlePreAttack.addBox(0.0F, 0.0F, 0.0F, 1, 31, 1, 0.0F);
        this.setRotateAngle(scytheHandlePreAttack, -1.0471975511965976F, -0.36425021489121656F, 0.0F);
        this.rightArmPreAttack = new ModelRenderer(this, 40, 16);
        this.rightArmPreAttack.setRotationPoint(-5.0F, 2.0F, 0.0F);
        this.rightArmPreAttack.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightArmPreAttack, -0.6373942428283291F, 2.1399481958702475F, 0.0F);
        this.headPreAttack = new ModelRenderer(this, 0, 0);
        this.headPreAttack.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.headPreAttack.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.0F);
        this.setRotateAngle(headPreAttack, -0.27314402793711257F, 0.18203784098300857F, 0.0F);
        this.scytheHeadPreAttack = new ModelRenderer(this, 0, 32);
        this.scytheHeadPreAttack.setRotationPoint(7.8F, -11.8F, 17.5F);
        this.scytheHeadPreAttack.addBox(0.0F, 0.0F, 0.0F, 16, 16, 0, 0.0F);
        this.setRotateAngle(scytheHeadPreAttack, -1.0471975511965976F, -0.36425021489121656F, 0.0F);

        this.chestPostAttack = new ModelRenderer(this, 16, 16);
        this.chestPostAttack.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.chestPostAttack.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, 0.0F);
        this.setRotateAngle(chestPostAttack, 0.5918411493512771F, 0.5918411493512771F, 0.0F);
        this.leftArmPostAttack = new ModelRenderer(this, 40, 16);
        this.leftArmPostAttack.mirror = true;
        this.leftArmPostAttack.setRotationPoint(5.0F, 2.0F, 0.0F);
        this.leftArmPostAttack.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftArmPostAttack, -0.7740535232594852F, 1.0927506446736497F, 0.136659280431156F);
        this.cowlPostAttack = new ModelRenderer(this, 32, 0);
        this.cowlPostAttack.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.cowlPostAttack.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.5F);
        this.setRotateAngle(cowlPostAttack, 0.7740535232594852F, 0.7285004297824331F, 0.0F);
        this.scytheHeadPostAttack = new ModelRenderer(this, 0, 32);
        this.scytheHeadPostAttack.setRotationPoint(0.8F, 8.9F, -24.0F);
        this.scytheHeadPostAttack.addBox(0.0F, 0.0F, 0.0F, 16, 16, 0, 0.0F);
        this.setRotateAngle(scytheHeadPostAttack, -1.6235052702051254F, 2.9543188248508017F, -0.27314402793711257F);
        this.scytheHandlePostAttack = new ModelRenderer(this, 37, 32);
        this.scytheHandlePostAttack.setRotationPoint(-4.3F, 9.0F, 6.7F);
        this.scytheHandlePostAttack.addBox(0.0F, 0.0F, 0.0F, 1, 31, 1, 0.0F);
        this.setRotateAngle(scytheHandlePostAttack, 1.5025539530419183F, 2.9595548126067843F, -0.36425021489121656F);
        this.rightLegPostAttack = new ModelRenderer(this, 0, 16);
        this.rightLegPostAttack.setRotationPoint(2.0F, 10.0F, 6.6F);
        this.rightLegPostAttack.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightLegPostAttack, 0.5462880558742251F, 0.5918411493512771F, -0.091106186954104F);
        this.headPostAttack = new ModelRenderer(this, 0, 0);
        this.headPostAttack.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.headPostAttack.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.0F);
        this.setRotateAngle(headPostAttack, 0.7740535232594852F, 0.7285004297824331F, 0.0F);
        this.leftLegPostAttack = new ModelRenderer(this, 0, 16);
        this.leftLegPostAttack.mirror = true;
        this.leftLegPostAttack.setRotationPoint(5.4F, 9.8F, 4.6F);
        this.leftLegPostAttack.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftLegPostAttack, 0.5009094953223726F, 0.6829473363053812F, -0.045553093477052F);
        this.rightArmPostAttack = new ModelRenderer(this, 40, 16);
        this.rightArmPostAttack.setRotationPoint(-5.0F, 1.7F, 3.3F);
        this.rightArmPostAttack.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightArmPostAttack, -1.593485607070823F, 2.5497515042385164F, 0.0F);

        this.cowlBlock = new ModelRenderer(this, 32, 0);
        this.cowlBlock.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.cowlBlock.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.5F);
        this.setRotateAngle(cowlBlock, 0.091106186954104F, 0.0F, 0.0F);
        this.leftLegBlock = new ModelRenderer(this, 0, 16);
        this.leftLegBlock.mirror = true;
        this.leftLegBlock.setRotationPoint(1.9F, 12.0F, 0.0F);
        this.leftLegBlock.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftLegBlock, -0.136659280431156F, 0.045553093477052F, 0.0F);
        this.headBlock = new ModelRenderer(this, 0, 0);
        this.headBlock.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.headBlock.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.0F);
        this.setRotateAngle(headBlock, 0.136659280431156F, 0.0F, 0.0F);
        this.rightArmBlock = new ModelRenderer(this, 40, 16);
        this.rightArmBlock.setRotationPoint(-5.0F, 2.0F, 0.0F);
        this.rightArmBlock.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightArmBlock, -1.2292353921796064F, 0.0F, 1.8668041679331349F);
        this.scytheHandleBlock = new ModelRenderer(this, 36, 32);
        this.scytheHandleBlock.setRotationPoint(-18.5F, -3.7F, -10.1F);
        this.scytheHandleBlock.addBox(0.0F, 0.0F, 0.0F, 1, 31, 1, 0.0F);
        this.setRotateAngle(scytheHandleBlock, 1.2292353921796064F, 1.5481070465189704F, 0.0F);
        this.rightLegBlock = new ModelRenderer(this, 0, 16);
        this.rightLegBlock.setRotationPoint(-1.9F, 12.0F, 0.0F);
        this.rightLegBlock.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightLegBlock, -0.136659280431156F, 0.091106186954104F, 0.0F);
        this.chestBlock = new ModelRenderer(this, 16, 16);
        this.chestBlock.setRotationPoint(0.0F, 0.0F, 1.0F);
        this.chestBlock.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, 0.0F);
        this.setRotateAngle(chestBlock, -0.091106186954104F, 0.091106186954104F, 0.0F);
        this.leftArmBlock = new ModelRenderer(this, 40, 16);
        this.leftArmBlock.mirror = true;
        this.leftArmBlock.setRotationPoint(5.0F, 2.0F, 0.0F);
        this.leftArmBlock.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftArmBlock, -1.5025539530419183F, 0.40980330836826856F, 0.136659280431156F);
        this.scytheHeadBlock = new ModelRenderer(this, 0, 32);
        this.scytheHeadBlock.setRotationPoint(-18.5F, -3.7F, -10.1F);
        this.scytheHeadBlock.addBox(0.0F, 0.0F, 0.5F, 16, 16, 0, 0.0F);
        this.setRotateAngle(scytheHeadBlock, 1.2292353921796064F, 1.5481070465189704F, 0.0F);

        this.rightArmRest = new ModelRenderer(this, 40, 16);
        this.rightArmRest.setRotationPoint(-5.0F, 2.0F, 0.0F);
        this.rightArmRest.addBox(-3.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightArmRest, 0.091106186954104F, -0.045553093477052F, 0.4553564018453205F);
        this.rightLegRest = new ModelRenderer(this, 0, 16);
        this.rightLegRest.setRotationPoint(-1.9F, 12.0F, 0.0F);
        this.rightLegRest.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(rightLegRest, 0.045553093477052F, 0.091106186954104F, 0.0F);
        this.leftArmRest = new ModelRenderer(this, 40, 16);
        this.leftArmRest.mirror = true;
        this.leftArmRest.setRotationPoint(5.0F, 2.0F, 0.0F);
        this.leftArmRest.addBox(-1.0F, -2.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftArmRest, -1.6845917940249266F, -1.5481070465189704F, 0.9560913642424937F);
        this.chestRest = new ModelRenderer(this, 16, 16);
        this.chestRest.setRotationPoint(0.0F, 0.0F, 0.1F);
        this.chestRest.addBox(-4.0F, 0.0F, -2.0F, 8, 12, 4, 0.0F);
        this.setRotateAngle(chestRest, 0.0F, 0.091106186954104F, 0.0F);
        this.leftLegRest = new ModelRenderer(this, 0, 16);
        this.leftLegRest.mirror = true;
        this.leftLegRest.setRotationPoint(1.9F, 12.0F, 0.0F);
        this.leftLegRest.addBox(-2.0F, 0.0F, -2.0F, 4, 12, 4, 0.0F);
        this.setRotateAngle(leftLegRest, 0.045553093477052F, 0.045553093477052F, 0.0F);
        this.headRest = new ModelRenderer(this, 0, 0);
        this.headRest.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.headRest.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.0F);
        this.setRotateAngle(headRest, 1.0927506446736497F, 0.0F, 0.03159045946109736F);
        this.scytheHeadRest = new ModelRenderer(this, 0, 32);
        this.scytheHeadRest.setRotationPoint(-0.1F, -7.3F, -11.7F);
        this.scytheHeadRest.addBox(0.0F, 0.0F, 0.5F, 16, 16, 0, 0.0F);
        this.setRotateAngle(scytheHeadRest, 0.091106186954104F, 1.2747884856566583F, 0.091106186954104F);
        this.cowlRest = new ModelRenderer(this, 32, 0);
        this.cowlRest.setRotationPoint(0.0F, 0.0F, 0.0F);
        this.cowlRest.addBox(-4.0F, -8.0F, -4.0F, 8, 8, 8, 0.5F);
        this.setRotateAngle(cowlRest, 1.0471975511965976F, 0.0F, 0.0F);
        this.scytheHandleRest = new ModelRenderer(this, 36, 32);
        this.scytheHandleRest.setRotationPoint(-1.0F, 7.0F, -10.1F);
        this.scytheHandleRest.addBox(0.5F, -15.5F, 0.5F, 1, 31, 1, 0.0F);
        this.setRotateAngle(scytheHandleRest, 0.091106186954104F, 1.2747884856566583F, 0.091106186954104F);
    }

    @Override
    public void render(Entity entity, float f, float f1, float f2, float f3, float f4, float f5) {
        EntityGrimReaper reaper = (EntityGrimReaper) entity;

        if (reaper.getAttackState() == EnumReaperAttackState.PRE) {
            this.leftLegPreAttack.render(f5);
            this.leftArmPreAttack.render(f5);
            this.rightLegPreAttack.render(f5);
            this.chestPreAttack.render(f5);
            this.cowlPreAttack.render(f5);
            this.headPreAttack.render(f5);
            this.rightArmPreAttack.render(f5);
            this.scytheHandlePreAttack.render(f5);
            this.scytheHeadPreAttack.render(f5);
        } else if (reaper.getAttackState() == EnumReaperAttackState.POST) {
            this.leftLegPostAttack.render(f5);
            this.leftArmPostAttack.render(f5);
            this.rightLegPostAttack.render(f5);
            this.chestPostAttack.render(f5);
            this.cowlPostAttack.render(f5);
            this.headPostAttack.render(f5);
            this.rightArmPostAttack.render(f5);
            this.scytheHandlePostAttack.render(f5);
            this.scytheHeadPostAttack.render(f5);
        } else if (reaper.getAttackState() == EnumReaperAttackState.BLOCK) {
            this.cowlBlock.render(f5);
            this.leftLegBlock.render(f5);
            this.headBlock.render(f5);
            this.rightArmBlock.render(f5);
            this.scytheHandleBlock.render(f5);
            this.rightLegBlock.render(f5);
            this.chestBlock.render(f5);
            this.leftArmBlock.render(f5);
            this.scytheHeadBlock.render(f5);
        } else if (reaper.getAttackState() == EnumReaperAttackState.REST) {

            GL11.glPushMatrix();
            {
                double amt = Math.cos(reaper.getFloatingTicks()) / 4;
                GL11.glTranslated(0.0D, amt, 0.0D);

                this.rightArmRest.render(f5);
                this.rightLegRest.render(f5);
                this.leftArmRest.render(f5);
                this.chestRest.render(f5);
                this.leftLegRest.render(f5);
                this.cowlRest.render(f5);

                GL11.glPushMatrix();
                {
                    double amt2 = Math.cos(reaper.getFloatingTicks()) / 8;
                    GL11.glTranslated(0.0D, amt2, 0.0D);

                    this.scytheHeadRest.render(f5);
                    this.scytheHandleRest.render(f5);
                }
                GL11.glPopMatrix();
            }
            GL11.glPopMatrix();
        } else {
            rightLeg.rotateAngleX = MathHelper.clamp(MathHelper.cos(100F * 0.6662F + 3.141593F) * 2.5F * f1, 0.0F, 1.1F);
            leftLeg.rotateAngleX = MathHelper.clamp(MathHelper.cos(100F * 0.6662F + 3.141593F) * 2.5F * f1, 0.0F, 1.1F);
            rightLeg.rotateAngleX = MathHelper.clamp(MathHelper.cos(100F * 0.6662F + 3.141593F) * 2.5F * f1, 0.0F, 1.1F);
            leftLeg.rotateAngleX = MathHelper.clamp(MathHelper.cos(100F * 0.6662F + 3.141593F) * 2.5F * f1, 0.0F, 1.1F);

            rightLeg.rotateAngleY = 0.0F;
            leftLeg.rotateAngleY = 0.0F;

            this.leftLeg.render(f5);
            this.leftArm.render(f5);
            this.rightLeg.render(f5);
            this.chest.render(f5);
            this.cowl.render(f5);
            this.head.render(f5);
            this.rightArm.render(f5);
        }
    }

    public void setRotateAngle(ModelRenderer modelRenderer, float x, float y, float z) {
        modelRenderer.rotateAngleX = x;
        modelRenderer.rotateAngleY = y;
        modelRenderer.rotateAngleZ = z;
    }
}

================================================
FILE: src/main/java/mca/client/model/ModelVillagerMCA.java
================================================
package mca.client.model;

import mca.enums.EnumGender;
import org.lwjgl.opengl.GL11;

import mca.entity.EntityVillagerMCA;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.model.ModelRenderer;
import net.minecraft.entity.Entity;
import net.minecraft.inventory.EntityEquipmentSlot;
import net.minecraft.item.ItemStack;

public class ModelVillagerMCA extends ModelBiped {
    private ModelRenderer breasts;

    public ModelVillagerMCA() {
        super(0.0F, 0.0F, 64, 64);
        breasts = new ModelRenderer(this, 18, 21);
        breasts.addBox(-3F, 0F, -1F, 6, 3, 3);
        breasts.setRotationPoint(0F, 3.5F, -3F);
        breasts.setTextureSize(64, 64);
        breasts.mirror = true;
    }

    @Override
    public void render(Entity entity, float swing, float swingAmount, float age, float headYaw, float headPitch, float scale) {
        super.render(entity, swing, swingAmount, age, headYaw, headPitch, scale);
        EntityVillagerMCA villager = (EntityVillagerMCA)entity;
        if (EnumGender.byId(villager.get(EntityVillagerMCA.GENDER)) == EnumGender.FEMALE && !villager.isChild() && villager.getItemStackFromSlot(EntityEquipmentSlot.CHEST) == ItemStack.EMPTY) {
            GL11.glPushMatrix();
            GL11.glTranslated(0.005D, -0.05D, -0.28D);
            GL11.glScaled(1.15D, 1.0D, 1.0D);
            GL11.glRotatef(60.0F, 1.0F, 0.0F, 0.0F);
            breasts.render(scale);
            GL11.glPopMatrix();
        }
    }
}

================================================
FILE: src/main/java/mca/client/network/ClientMessageQueue.java
================================================
package mca.client.network;

import mca.core.MCA;
import mca.core.forge.NetMCA;
import mca.entity.EntityVillagerMCA;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;

import java.util.Optional;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;

public class ClientMessageQueue {
    private static ConcurrentLinkedQueue<IMessage> scheduledMessages = new ConcurrentLinkedQueue<>();

    public static void processScheduledMessages() {
        IMessage next = scheduledMessages.poll();

        if (next != null) handle(next);
    }

    public static void add(IMessage msg) {
        scheduledMessages.add(msg);
    }

    private static void handle(IMessage msg) {
        if (msg instanceof NetMCA.CareerResponse) handleCareerId((NetMCA.CareerResponse) msg);
        else if (msg instanceof NetMCA.InventoryResponse) handleInventory((NetMCA.InventoryResponse) msg);
        else MCA.getLog().error("Unexpected message in queue:" + msg.getClass().getName());
    }

    private static void handleCareerId(NetMCA.CareerResponse msg) {
        EntityPlayer player = Minecraft.getMinecraft().player;

        try {
            Optional<EntityVillagerMCA> villager = getVillagerByUUID(player.getEntityWorld(), msg.getEntityUUID());

            if (villager.isPresent()) {
                ObfuscationReflectionHelper.setPrivateValue(EntityVillager.class, villager.get(), msg.getCareerId(), EntityVillagerMCA.VANILLA_CAREER_ID_FIELD_INDEX);
            }
        } catch (ClassCastException e) {
            MCA.getLog().error("Failed to cast entity to villager on career ID update.");
        } catch (Exception e) {
            MCA.getLog().error("Failed to set career ID on villager!", e);
        }
    }

    private static void handleInventory(NetMCA.InventoryResponse msg) {
        EntityPlayer player = Minecraft.getMinecraft().player;
        if (player != null) {
            Optional<EntityVillagerMCA> villager = getVillagerByUUID(player.world, msg.getEntityUUID());
            villager.ifPresent(entityVillagerMCA -> entityVillagerMCA.inventory.readInventoryFromNBT(msg.getInventoryNBT().getTagList("inventory", 10)));
        }
    }

    private static Optional<EntityVillagerMCA> getVillagerByUUID(World world, UUID uuid) {
        try {
            synchronized (world.loadedEntityList) {
                return world.loadedEntityList.stream().filter(e -> e.getUniqueID().equals(uuid)).map(EntityVillagerMCA.class::cast).findFirst();
            }
        } catch (ClassCastException ignored) {
            MCA.getLog().error("Failed to cast entity with UUID " + uuid.toString() + " to a villager!");
        }
        return Optional.empty();
    }
}


================================================
FILE: src/main/java/mca/client/render/RenderGrimReaper.java
================================================
package mca.client.render;

import mca.client.model.ModelGrimReaper;
import mca.entity.EntityGrimReaper;
import net.minecraft.client.renderer.entity.RenderBiped;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;

public class RenderGrimReaper<T extends EntityGrimReaper> extends RenderBiped<T> {
    private static final ResourceLocation TEXTURE = new ResourceLocation("mca:textures/entity/grimreaper.png");

    public RenderGrimReaper(RenderManager manager) {
        super(manager, new ModelGrimReaper(), 0.5F);
    }

    @Override
    public void doRender(T entity, double posX, double posY, double posZ, float angle, float offsetY) {
        super.doRender(entity, posX, posY, posZ, angle, offsetY);
    }

    @Override
    protected void preRenderCallback(T entity, float partialTickTime) {
        super.preRenderCallback(entity, partialTickTime);

        double scale = 1.3D;
        GL11.glScaled(scale, scale, scale);
    }

    @Override
    protected ResourceLocation getEntityTexture(T entity) {
        return TEXTURE;
    }
}

================================================
FILE: src/main/java/mca/client/render/RenderReaperFactory.java
================================================
package mca.client.render;

import mca.entity.EntityGrimReaper;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraftforge.fml.client.registry.IRenderFactory;

public class RenderReaperFactory implements IRenderFactory<EntityGrimReaper> {
    public static final RenderReaperFactory INSTANCE = new RenderReaperFactory();

    @Override
    public Render<? super EntityGrimReaper> createRenderFor(RenderManager manager) {
        return new RenderGrimReaper(manager);
    }
}

================================================
FILE: src/main/java/mca/client/render/RenderVillagerFactory.java
================================================
package mca.client.render;

import mca.entity.EntityVillagerMCA;
import net.minecraft.client.renderer.entity.Render;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraftforge.fml.client.registry.IRenderFactory;

public class RenderVillagerFactory implements IRenderFactory<EntityVillagerMCA> {
    public static final RenderVillagerFactory INSTANCE = new RenderVillagerFactory();

    @Override
    public Render<? super EntityVillagerMCA> createRenderFor(RenderManager manager) {
        return new RenderVillagerMCA(manager);
    }
}

================================================
FILE: src/main/java/mca/client/render/RenderVillagerMCA.java
================================================
package mca.client.render;

import mca.client.model.ModelVillagerMCA;
import mca.entity.EntityVillagerMCA;
import mca.enums.EnumAgeState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.model.ModelBiped;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderBiped;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.entity.layers.LayerBipedArmor;
import net.minecraft.client.renderer.entity.layers.LayerHeldItem;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.ResourceLocation;
import org.lwjgl.opengl.GL11;

public class RenderVillagerMCA<T extends EntityVillagerMCA> extends RenderBiped<EntityVillagerMCA> {
    private static final ResourceLocation gui = new ResourceLocation("mca:textures/gui.png");
    private static final float LABEL_SCALE = 0.027F;

    public RenderVillagerMCA(RenderManager manager) {
        super(manager, new ModelVillagerMCA(), 0.5F);
        this.addLayer(new LayerBipedArmor(this));
        this.addLayer(new LayerHeldItem(this));
    }

    @Override
    protected void preRenderCallback(EntityVillagerMCA villager, float partialTickTime) {
        if (villager.isChild()) {
            float scaleForAge = EnumAgeState.byId(villager.get(EntityVillagerMCA.AGE_STATE)).getScaleForAge();
            GlStateManager.scale(scaleForAge, scaleForAge, scaleForAge);
        }

        if (villager.isRiding()) {
            GlStateManager.translate(0, 0.5, 0);
        }
    }

    @Override
    public void renderName(EntityVillagerMCA entity, double x, double y, double z) {
        super.renderName(entity, x, y ,z);
        if (canRenderName(entity)) {
            if (entity.getHealth() < entity.getMaxHealth()) {
                renderHealth(entity, x, y, z, (int) entity.getHealth(), (int) entity.getMaxHealth());
            }

            if (entity.getCurrentActivity() != null) {
                double d0 = entity.getDistanceSq(this.renderManager.renderViewEntity);
                float f = entity.isSneaking() ? NAME_TAG_RANGE_SNEAK : NAME_TAG_RANGE;
                if (d0 < (double) (f * f)) {
                    this.renderEntityName(entity, x, y - 0.25F, z, "(" + entity.getCurrentActivity() + ")", d0);
                }
            }
        }
    }

    private void renderHealth(EntityVillagerMCA villager, double posX, double posY, double posZ, int currentHealth, int maxHealth) {
        final int redHeartU = 80;
        final int darkHeartU = 96;
        int heartsDrawn = 0;

        float maxHealthF = Math.round((float)maxHealth / 2.0F);
        float currentHealthF = Math.round((float)currentHealth / 2.0F);
        int heartsMax = Math.round((maxHealthF / maxHealthF) * 10.0F);
        int heartsToDraw = Math.round((currentHealthF / maxHealthF) * 10.0F);

        for (int i = 0; i < heartsMax; i++) {
            int heartU = i < heartsToDraw ? redHeartU : darkHeartU;
            heartsDrawn++;

            GL11.glPushMatrix();{
                GL11.glTranslatef((float) posX + 0.0F, (float) posY + villager.height + 1.0F, (float) posZ);
                GL11.glRotatef(-renderManager.playerViewY, 0.0F, 1.0F, 0.0F);
                GL11.glRotatef(renderManager.playerViewX, 1.0F, 0.0F, 0.0F);
                GL11.glScalef(-LABEL_SCALE, -LABEL_SCALE, LABEL_SCALE);
                GL11.glDisable(GL11.GL_LIGHTING);
                GL11.glTranslatef(-2.0F, 2.0F, -2.0F);
                drawTexturedRectangle(gui, (int)posX + (heartsDrawn * 8) - 45, (int)posY - 4, heartU, 0, 16, 16);
            }
            GL11.glPopMatrix();
            GL11.glDepthMask(true);
            GL11.glEnable(GL11.GL_LIGHTING);
        }
    }

    @Override
    protected ResourceLocation getEntityTexture(EntityVillagerMCA villager) {
        return villager.getTextureResourceLocation();
    }

    @Override
    protected boolean canRenderName(EntityVillagerMCA entity) {
        float distance = Minecraft.getMinecraft().player.getDistance(entity);
        return distance < 5F;
    }

    public static void drawTexturedRectangle(ResourceLocation texture, int x, int y, int u, int v, int width, int height)
    {
        Minecraft.getMinecraft().renderEngine.bindTexture(texture);

        float f = 0.00390625F;
        float f1 = 0.00390625F;

        final Tessellator tessellator = Tessellator.getInstance();
        BufferBuilder buffer = tessellator.getBuffer();

        buffer.begin(7, DefaultVertexFormats.POSITION_TEX);
        buffer.pos(x + 0, y + height, 0.0D).tex((u + 0) * f, ((v + height) * f1)).endVertex();
        buffer.pos(x + width, y + height, 0.0D).tex((u + width) * f, ((v + height) * f1)).endVertex();
        buffer.pos(x + width, y + 0,	0.0D).tex((u + width) * f, ((v + 0) * f1)).endVertex();
        buffer.pos(x + 0, y + 0, 0.0D).tex((u + 0) * f, ((v + 0) * f1)).endVertex();
        tessellator.draw();
    }

    @Override
    protected void renderLivingAt(EntityVillagerMCA entityLiving, double x, double y, double z) {
        if (entityLiving.isEntityAlive() && entityLiving.isSleeping()) {
            super.renderLivingAt(entityLiving, x + (double)entityLiving.renderOffsetX, y + (double)entityLiving.renderOffsetY, z + (double)entityLiving.renderOffsetZ);
        } else {
            super.renderLivingAt(entityLiving, x, y, z);
        }
    }

    @Override
    protected void applyRotations(EntityVillagerMCA entityLiving, float p_77043_2_, float rotationYaw, float partialTicks) {
        if (entityLiving.isSleeping()) {
            GlStateManager.rotate(entityLiving.getBedOrientationInDegrees(), 0.0F, 1.0F, 0.0F);
            GlStateManager.rotate(this.getDeathMaxRotation(entityLiving), 0.0F, 0.0F, 1.0F);
            GlStateManager.rotate(270.0F, 0.0F, 1.0F, 0.0F);
            rotationYaw = 180.0f;
        }
        super.applyRotations(entityLiving, p_77043_2_, rotationYaw, partialTicks);
    }
}


================================================
FILE: src/main/java/mca/command/CommandAdminMCA.java
================================================
package mca.command;

import com.google.common.base.Optional;
import mca.core.Constants;
import mca.core.MCA;
import mca.core.minecraft.ItemsMCA;
import mca.entity.EntityGrimReaper;
import mca.entity.EntityVillagerMCA;
import mca.entity.data.PlayerSaveData;
import mca.items.ItemBaby;
import mca.util.Util;
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.WrongUsageException;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;

import java.util.Arrays;
import java.util.UUID;

public class CommandAdminMCA extends CommandBase {
    @Override
    public String getName() {
        return "mca-admin";
    }

    @Override
    public String getUsage(ICommandSender commandSender) {
        return "/mca-admin <subcommand> <arguments>";
    }

    @Override
    public void execute(MinecraftServer server, ICommandSender commandSender, String[] input) throws CommandException {
        try {
            if (!MCA.getConfig().enableAdminCommands) {
                sendMessage(commandSender, "MCA admin commands have been disabled by the server administrator.");
                return;
            }

            if (input.length == 0) {
                throw new WrongUsageException("");
            }

            final EntityPlayer player = (EntityPlayer) commandSender;
            String subcommand = input[0].toLowerCase();
            String[] arguments = Arrays.copyOfRange(input, 1, input.length);
            MCA.getLog().info(player.getName() + " entered debug command " + Arrays.toString(input));

            switch (subcommand) {
                case "help": displayHelp(commandSender); break;
                case "ffh": forceFullHearts(player); break;
                case "fbg": forceBabyGrow(player); break;
                case "fcg": forceChildGrow(player); break;
                case "clv": clearLoadedVillagers(player);break;
                case "inh": incrementHearts(player); break;
                case "deh": decrementHearts(player); break;
                case "sgr": spawnGrimReaper(player); break;
                case "kgr": killGrimReaper(player); break;
                case "dpd": dumpPlayerData(player); break;
                case "rvd": resetVillagerData(player, arguments); break;
                case "rpd": resetPlayerData(player, arguments); break;
                case "cve": clearVillagerEditors(player); break;
                default: throw new WrongUsageException("");
            }
        } catch (ClassCastException e) {
            throw new CommandException("MCA commands cannot be used through rcon.");
        } catch (WrongUsageException e) {
            throw new CommandException("Your command was invalid or improperly formatted. Usage: " + getUsage(commandSender));
        }
    }

    private void forceFullHearts(EntityPlayer player) {
        for (Entity entity : player.world.loadedEntityList) {
            if (entity instanceof EntityVillagerMCA) {
                EntityVillagerMCA villager = (EntityVillagerMCA) entity;
                villager.getPlayerHistoryFor(player.getUniqueID()).setHearts(100);
            }
        }
        sendMessage(player, Constants.Color.GREEN + "Forced full hearts on all villagers.");
    }

    private void forceBabyGrow(EntityPlayer player) {
        for (ItemStack stack : player.inventory.mainInventory) {
            if (stack.getItem() instanceof ItemBaby) {
                stack.getTagCompound().setInteger("age", MCA.getConfig().babyGrowUpTime);
            }
        }
        sendMessage(player, Constants.Color.GREEN + "Forced any held babies to grow up age.");
    }

    private void forceChildGrow(EntityPlayer player) {
        player.world.loadedEntityList.stream()
                .filter(e -> e instanceof EntityVillagerMCA && ((EntityVillagerMCA)e).isChild())
                .forEach(e -> ((EntityVillagerMCA) e).addGrowth(999999));
        sendMessage(player, Constants.Color.GREEN + "Forced any children to grow to adults.");
    }

    private void clearLoadedVillagers(EntityPlayer player) {
        int n = 0;
        for (Entity entity : player.world.loadedEntityList) {
            if (entity instanceof EntityVillagerMCA) {
                entity.setDead();
                ++n;
            }
        }
        sendMessage(player, Constants.Color.GREEN + "Cleared " + n + " villagers from the world.");
    }

    private void incrementHearts(EntityPlayer player) {
        for (Entity entity : player.world.loadedEntityList) {
            if (entity instanceof EntityVillagerMCA) {
                EntityVillagerMCA villager = (EntityVillagerMCA) entity;
                villager.getPlayerHistoryFor(player.getUniqueID()).changeHearts(10);
            }
        }
        sendMessage(player, Constants.Color.GREEN + "Increased hearts for all villagers by 10.");
    }

    private void decrementHearts(EntityPlayer player) {
        for (Entity entity : player.world.loadedEntityList) {
            if (entity instanceof EntityVillagerMCA) {
                EntityVillagerMCA villager = (EntityVillagerMCA) entity;
                villager.getPlayerHistoryFor(player.getUniqueID()).changeHearts(-10);
            }
        }
        sendMessage(player, Constants.Color.GREEN + "Decreased hearts for all villagers by 10.");
    }

    private void spawnGrimReaper(EntityPlayer player) {
        EntityGrimReaper reaper = new EntityGrimReaper(player.world);
        reaper.setPosition(player.posX, player.posY, player.posZ);
        player.world.spawnEntity(reaper);
    }

    private void killGrimReaper(EntityPlayer player) {
        player.world.loadedEntityList.stream().filter((e) -> e instanceof EntityGrimReaper).forEach((e) -> e.setDead());
    }

    private void dumpPlayerData(EntityPlayer player) {
        PlayerSaveData.get(player).dump(player);
    }

    private void resetVillagerData(EntityPlayer sender, String[] arguments) {
        Optional<EntityVillagerMCA> target = Util.getEntityByUUID(sender.world, UUID.fromString(arguments[0]), EntityVillagerMCA.class);
        if (!target.isPresent()) {
            sendMessage(sender, "Target villager was not found.");
        } else {
            target.get().reset();
            sendMessage(sender, target.get().getDisplayName().getUnformattedText() + " has been reset successfully.");
        }
    }

    private void resetPlayerData(EntityPlayer sender, String[] arguments) {
        Optional<Entity> target = com.google.common.base.Optional.fromJavaUtil(sender.world.loadedEntityList.stream()
                .filter(e -> e instanceof EntityPlayer && e.getName().equals(arguments[0]))
                .findFirst());
        if (!target.isPresent()) {
            sendMessage(sender, "Player not found on the server.");
        } else {
            PlayerSaveData.get((EntityPlayer)target.get()).reset();
            sendMessage(sender, "Player data for " + target.get().getName() + " has been reset successfully.");
            sendMessage(target.get(), "Your player data has been reset by " + sender.getName() + ".");
        }
    }

    private void clearVillagerEditors(EntityPlayer sender) {
        ItemStack editorStack = new ItemStack(ItemsMCA.VILLAGER_EDITOR);
        sender.world.playerEntities.stream().filter(p -> p.inventory.hasItemStack(editorStack)).forEach(p -> {
            int i = 0;
            while (i < p.inventory.getSizeInventory() - 1) {
                if (p.inventory.getStackInSlot(i).getItem() == ItemsMCA.VILLAGER_EDITOR) {
                    p.inventory.setInventorySlotContents(i, ItemStack.EMPTY);
                }
                i++;
            }
        });
        sendMessage(sender, "All villager editors cleared from inventories.");
    }

    @Override
    public int getRequiredPermissionLevel() {
        return 4;
    }

    private void sendMessage(ICommandSender commandSender, String message) {
        commandSender.sendMessage(new TextComponentString(Constants.Color.GOLD + "[MCA] " + Constants.Format.RESET + message));
    }

    private void sendMessage(ICommandSender commandSender, String message, boolean noPrefix) {
        if (noPrefix) {
            commandSender.sendMessage(new TextComponentString(message));
        } else {
            sendMessage(commandSender, message);
        }
    }

    private void displayHelp(ICommandSender commandSender) {
        sendMessage(commandSender, Constants.Color.DARKRED + "--- " + Constants.Color.GOLD + "OP COMMANDS" + Constants.Color.DARKRED + " ---", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin ffh " + Constants.Color.GOLD + " - Force all hearts on all villagers.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin fbg " + Constants.Color.GOLD + " - Force your baby to grow up.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin fcg " + Constants.Color.GOLD + " - Force nearby children to grow.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin clv " + Constants.Color.GOLD + " - Clear all loaded villagers. " + Constants.Color.RED + "(IRREVERSABLE)", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin inh " + Constants.Color.GOLD + " - Increase hearts by 10.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin deh " + Constants.Color.GOLD + " - Decrease hearts by 10.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin kgr " + Constants.Color.GOLD + " - Kill all Grim Reapers in the world.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin dpd " + Constants.Color.GOLD + " - Dumps player data to chat.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin rvd <UUID>" + Constants.Color.GOLD + " - Resets the given villager.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin rpd <PlayerName>" + Constants.Color.GOLD + " - Resets the given player's MCA data.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin cve" + Constants.Color.GOLD + " - Remove all villager editors from the game.", true);

        sendMessage(commandSender, Constants.Color.DARKRED + "--- " + Constants.Color.GOLD + "GLOBAL COMMANDS" + Constants.Color.DARKRED + " ---", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin help " + Constants.Color.GOLD + " - Shows this list of commands.", true);
    }
}


================================================
FILE: src/main/java/mca/command/CommandMCA.java
================================================
package mca.command;

import mca.core.Constants;
import mca.core.MCA;
import mca.core.MCAServer;
import net.minecraft.command.CommandBase;
import net.minecraft.command.CommandException;
import net.minecraft.command.ICommandSender;
import net.minecraft.command.WrongUsageException;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.text.TextComponentString;

import java.util.Arrays;

public class CommandMCA extends CommandBase {
    @Override
    public String getName() {
        return "mca";
    }

    @Override
    public String getUsage(ICommandSender commandSender) {
        return "/mca <subcommand> <arguments>";
    }

    @Override
    public void execute(MinecraftServer server, ICommandSender commandSender, String[] input) throws CommandException {
        try {
            if (!MCA.getConfig().allowPlayerMarriage) {
                sendMessage(commandSender, "MCA commands have been disabled by the server administrator.");
                return;
            }

            if (input.length == 0) {
                throw new WrongUsageException("");
            }

            final EntityPlayer player = (EntityPlayer) commandSender;
            String subcommand = input[0].toLowerCase();
            String[] arguments = Arrays.copyOfRange(input, 1, input.length);
            MCA.getLog().info(player.getName() + " entered command " + Arrays.toString(input));

            switch (subcommand) {
                case "help":
                    displayHelp(commandSender);
                    break;
                case "propose":
                    EntityPlayer target = player.world.getPlayerEntityByName(arguments[0]);
                    if (target != null) {
                        MCAServer.get().sendProposal(player, target);
                    } else {
                        player.sendMessage(new TextComponentString("Player not found on the server."));
                    }
                    break;
                case "accept":
                    target = player.world.getPlayerEntityByName(arguments[0]);
                    if (target != null) {
                        MCAServer.get().acceptProposal(player, target);
                    } else {
                        player.sendMessage(new TextComponentString("Player not found on the server."));
                    }
                    break;
                case "proposals":
                    MCAServer.get().listProposals(player);
                    break;
                case "procreate":
                    MCAServer.get().procreate(player);
                    break;
                case "separate":
                    MCAServer.get().endMarriage(player);
                    break;
                case "reject":
                    target = player.world.getPlayerEntityByName(arguments[0]);
                    if (target != null) {
                        MCAServer.get().rejectProposal(player, target);
                    } else {
                        player.sendMessage(new TextComponentString("Player not found on the server."));
                    }
                    break;
                default:
                    throw new WrongUsageException("");
            }
        } catch (ClassCastException e) {
            throw new CommandException("MCA commands cannot be used through rcon.");
        } catch (WrongUsageException e) {
            throw new CommandException("Your command was invalid or improperly formatted. Usage: " + getUsage(commandSender));
        }
    }

    @Override
    public int getRequiredPermissionLevel() {
        return 0;
    }

    private void sendMessage(ICommandSender commandSender, String message) {
        commandSender.sendMessage(new TextComponentString(Constants.Color.GOLD + "[MCA] " + Constants.Format.RESET + message));
    }

    private void sendMessage(ICommandSender commandSender, String message, boolean noPrefix) {
        if (noPrefix) {
            commandSender.sendMessage(new TextComponentString(message));
        } else {
            sendMessage(commandSender, message);
        }
    }

    private void displayHelp(ICommandSender commandSender) {
        sendMessage(commandSender, Constants.Color.DARKRED + "--- " + Constants.Color.GOLD + "PLAYER COMMANDS" + Constants.Color.DARKRED + " ---", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca propose <PlayerName>" + Constants.Color.GOLD + " - Proposes marriage to the given player.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca proposals " + Constants.Color.GOLD + " - Shows all active proposals.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca accept <PlayerName>" + Constants.Color.GOLD + " - Accepts the player's marriage request.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca reject <PlayerName>" + Constants.Color.GOLD + " - Rejects the player's marriage request.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca procreate " + Constants.Color.GOLD + " - Starts procreation.", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca separate " + Constants.Color.GOLD + " - Ends your marriage.", true);
        sendMessage(commandSender, Constants.Color.DARKRED + "--- " + Constants.Color.GOLD + "GLOBAL COMMANDS" + Constants.Color.DARKRED + " ---", true);
        sendMessage(commandSender, Constants.Color.WHITE + " /mca help " + Constants.Color.GOLD + " - Shows this list of commands.", true);
    }
}


================================================
FILE: src/main/java/mca/core/Config.java
================================================
package mca.core;

import net.minecraftforge.common.config.ConfigElement;
import net.minecraftforge.common.config.Configuration;
import net.minecraftforge.fml.client.config.IConfigElement;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

public final class Config implements Serializable {
    private transient final Configuration config;

    public boolean overwriteOriginalVillagers;
    public boolean enableDiminishingReturns;
    public boolean enableInfection;
    public int infectionChance;
    public boolean allowGrimReaper;
    public int guardSpawnRate;
    public int chanceToHaveTwins;
    public int marriageHeartsRequirement;
    public int roseGoldSpawnWeight;
    public int babyGrowUpTime;
    public int childGrowUpTime;
    public int villagerSpawnerCap;
    public int villagerSpawnerRateMinutes;
    public int villagerMaxHealth;
    public boolean allowTrading;
    public boolean logVillagerDeaths;
    public boolean enableRevivals;
    public String villagerChatPrefix;
    public boolean allowPlayerMarriage;
    public boolean enableAdminCommands;
    public boolean allowCrashReporting;
    public boolean allowUpdateChecking;
    public boolean allowRoseGoldGeneration;

    public Config(FMLPreInitializationEvent event) {
        config = new Configuration(event.getSuggestedConfigurationFile());
        addConfigValues();
    }

    private void addConfigValues() {
        overwriteOriginalVillagers = config.get("General", "Overwrite Original Villagers?", true, "Should original villagers be overwritten by MCA villagers?").getBoolean();
        enableDiminishingReturns = config.get("General", "Enable Interaction Fatigue?", true, "Should interactions yield diminishing returns over time?").getBoolean();
        enableInfection = config.get("General", "Enable Zombie Infection?", true, "Should zombies be able to infect villagers?").getBoolean();
        infectionChance = config.get("General", "Chance of Infection", 5, "Chance that a villager will be infected on hit from a zombie. Default is 5 for 5%.").getInt();
        allowGrimReaper = config.get("General", "Allow Grim Reaper?", true, "Should the Grim Reaper boss be enabled?").getBoolean();
        guardSpawnRate = config.get("General", "Guard Spawn Rate", 6, "How many villagers that should be in a village before a guard spawns.").getInt();
        chanceToHaveTwins = config.get("General", "Chance to Have Twins", 2, "Chance that you will have twins. Default is 2 for 2%.").getInt();
        marriageHeartsRequirement = config.get("General", "Marriage Hearts Requirement", 100, "Number of hearts required to get married.").getInt();
        roseGoldSpawnWeight = config.get("General", "Rose Gold Spawn Weight", 6, "Spawn weights for Rose Gold").getInt();
        babyGrowUpTime = config.get("General", "Baby Grow Up Time (Minutes)", 30, "Minutes it takes for a baby to be ready to grow up.").getInt();
        childGrowUpTime = config.get("General", "Child Grow Up Time (Minutes)", 60, "Minutes it takes for a child to grow into an adult.").getInt();
        villagerSpawnerCap = config.get("General", "Villager Spawner Cap", 5, "Maximum number of villagers that a spawner will create in the area before it stops.").getInt();
        villagerSpawnerRateMinutes = config.get("General", "Villager Spawner Rate", 30, "The spawner will spawn 1 villager per this many minutes.").getInt();
        allowTrading = config.get("General", "Enable Trading?", true, "Is trading with villagers enabled?").getBoolean();
        logVillagerDeaths = config.get("General", "Log Villager Deaths?", true, "Should villager deaths be logged?").getBoolean();
        enableRevivals = config.get("General", "Enable Revivals?", true, "Should reviving dead villagers be enabled?").getBoolean();
        villagerChatPrefix = config.get("General", "Villager Chat Prefix", "", "Formatting prefix used for all chat with villagers.").getString();
        allowPlayerMarriage = config.get("General", "Allow Player Marriage?", true, "Enables or disables player marriage.").getBoolean();
        enableAdminCommands = config.get("General", "Enable Admin Commands?", true, "Enables or disables MCA admin commands for ops.").getBoolean();
        allowCrashReporting = config.get("General", "Allow Crash Reporting?", true, "If enabled, sends crash reports to MCA developers.").getBoolean();
        allowUpdateChecking = config.get("General", "Allow Update Checking?", true, "If enabled, notifies you when an update to MCA is available.").getBoolean();
        allowRoseGoldGeneration = config.get("General", "Allow Rose Gold World Generation", true, "If enabled, generates rose gold in your world. If disabled, generates stone instead.").getBoolean();
        villagerMaxHealth = config.get("General", "Villager Max Health", 20, "Each villager's maximum health. 1 point equals 1 heart.").getInt();
        config.save();
    }

    public Configuration getInstance() {
        return config;
    }

    public List<IConfigElement> getCategories() {
        List<IConfigElement> elements = new ArrayList<>();

        for (String s : config.getCategoryNames()) {
            if (s.equals("server")) continue;

            IConfigElement element = new ConfigElement(config.getCategory(s));
            elements.addAll(element.getChildElements());
        }

        return elements;
    }
}

================================================
FILE: src/main/java/mca/core/Constants.java
================================================
package mca.core;

import java.util.UUID;

public class Constants {
    public static final int GUI_ID_INTERACT = 1;
    public static final int GUI_ID_NAMEBABY = 2;
    public static final int GUI_ID_INVENTORY = 3;
    public static final int GUI_ID_STAFFOFLIFE = 4;
    public static final int GUI_ID_VILLAGEREDITOR = 5;
    public static final int GUI_ID_GUIDEBOOK = 6;
    public static final int GUI_ID_WHISTLE = 7;
    public static final UUID ZERO_UUID = new UUID(0, 0);
    private static final String SECTION_SIGN = "\u00a7";

    public static final int GUI_SCREEN_BUTTON_LIST_FIELD_INDEX = 7;

    /**
     * All possible font colors
     */
    public final class Color {
        public static final String BLACK = SECTION_SIGN + "0";
        public static final String DARKBLUE = SECTION_SIGN + "1";
        public static final String DARKGREEN = SECTION_SIGN + "2";
        public static final String DARKAQUA = SECTION_SIGN + "3";
        public static final String DARKRED = SECTION_SIGN + "4";
        public static final String PURPLE = SECTION_SIGN + "5";
        public static final String GOLD = SECTION_SIGN + "6";
        public static final String GRAY = SECTION_SIGN + "7";
        public static final String DARKGRAY = SECTION_SIGN + "8";
        public static final String BLUE = SECTION_SIGN + "9";
        public static final String GREEN = SECTION_SIGN + "A";
        public static final String AQUA = SECTION_SIGN + "B";
        public static final String RED = SECTION_SIGN + "C";
        public static final String LIGHTPURPLE = SECTION_SIGN + "D";
        public static final String YELLOW = SECTION_SIGN + "E";
        public static final String WHITE = SECTION_SIGN + "F";
    }

    /**
     * All possible font formats.
     */
    public final class Format {
        public static final String OBFUSCATED = SECTION_SIGN + "k";
        public static final String BOLD = SECTION_SIGN + "l";
        public static final String STRIKE = SECTION_SIGN + "m";
        public static final String UNDERLINE = SECTION_SIGN + "n";
        public static final String ITALIC = SECTION_SIGN + "o";
        public static final String RESET = SECTION_SIGN + "r";
    }
}


================================================
FILE: src/main/java/mca/core/Localizer.java
================================================
package mca.core;

import com.google.common.base.Charsets;
import net.minecraft.util.StringUtils;
import org.apache.commons.io.IOUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

public class Localizer {
    private Map<String, String> localizerMap = new HashMap<>();
    private static final ArrayList<String> EMPTY_LIST = new ArrayList<>();

    public Localizer() {
        InputStream inStream = StringUtils.class.getResourceAsStream("/assets/mca/lang/en_us.lang");

        try {
            List<String> lines = IOUtils.readLines(inStream, Charsets.UTF_8);

            for (String line : lines) {
                if (line.startsWith("#") || line.isEmpty()) {
                    continue;
                }

                String[] split = line.split("\\=");
                String key = split[0];
                String value = split[1];

                localizerMap.put(key, value);
            }
        } catch (IOException e) {
            MCA.getLog().error("Error initializing localizer: " + e);
        }
    }

    public String localize(String key, String... vars) {
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, vars);
        return localize(key, vars != null ? list : EMPTY_LIST);
    }

    public String localize(String key, ArrayList<String> vars) {
        String result = localizerMap.getOrDefault(key, key);
        if (result.equals(key)) {
            List<String> responses = localizerMap.entrySet().stream().filter(entry -> entry.getKey().contains(key)).map(Map.Entry::getValue).collect(Collectors.toList());
            if (responses.size() > 0) result = responses.get(new Random().nextInt(responses.size()));
        }

        return parseVars(result, vars).replaceAll("\\\\", "");
    }

    private String parseVars(String str, ArrayList<String> vars) {
        int index = 1;
        str = str.replaceAll("%Supporter%", MCA.getInstance().getRandomSupporter());

        String varString = "%v" + index + "%";
        while (str.contains("%v") && index < 10) { // signature of a var being present
            try {
                str = str.replaceAll(varString, vars.get(index - 1));
            } catch (IndexOutOfBoundsException e) {
                str = str.replaceAll(varString, "");
                MCA.getLog().warn("Failed to replace variable in localized string: " + str);
            } finally {
                index++;
                varString = "%v" + index + "%";
            }
        }

        return str;
    }
}


================================================
FILE: src/main/java/mca/core/MCA.java
================================================
package mca.core;

import com.google.gson.Gson;
import mca.api.API;
import mca.command.CommandAdminMCA;
import mca.command.CommandMCA;
import mca.core.forge.EventHooks;
import mca.core.forge.GuiHandler;
import mca.core.forge.NetMCA;
import mca.core.forge.ServerProxy;
import mca.core.minecraft.ItemsMCA;
import mca.core.minecraft.ProfessionsMCA;
import mca.core.minecraft.RoseGoldOreGenerator;
import mca.entity.EntityGrimReaper;
import mca.entity.EntityVillagerMCA;
import mca.enums.EnumGender;
import mca.util.Util;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventHandler;
import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.*;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.registry.EntityRegistry;
import net.minecraftforge.fml.common.registry.GameRegistry;
import org.apache.commons.io.FileUtils;
import org.apache.logging.log4j.Logger;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.*;

@Mod(modid = MCA.MODID, name = MCA.NAME, version = MCA.VERSION, guiFactory = "mca.client.MCAGuiFactory")
public class MCA {
    public static final String MODID = "mca";
    public static final String NAME = "Minecraft Comes Alive";
    public static final String VERSION = "6.0.1";
    @SidedProxy(clientSide = "mca.core.forge.ClientProxy", serverSide = "mca.core.forge.ServerProxy")
    public static ServerProxy proxy;
    public static CreativeTabs creativeTab;
    @Mod.Instance
    private static MCA instance;
    private static Logger logger;
    private static Localizer localizer;
    private static Config config;
    private static long startupTimestamp;
    public static String latestVersion = "";
    public static boolean updateAvailable = false;
    public String[] supporters = new String[0];

    public static Logger getLog() {
        return logger;
    }

    public static MCA getInstance() {
        return instance;
    }

    public static Localizer getLocalizer() {
        return localizer;
    }

    public static Config getConfig() {
        return config;
    }

    public static long getStartupTimestamp() {
        return startupTimestamp;
    }

    @EventHandler
    public void preInit(FMLPreInitializationEvent event) {
        startupTimestamp = new Date().getTime();
        instance = this;
        logger = event.getModLog();
        proxy.registerEntityRenderers();
        localizer = new Localizer();
        config = new Config(event);
        creativeTab = new CreativeTabs("MCA") {
            @Override
            public ItemStack getTabIconItem() {
                return new ItemStack(ItemsMCA.ENGAGEMENT_RING);
            }
        };
        MinecraftForge.EVENT_BUS.register(new EventHooks());
        NetworkRegistry.INSTANCE.registerGuiHandler(this, new GuiHandler());
        NetMCA.registerMessages();

        if (MCA.getConfig().allowUpdateChecking) {
            latestVersion = Util.httpGet("https://minecraftcomesalive.com/api/latest");
            if (!latestVersion.equals(VERSION) && !latestVersion.equals("")) {
                updateAvailable = true;
                MCA.getLog().warn("An update for Minecraft Comes Alive is available: v" + latestVersion);
            }
        }

        supporters = Util.httpGet("https://minecraftcomesalive.com/api/supporters").split(",");
        MCA.getLog().info("Loaded " + supporters.length + " supporters.");
    }

    @EventHandler
    public void init(FMLInitializationEvent event) {
        GameRegistry.registerWorldGenerator(new RoseGoldOreGenerator(), MCA.getConfig().roseGoldSpawnWeight);
        EntityRegistry.registerModEntity(new ResourceLocation(MODID, "EntityVillagerMCA"), EntityVillagerMCA.class, EntityVillagerMCA.class.getSimpleName(), 1120, this, 50, 2, true);
        EntityRegistry.registerModEntity(new ResourceLocation(MODID, "GrimReaperMCA"), EntityGrimReaper.class, EntityGrimReaper.class.getSimpleName(), 1121, this, 50, 2, true);
        ProfessionsMCA.registerCareers();

        proxy.registerModelMeshers();
        ItemsMCA.assignCreativeTabs();
    }

    @EventHandler
    public void postInit(FMLPostInitializationEvent event) {
        API.init();
    }

    @EventHandler
    public void serverStarting(FMLServerStartingEvent event) {
        event.registerServerCommand(new CommandMCA());
        event.registerServerCommand(new CommandAdminMCA());
    }

    @EventHandler
    public void serverStopping(FMLServerStoppingEvent event) {
        checkForCrashReports();
    }

    public String getRandomSupporter() {
        if (supporters.length > 0) {
            return supporters[new Random().nextInt(supporters.length)];
        } else {
            return API.getRandomName(EnumGender.getRandom());
        }
    }

    public void checkForCrashReports() {
        if (MCA.getConfig().allowCrashReporting) {
            File crashReportsFolder = new File(System.getProperty("user.dir") + "/crash-reports/");
            File[] crashReportFiles = crashReportsFolder.listFiles(File::isFile);
            try {
                if (crashReportFiles != null) {
                    Optional<File> newestFile = Arrays.stream(crashReportFiles).max(Comparator.comparingLong(File::lastModified));
                    if (newestFile.isPresent() && newestFile.get().lastModified() > startupTimestamp) {
                        // Raw Java for sending the POST request as the HttpClient from Apache libs is not present on servers.
                        MCA.getLog().warn("Crash detected! Attempting to upload report...");
                        Map<String, String> payload = new HashMap<>();
                        payload.put("minecraft_version", FMLCommonHandler.instance().getMinecraftServerInstance().getMinecraftVersion());
                        payload.put("operating_system", System.getProperty("os.name") + " (" + System.getProperty("os.arch") + ") version " + System.getProperty("os.version"));
                        payload.put("java_version", System.getProperty("java.version") + ", " + System.getProperty("java.vendor"));
                        payload.put("mod_version", MCA.VERSION);
                        payload.put("body", FileUtils.readFileToString(newestFile.get(), "UTF-8"));

                        byte[] out = new Gson().toJson(payload).getBytes(StandardCharsets.UTF_8);
                        URL url = new URL("http://minecraftcomesalive.com/api/crash-reports");
                        URLConnection con = url.openConnection();
                        HttpURLConnection http = (HttpURLConnection)con;
                        http.setRequestMethod("POST");
                        http.setDoOutput(true);
                        http.setFixedLengthStreamingMode(out.length);
                        http.setRequestProperty("Content-Type", "application/json; charset=UTF-8");
                        http.setRequestProperty("User-Agent", "Minecraft Client " + FMLCommonHandler.instance().getMinecraftServerInstance().getMinecraftVersion());
                        http.connect();
                        OutputStream os = http.getOutputStream();
                        os.write(out);
                        os.flush();
                        os.close();
                        if (http.getResponseCode() != 200) {
                            MCA.getLog().error("Failed to submit crash report. Non-OK response code returned: " + http.getResponseCode());
                        } else {
                            MCA.getLog().warn("Crash report submitted successfully.");
                        }
                    }
                }
            } catch (IOException e) {
                MCA.getLog().error("An unexpected error occurred while attempting to submit the crash report.", e);
            }
        }
    }
}


================================================
FILE: src/main/java/mca/core/MCAServer.java
================================================
package mca.core;

import mca.core.minecraft.ItemsMCA;
import mca.core.minecraft.VillageHelper;
import mca.entity.EntityGrimReaper;
import mca.entity.EntityVillagerMCA;
import mca.entity.data.PlayerSaveData;
import net.minecraft.entity.Entity;
import net.minecraft.entity.effect.EntityLightningBolt;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.FMLCommonHandler;

import java.util.*;

public class MCAServer {
    private static MCAServer instance;
    // Maps a player's UUID to a list of UUIDs that have proposed to them with /mca propose
    private static Map<UUID, List<UUID>> proposals;
    // List of UUIDs that initiated procreation mapped to the time the request expires.
    private static Map<UUID, Long> procreateMap;
    private int serverTicks = 0;
    private int reaperSummonTicks = 0;
    private BlockPos reaperSpawnPos = BlockPos.ORIGIN;
    private World reaperSpawnWorld = null;

    private MCAServer() {
        proposals = new HashMap<>();
        procreateMap = new HashMap<>();
    }

    public static MCAServer get() {
        if (instance == null) {
            instance = new MCAServer();
        }
        return instance;
    }

    public void tick() {
        serverTicks++;

        if (serverTicks >= 100) {
            World overworld = FMLCommonHandler.instance().getMinecraftServerInstance().getWorld(0);
            VillageHelper.tick(overworld);
            serverTicks = 0;
        }

        if (reaperSummonTicks > 0) {
            reaperSummonTicks--;
            if (reaperSummonTicks % 20 == 0) { // every second
                EntityLightningBolt lightningBolt = new EntityLightningBolt(reaperSpawnWorld, reaperSpawnPos.getX(), reaperSpawnPos.getY(), reaperSpawnPos.getZ(), false);
                reaperSpawnWorld.addWeatherEffect(lightningBolt);
            }

            if (reaperSummonTicks == 0) { // when counter reaches 0
                EntityGrimReaper reaper = new EntityGrimReaper(reaperSpawnWorld);
                reaper.setPosition(reaperSpawnPos.getX(), reaperSpawnPos.getY(), reaperSpawnPos.getZ());
                reaperSpawnWorld.spawnEntity(reaper);
            }
        }

        // Collect all expired procreate requests and remove them.
        List<UUID> removals = new ArrayList<>();
        procreateMap.keySet().stream()
                .filter((k) -> procreateMap.get(k) < System.currentTimeMillis())
                .forEach(removals::add);
        removals.forEach(procreateMap::remove);
    }

    /**
     * Returns true if receiver has a proposal from sender.
     *
     * @param sender   Command sender
     * @param receiver Player whose name was entered by the sender
     * @return boolean
     */
    private boolean hasProposalFrom(EntityPlayer sender, EntityPlayer receiver) {
        return getProposalsFor(receiver).contains(sender.getUniqueID());
    }

    /**
     * Returns all proposals for the provided player
     *
     * @param player Player whose proposals should be returned.
     * @return List<UUID>
     */
    private List<UUID> getProposalsFor(EntityPlayer player) {
        return proposals.getOrDefault(player.getUniqueID(), new ArrayList<>());
    }

    /**
     * Removes the provided proposer from the target's list of proposals.
     *
     * @param target   Target player who's proposal list will be modified.
     * @param proposer The proposer to the target player.
     */
    private void removeProposalFor(EntityPlayer target, EntityPlayer proposer) {
        List<UUID> list = getProposalsFor(target);
        list.remove(proposer.getUniqueID());
        proposals.put(target.getUniqueID(), list);
    }

    /**
     * Lists all proposals for the given player.
     *
     * @param sender Player whose active proposals will be listed.
     */
    public void listProposals(EntityPlayer sender) {
        List<UUID> proposals = getProposalsFor(sender);

        if (proposals.size() == 0) {
            infoMessage(sender, "You have no active proposals.");
        } else {
            infoMessage(sender, "You have active proposals from: ");
        }

        // Send the name of all online players to the command sender.
        proposals.forEach((uuid -> {
            EntityPlayer player = sender.world.getPlayerEntityByUUID(uuid);
            if (player != null) {
                infoMessage(sender, "- " + player.getName());
            }
        }));
    }

    /**
     * Sends a proposal from the sender to the receiver.
     *
     * @param sender   The player sending the proposal.
     * @param receiver The player being proposed to.
     */
    public void sendProposal(EntityPlayer sender, EntityPlayer receiver) {
        // Ensure the sender isn't already married.
        if (PlayerSaveData.get(sender).isMarriedOrEngaged()) {
            failMessage(sender, "You cannot send a proposal since you are already married or engaged.");
            return;
        }

        // Ensure the sender isn't himself.
        if (sender == receiver) {
            failMessage(sender, "You cannot propose to yourself.");
            return;
        }

        // Ensure the receiver hasn't already been proposed to by this player.
        if (hasProposalFrom(sender, receiver)) {
            failMessage(sender, "You have already sent a proposal to " + receiver.getName());
        } else {
            // Send the proposal messages.
            successMessage(sender, "Your proposal to " + receiver.getName() + " has been sent!");
            infoMessage(receiver, sender.getName() + " has proposed marriage. To accept, type /mca accept " + sender.getName());

            // Add the proposal to the receiver's proposal list.
            List<UUID> list = getProposalsFor(receiver);
            list.add(sender.getUniqueID());
            proposals.put(receiver.getUniqueID(), list);
        }
    }

    /**
     * Rejects and removes a proposal from the receiver to the sender.
     *
     * @param sender   The person rejecting the proposal.
     * @param receiver The initial proposer.
     */
    public void rejectProposal(EntityPlayer sender, EntityPlayer receiver) {
        // Ensure a proposal existed.
        if (!hasProposalFrom(receiver, sender)) {
            failMessage(sender, receiver.getName() + " hasn't proposed to you.");
        } else {
            // Notify of the proposal failure and remove it.
            successMessage(sender, "Your rejection has been sent.");
            failMessage(receiver, sender.getName() + " rejected your proposal.");
            removeProposalFor(sender, receiver);
        }
    }

    /**
     * Accepts and removes a proposal from the receiver to the sender.
     *
     * @param sender   The person accepting the proposal.
     * @param receiver The initial proposer.
     */
    public void acceptProposal(EntityPlayer sender, EntityPlayer receiver) {
        // Ensure a proposal is active.
        if (!hasProposalFrom(receiver, sender)) {
            failMessage(sender, receiver.getName() + " hasn't proposed to you.");
        } else {
            // Notify of acceptance.
            successMessage(receiver, sender.getName() + " has accepted your proposal!");

            // Set both player datas as married.
            PlayerSaveData senderData = PlayerSaveData.get(sender);
            PlayerSaveData receiverData = PlayerSaveData.get(receiver);
            senderData.marry(receiver.getUniqueID(), receiver.getName());
            receiverData.marry(sender.getUniqueID(), sender.getName());

            // Send success messages.
            successMessage(sender, "You and " + receiver.getName() + " are now married.");
            successMessage(receiver, "You and " + sender.getName() + " are now married.");

            // Remove the proposal.
            removeProposalFor(sender, receiver);
        }
    }

    /**
     * Ends the sender's marriage and notifies their spouse if the spouse is online.
     *
     * @param sender The person ending their marriage.
     */
    public void endMarriage(EntityPlayer sender) {
        // Retrieve all data instances and an instance of the ex-spouse if they are present.
        PlayerSaveData senderData = PlayerSaveData.get(sender);

        // Ensure the sender is married
        if (!senderData.isMarriedOrEngaged()) {
            failMessage(sender, "You are not married.");
            return;
        }

        // Lookup the spouse, if it's a villager, we can't continue
        Optional<Entity> spouse = sender.world.loadedEntityList.stream().filter(e -> e.getUniqueID().equals(senderData.getSpouseUUID())).findFirst();
        if (spouse.isPresent() && spouse.get() instanceof EntityVillagerMCA) {
            failMessage(sender, "You cannot use this command when married to a villager.");
            return;
        }

        PlayerSaveData receiverData = PlayerSaveData.getExisting(sender.world, senderData.getSpouseUUID());

        // Notify the sender of the success and end both marriages.
        successMessage(sender, "Your marriage to " + senderData.getSpouseName() + " has ended.");
        senderData.endMarriage();
        receiverData.endMarriage();

        // Notify the ex if they are online.
        spouse.ifPresent(e -> failMessage((EntityPlayer) e, sender.getName() + " has ended their marriage with you."));
    }

    /**
     * Initiates procreation with a married player.
     *
     * @param sender The person requesting procreation.
     */
    public void procreate(EntityPlayer sender) {
        // Ensure the sender is married.
        PlayerSaveData senderData = PlayerSaveData.get(sender);
        if (!senderData.isMarriedOrEngaged()) {
            failMessage(sender, "You cannot procreate if you are not married.");
            return;
        }

        // Ensure we don't already have a baby
        if (senderData.isBabyPresent()) {
            failMessage(sender, "You already have a baby.");
            return;
        }

        // Ensure the spouse is online.
        EntityPlayer spouse = sender.world.getPlayerEntityByUUID(senderData.getSpouseUUID());
        if (spouse != null) {
            // If the spouse is online and has previously sent a procreation request that hasn't expired, we can continue.
            // Otherwise we notify the spouse that they must also enter the command.
            if (!procreateMap.containsKey(spouse.getUniqueID())) {
                procreateMap.put(sender.getUniqueID(), System.currentTimeMillis() + 10000);
                infoMessage(spouse, sender.getName() + " has requested procreation. To accept, type /mca procreate within 10 seconds.");
            } else {
                // On success, add a randomly generated baby to the original requester.
                successMessage(sender, "Procreation successful!");
                successMessage(spouse, "Procreation successful!");
                spouse.addItemStackToInventory(new ItemStack(sender.world.rand.nextBoolean() ? ItemsMCA.BABY_BOY : ItemsMCA.BABY_GIRL));

                PlayerSaveData spouseData = PlayerSaveData.get(spouse);
                spouseData.setBabyPresent(true);
                senderData.setBabyPresent(true);
            }
        } else {
            failMessage(sender, "Your spouse is not present on the server.");
        }
    }

    private void successMessage(EntityPlayer player, String message) {
        player.sendMessage(new TextComponentString(Constants.Color.GREEN + message));
    }

    private void failMessage(EntityPlayer player, String message) {
        player.sendMessage(new TextComponentString(Constants.Color.RED + message));
    }

    private void infoMessage(EntityPlayer player, String message) {
        player.sendMessage(new TextComponentString(Constants.Color.YELLOW + message));
    }

    public void setReaperSpawnPos(World world, BlockPos pos) {
        this.reaperSpawnWorld = world;
        this.reaperSpawnPos = pos;
    }

    public void startSpawnReaper() {
        this.reaperSummonTicks = 20 * 4; // 3 seconds
    }
}


================================================
FILE: src/main/java/mca/core/forge/ClientProxy.java
================================================
package mca.core.forge;

import mca.client.render.RenderReaperFactory;
import mca.client.render.RenderVillagerFactory;
import mca.core.minecraft.BlocksMCA;
import mca.core.minecraft.ItemsMCA;
import mca.entity.EntityGrimReaper;
import mca.entity.EntityVillagerMCA;
import net.minecraftforge.fml.client.registry.RenderingRegistry;

public class ClientProxy extends ServerProxy {
    @Override
    public void registerEntityRenderers() {
        RenderingRegistry.registerEntityRenderingHandler(EntityVillagerMCA.class, RenderVillagerFactory.INSTANCE);
        RenderingRegistry.registerEntityRenderingHandler(EntityGrimReaper.class, RenderReaperFactory.INSTANCE);
    }

    @Override
    public void registerModelMeshers() {
        ItemsMCA.registerModelMeshers();
        BlocksMCA.registerModelMeshers();
    }
}


================================================
FILE: src/main/java/mca/core/forge/EventHooks.java
================================================
package mca.core.forge;

import mca.client.network.ClientMessageQueue;
import mca.core.Constants;
import mca.core.MCA;
import mca.core.MCAServer;
import mca.core.minecraft.BlocksMCA;
import mca.core.minecraft.ItemsMCA;
import mca.core.minecraft.ProfessionsMCA;
import mca.core.minecraft.WorldEventListenerMCA;
import mca.entity.EntityVillagerMCA;
import mca.items.ItemBaby;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.monster.EntityMob;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.StatList;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.world.World;
import net.minecraftforge.event.RegistryEvent;
import net.minecraftforge.event.entity.EntityJoinWorldEvent;
import net.minecraftforge.event.entity.PlaySoundAtEntityEvent;
import net.minecraftforge.event.entity.item.ItemTossEvent;
import net.minecraftforge.event.entity.living.LivingDamageEvent;
import net.minecraftforge.event.entity.living.LivingDeathEvent;
import net.minecraftforge.event.entity.living.LivingSetAttackTargetEvent;
import net.minecraftforge.event.entity.player.PlayerInteractEvent;
import net.minecraftforge.event.world.BlockEvent;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.common.FMLCommonHandler;
import net.minecraftforge.fml.common.eventhandler.Event;
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
import net.minecraftforge.fml.common.gameevent.PlayerEvent;
import net.minecraftforge.fml.common.gameevent.TickEvent;
import net.minecraftforge.fml.common.registry.GameRegistry;
import net.minecraftforge.fml.relauncher.Side;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;

public class EventHooks {
    // Maps a player UUID to the itemstack of their held ItemBaby. Filled when a player dies so the baby is never lost.
    public Map<UUID, ItemStack> limbo = new HashMap<>();

    @SubscribeEvent
    public void onRegisterItems(RegistryEvent.Register<Item> event) {
        ItemsMCA.register(event);
        BlocksMCA.registerItemBlocks(event);

        GameRegistry.addSmelting(BlocksMCA.ROSE_GOLD_ORE, new ItemStack(ItemsMCA.ROSE_GOLD_INGOT), 5.0F);
    }

    @SubscribeEvent
    public void onRegisterBlocks(RegistryEvent.Register<Block> event) {
        BlocksMCA.register(event);
    }

    @SubscribeEvent
    public void onWorldLoad(WorldEvent.Load event) {
        if (event.getWorld().isRemote) event.getWorld().addEventListener(new WorldEventListenerMCA());
    }

    @SubscribeEvent
    public void onClientTick(TickEvent.ClientTickEvent event) {
        ClientMessageQueue.processScheduledMessages();
    }

    @SubscribeEvent
    public void onServerTick(TickEvent.ServerTickEvent event) {
        MCAServer.get().tick();
    }

    @SubscribeEvent
    public void onPlayerLogin(PlayerEvent.PlayerLoggedInEvent event) {
        if (!MCA.updateAvailable) return;
        TextComponentString updateMessage = new TextComponentString(Constants.Color.DARKGREEN + "An update for Minecraft Comes Alive is available: v" + MCA.latestVersion);
        String updateURLText = Constants.Color.YELLOW + "Click " + Constants.Color.BLUE + Constants.Format.ITALIC + Constants.Format.UNDERLINE + "here" + Constants.Format.RESET + Constants.Color.YELLOW + " to download the update.";

        TextComponentString chatComponentUpdate = new TextComponentString(updateURLText);
        chatComponentUpdate.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://minecraftcomesalive.com/download"));
        chatComponentUpdate.getStyle().setUnderlined(true);

        event.player.sendMessage(updateMessage);
        event.player.sendMessage(chatComponentUpdate);

        MCA.updateAvailable = false;
    }

    @SubscribeEvent
    public void onWorldUnload(WorldEvent.Unload event) {
        // Only send crash reports on unloading the overworld. This will never change based on other mods installed
        // and ensures only one crash report is sent per instance.
        if (!event.getWorld().isRemote && event.getWorld().provider.getDimension() == 0) MCA.getInstance().checkForCrashReports();
    }

    @SubscribeEvent
    public void onEntityJoinWorld(EntityJoinWorldEvent event) {
        World world = event.getWorld();
        Entity entity = event.getEntity();

        if (world.isRemote) return;
        if (!MCA.getConfig().overwriteOriginalVillagers) return;

        if (entity.getClass().equals(EntityVillager.class)) {
            EntityVillager originalVillager = (EntityVillager) entity;
            originalVillager.setDead();

            EntityVillagerMCA newVillager = new EntityVillagerMCA(world, com.google.common.base.Optional.of(originalVillager.getProfessionForge()), com.google.common.base.Optional.absent());
            newVillager.setPosition(originalVillager.posX, originalVillager.posY, originalVillager.posZ);
            newVillager.finalizeMobSpawn(world.getDifficultyForLocation(newVillager.getPos()), null, false);
            newVillager.forcePositionAsHome();
            world.spawnEntity(newVillager);
        }
    }

    @SubscribeEvent
    public void onEntityInteractSpecific(PlayerInteractEvent.EntityInteractSpecific event) {
        if (event.getTarget() instanceof EntityVillagerMCA && event.getEntityPlayer() != null) {
            EntityPlayer player = event.getEntityPlayer();
            EntityVillagerMCA villager = (EntityVillagerMCA)event.getTarget();

            if (villager.getProfessionForge() == ProfessionsMCA.bandit) {
                event.setResult(Event.Result.DENY);
            } else if (player.getHeldItemMainhand().getItem() == ItemsMCA.VILLAGER_EDITOR) {
                player.openGui(MCA.getInstance(), Constants.GUI_ID_VILLAGEREDITOR, player.world, villager.getEntityId(), 0, 0);
                event.setResult(Event.Result.ALLOW);
            } else {
                player.addStat(StatList.TALKED_TO_VILLAGER);
                player.openGui(MCA.getInstance(), Constants.GUI_ID_INTERACT, player.world, villager.getEntityId(), 0, 0);
                event.setResult(Event.Result.ALLOW);
            }
        }
    }

    @SubscribeEvent
    public void onEntityDamaged(LivingDamageEvent event) {
        if (event.getEntity() instanceof EntityVillagerMCA) {
            EntityVillagerMCA villager = (EntityVillagerMCA)event.getEntity();
            Entity source = event.getSource() != null ? event.getSource().getTrueSource() : null;

            if (source instanceof EntityLivingBase) {
                villager.world.loadedEntityList.stream().filter(e ->
                        e instanceof EntityVillagerMCA &&
                        e.getDistance(villager) <= 10.0D &&
                        ((EntityVillagerMCA)e).getProfessionForge() == ProfessionsMCA.guard)
                .forEach(e -> ((EntityVillagerMCA) e).setAttackTarget((EntityLivingBase)source));
            }
        }
    }

    @SubscribeEvent
    public void onItemToss(ItemTossEvent event) {
        ItemStack stack = event.getEntityItem().getItem();
        if (stack.getItem() instanceof ItemBaby) {
            event.getPlayer().addItemStackToInventory(stack);
            event.setCanceled(true);
        }
    }

    @SubscribeEvent
    public void onPlaceEvent(BlockEvent.PlaceEvent event) {
        int x = event.getPos().getX();
        int y = event.getPos().getY();
        int z = event.getPos().getZ();
        Block placedBlock = event.getPlacedBlock().getBlock();

        if (placedBlock == Blocks.FIRE && event.getWorld().getBlockState(new BlockPos(x, y - 1, z)).getBlock() == Blocks.EMERALD_BLOCK) {
            int totemsFound = 0;

            // Check on +/- X and Z for at least 3 totems on fire.
            for (int i = 0; i < 4; i++) {
                int dX = 0;
                int dZ = 0;

                if (i == 0 || i == 2) dX = -3;
                else dZ = 3;

                // Scan upwards to ensure it's obsidian, and on fire.
                for (int j = -1; j < 2; j++) {
                    Block block = event.getWorld().getBlockState(new BlockPos(x + dX, y + j, z + dZ)).getBlock();
                    if (block != Blocks.OBSIDIAN && block != Blocks.FIRE) break;

                    // If we made it up to 1 without breaking, make sure the block is fire so that it's a lit totem.
                    if (j == 1 && block == Blocks.FIRE) totemsFound++;
                }
            }

            if (totemsFound >= 3 && !event.getWorld().isDaytime()) {
                MCAServer.get().setReaperSpawnPos(event.getWorld(), new BlockPos(x + 1, y + 10, z + 1));
                MCAServer.get().startSpawnReaper();
                for (int i = 0; i < 2; i++) event.getWorld().setBlockToAir(new BlockPos(x, y - i, z));
            }
        }
    }

    @SubscribeEvent
    public void onPlayerRespawn(PlayerEvent.PlayerRespawnEvent event) {
        // When players respawn check to see if their baby was saved in limbo. Add it back to their inventory.
        if (limbo.containsKey(event.player.getUniqueID())) {
            event.player.inventory.addItemStackToInventory(limbo.get(event.player.getUniqueID()));
            limbo.remove(event.player.getUniqueID());
        }
    }

    @SubscribeEvent
    public void onLivingDeath(LivingDeathEvent event) {
        // If a player dies while holding a baby, remember it until they respawn.
        if (event.getEntityLiving() instanceof EntityPlayer) {
            EntityPlayer player = (EntityPlayer)event.getEntityLiving();
            Optional<ItemStack> babyStack = player.inventory.mainInventory.stream().filter(s -> s.getItem() instanceof ItemBaby).findFirst();
            babyStack.ifPresent(s -> limbo.put(player.getUniqueID(), babyStack.get()));
        }
    }

    @SubscribeEvent
    public void onLivingSetTarget(LivingSetAttackTargetEvent event) {
        // Mobs shouldn't attack infected villagers. Account for this when they attempt to set their target.
        if (event.getEntityLiving() instanceof EntityMob && event.getTarget() instanceof EntityVillagerMCA) {
            EntityMob mob = (EntityMob) event.getEntityLiving();
            EntityVillagerMCA target = (EntityVillagerMCA) event.getTarget();

            if (target.get(EntityVillagerMCA.IS_INFECTED)) {
                mob.setAttackTarget(null);
            }
        }
    }

    @SubscribeEvent
    public void onPlaySoundAtEntityEvent(PlaySoundAtEntityEvent event) {
        // Cancel all villager sounds. We unfortunately cannot control on a per entity basis as getEntity() always returns null.
        if (FMLCommonHandler.instance().getEffectiveSide() != Side.CLIENT) return;
        try {
            event.setCanceled(event.getSound().getSoundName().toString().contains("villager"));
        } catch (NullPointerException e) {
            // throw out potential NPEs due to bad event data. some of these have been reported
        }
    }
}


================================================
FILE: src/main/java/mca/core/forge/GuiHandler.java
================================================
package mca.core.forge;

import mca.client.gui.*;
import mca.core.Constants;
import mca.core.MCA;
import mca.entity.EntityVillagerMCA;
import net.minecraft.client.gui.GuiScreenBook;
import net.minecraft.client.gui.inventory.GuiChest;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ContainerChest;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.network.IGuiHandler;

public class GuiHandler implements IGuiHandler {
    @Override
    public Object getServerGuiElement(int guiId, EntityPlayer player, World world, int entityId, int posY, int posZ) {
        switch (guiId) {
            case Constants.GUI_ID_INVENTORY:
                EntityVillagerMCA villager = (EntityVillagerMCA) world.getEntityByID(entityId);
                if (villager == null || villager.inventory == null) return null;
                return new ContainerChest(player.inventory, villager.inventory, player);
            default:
                return null;
        }
    }

    @Override
    public Object getClientGuiElement(int guiId, EntityPlayer player, World world, int entityId, int unused1, int unused2) {
        switch (guiId) {
            case Constants.GUI_ID_INVENTORY:
                Entity entity = world.getEntityByID(entityId);
                if (entity == null) return null;
                return new GuiChest(player.inventory, ((EntityVillagerMCA) entity).inventory);
            case Constants.GUI_ID_INTERACT:
                return new GuiInteract((EntityVillagerMCA) world.getEntityByID(entityId), player);
            case Constants.GUI_ID_NAMEBABY:
                return new GuiNameBaby(player, player.inventory.getStackInSlot(player.inventory.currentItem));
            case Constants.GUI_ID_STAFFOFLIFE:
                return new GuiStaffOfLife(player);
            case Constants.GUI_ID_VILLAGEREDITOR:
                return new GuiVillagerEditor((EntityVillagerMCA) world.getEntityByID(entityId), player);
            case Constants.GUI_ID_GUIDEBOOK:
                return new GuiScreenBook(player, player.inventory.getCurrentItem(), false);
            case Constants.GUI_ID_WHISTLE:
                return new GuiWhistle();
            default:
                MCA.getLog().fatal("Failed to handle provided GUI ID on client: " + guiId);
                return null;
        }
    }
}

================================================
FILE: src/main/java/mca/core/forge/NetMCA.java
================================================
package mca.core.forge;

import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import mca.client.gui.GuiStaffOfLife;
import mca.client.gui.GuiWhistle;
import mca.client.network.ClientMessageQueue;
import mca.core.MCA;
import mca.core.minecraft.ProfessionsMCA;
import mca.entity.EntityVillagerMCA;
import mca.entity.data.SavedVillagers;
import mca.entity.inventory.InventoryMCA;
import mca.items.ItemBaby;
import mca.server.ServerMessageHandler;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.passive.EntityVillager;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumParticleTypes;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.ObfuscationReflectionHelper;
import net.minecraftforge.fml.common.network.ByteBufUtils;
import net.minecraftforge.fml.common.network.NetworkRegistry;
import net.minecraftforge.fml.common.network.simpleimpl.IMessage;
import net.minecraftforge.fml.common.network.simpleimpl.IMessageHandler;
import net.minecraftforge.fml.common.network.simpleimpl.MessageContext;
import net.minecraftforge.fml.common.network.simpleimpl.SimpleNetworkWrapper;
import net.minecraftforge.fml.common.registry.VillagerRegistry;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
import scala.collection.parallel.ParIterableLike;

import javax.annotation.Nullable;
import java.util.*;

public class NetMCA {
    public static final SimpleNetworkWrapper INSTANCE = NetworkRegistry.INSTANCE.newSimpleChannel("mca");

    public static void registerMessages() {
        INSTANCE.registerMessage(ButtonActionHandler.class, ButtonAction.class, 0, Side.SERVER);
        INSTANCE.registerMessage(SayHandler.class, Say.class, 1, Side.CLIENT);
        INSTANCE.registerMessage(Baby
Download .txt
gitextract_9ljofwy4/

├── .github/
│   └── ISSUE_TEMPLATE/
│       ├── bug-report.md
│       └── feature-change-request.md
├── .gitignore
├── CHANGELOG
├── LICENSE
├── README.md
├── build.gradle
├── gradle/
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradle.properties
├── gradlew
├── gradlew.bat
└── src/
    └── main/
        ├── java/
        │   └── mca/
        │       ├── api/
        │       │   ├── API.java
        │       │   └── types/
        │       │       ├── APIButton.java
        │       │       ├── Gift.java
        │       │       └── SkinsGroup.java
        │       ├── blocks/
        │       │   └── BlockVillagerSpawner.java
        │       ├── client/
        │       │   ├── MCAGuiFactory.java
        │       │   ├── gui/
        │       │   │   ├── GuiConfigPage.java
        │       │   │   ├── GuiInteract.java
        │       │   │   ├── GuiNameBaby.java
        │       │   │   ├── GuiStaffOfLife.java
        │       │   │   ├── GuiVillagerEditor.java
        │       │   │   ├── GuiWhistle.java
        │       │   │   └── component/
        │       │   │       └── GuiButtonEx.java
        │       │   ├── model/
        │       │   │   ├── ModelGrimReaper.java
        │       │   │   └── ModelVillagerMCA.java
        │       │   ├── network/
        │       │   │   └── ClientMessageQueue.java
        │       │   └── render/
        │       │       ├── RenderGrimReaper.java
        │       │       ├── RenderReaperFactory.java
        │       │       ├── RenderVillagerFactory.java
        │       │       └── RenderVillagerMCA.java
        │       ├── command/
        │       │   ├── CommandAdminMCA.java
        │       │   └── CommandMCA.java
        │       ├── core/
        │       │   ├── Config.java
        │       │   ├── Constants.java
        │       │   ├── Localizer.java
        │       │   ├── MCA.java
        │       │   ├── MCAServer.java
        │       │   ├── forge/
        │       │   │   ├── ClientProxy.java
        │       │   │   ├── EventHooks.java
        │       │   │   ├── GuiHandler.java
        │       │   │   ├── NetMCA.java
        │       │   │   └── ServerProxy.java
        │       │   └── minecraft/
        │       │       ├── BlocksMCA.java
        │       │       ├── ItemsMCA.java
        │       │       ├── ProfessionsMCA.java
        │       │       ├── RoseGoldOreGenerator.java
        │       │       ├── SoundsMCA.java
        │       │       ├── VillageHelper.java
        │       │       └── WorldEventListenerMCA.java
        │       ├── entity/
        │       │   ├── EntityGrimReaper.java
        │       │   ├── EntityVillagerMCA.java
        │       │   ├── ai/
        │       │   │   ├── AbstractEntityAIChore.java
        │       │   │   ├── EntityAIAgeBaby.java
        │       │   │   ├── EntityAIChopping.java
        │       │   │   ├── EntityAIDefendFromTarget.java
        │       │   │   ├── EntityAIFishing.java
        │       │   │   ├── EntityAIGoHangout.java
        │       │   │   ├── EntityAIGoWorkplace.java
        │       │   │   ├── EntityAIHarvesting.java
        │       │   │   ├── EntityAIHunting.java
        │       │   │   ├── EntityAIMoveState.java
        │       │   │   ├── EntityAIProcreate.java
        │       │   │   ├── EntityAIProspecting.java
        │       │   │   └── EntityAISleeping.java
        │       │   ├── data/
        │       │   │   ├── ParentData.java
        │       │   │   ├── PlayerHistory.java
        │       │   │   ├── PlayerSaveData.java
        │       │   │   └── SavedVillagers.java
        │       │   └── inventory/
        │       │       └── InventoryMCA.java
        │       ├── enums/
        │       │   ├── EnumAgeState.java
        │       │   ├── EnumChore.java
        │       │   ├── EnumConstraint.java
        │       │   ├── EnumDialogueType.java
        │       │   ├── EnumGender.java
        │       │   ├── EnumMarriageState.java
        │       │   ├── EnumMoveState.java
        │       │   └── EnumReaperAttackState.java
        │       ├── items/
        │       │   ├── ItemBaby.java
        │       │   ├── ItemEngagementRing.java
        │       │   ├── ItemGuideBook.java
        │       │   ├── ItemMatchmakersRing.java
        │       │   ├── ItemSpawnEgg.java
        │       │   ├── ItemSpecialCaseGift.java
        │       │   ├── ItemStaffOfLife.java
        │       │   ├── ItemVillagerEditor.java
        │       │   ├── ItemWeddingRing.java
        │       │   └── ItemWhistle.java
        │       ├── server/
        │       │   └── ServerMessageHandler.java
        │       └── util/
        │           ├── ItemStackCache.java
        │           ├── ResourceLocationCache.java
        │           └── Util.java
        └── resources/
            ├── assets/
            │   └── mca/
            │       ├── api/
            │       │   ├── gifts.json
            │       │   ├── gui/
            │       │   │   ├── debug.json
            │       │   │   ├── editor.json
            │       │   │   ├── interact.json
            │       │   │   ├── location.json
            │       │   │   ├── main.json
            │       │   │   └── work.json
            │       │   └── skins.json
            │       ├── blockstates/
            │       │   ├── rose_gold_block.json
            │       │   ├── rose_gold_ore.json
            │       │   └── villager_spawner.json
            │       ├── lang/
            │       │   ├── en_us.lang
            │       │   └── names.lang
            │       ├── models/
            │       │   ├── block/
            │       │   │   ├── rose_gold_block.json
            │       │   │   ├── rose_gold_ore.json
            │       │   │   └── villager_spawner.json
            │       │   └── item/
            │       │       ├── baby_boy.json
            │       │       ├── baby_girl.json
            │       │       ├── book_death.json
            │       │       ├── book_family.json
            │       │       ├── book_infection.json
            │       │       ├── book_romance.json
            │       │       ├── book_rose_gold.json
            │       │       ├── egg_female.json
            │       │       ├── egg_male.json
            │       │       ├── engagement_ring.json
            │       │       ├── engagement_ring_rg.json
            │       │       ├── gold_dust.json
            │       │       ├── matchmakers_ring.json
            │       │       ├── rose_gold_block.json
            │       │       ├── rose_gold_dust.json
            │       │       ├── rose_gold_ingot.json
            │       │       ├── staff_of_life.json
            │       │       ├── villager_editor.json
            │       │       ├── wedding_ring.json
            │       │       ├── wedding_ring_rg.json
            │       │       └── whistle.json
            │       ├── recipes/
            │       │   ├── engagement_ring.json
            │       │   ├── engagement_ring_rg.json
            │       │   ├── gold_dust.json
            │       │   ├── gold_nugget_from_dust.json
            │       │   ├── matchmakers_ring.json
            │       │   ├── rose_gold_block.json
            │       │   ├── rose_gold_dust_from_ingot.json
            │       │   ├── rose_gold_ingot_from_dust.json
            │       │   ├── wedding_ring.json
            │       │   ├── wedding_ring_rg.json
            │       │   └── whistle.json
            │       ├── sounds/
            │       │   ├── reaper-block.ogg
            │       │   ├── reaper-death.ogg
            │       │   ├── reaper-idle.ogg
            │       │   ├── reaper-scythe-out.ogg
            │       │   ├── reaper-scythe-swing.ogg
            │       │   └── reaper-summon.ogg
            │       └── sounds.json
            ├── mcmod.info
            └── pack.mcmeta
Download .txt
SYMBOL INDEX (669 symbols across 81 files)

FILE: src/main/java/mca/api/API.java
  class API (line 31) | public class API {
    method init (line 42) | public static void init() {
    method getRandomSkin (line 86) | public static String getRandomSkin(EntityVillagerMCA villager) {
    method getButtonById (line 129) | public static Optional<APIButton> getButtonById(String key, String id) {
    method getGiftValueFromStack (line 139) | public static int getGiftValueFromStack(ItemStack stack) {
    method getResponseForGift (line 152) | public static String getResponseForGift(ItemStack stack) {
    method getRandomName (line 163) | public static String getRandomName(@Nonnull EnumGender gender) {
    method addButtons (line 177) | public static void addButtons(String guiKey, @Nullable EntityVillagerM...
    method getButton (line 204) | public static Optional<GuiButtonEx> getButton(String id, GuiScreen scr...

FILE: src/main/java/mca/api/types/APIButton.java
  class APIButton (line 17) | @AllArgsConstructor
    method getConstraints (line 30) | public List<EnumConstraint> getConstraints() {
    method isValidForConstraint (line 41) | public boolean isValidForConstraint(EntityVillagerMCA villager, Entity...

FILE: src/main/java/mca/api/types/Gift.java
  class Gift (line 9) | @AllArgsConstructor
    method exists (line 20) | public boolean exists() {

FILE: src/main/java/mca/api/types/SkinsGroup.java
  class SkinsGroup (line 7) | @AllArgsConstructor
    method getGender (line 13) | public EnumGender getGender() {

FILE: src/main/java/mca/blocks/BlockVillagerSpawner.java
  class BlockVillagerSpawner (line 15) | public class BlockVillagerSpawner extends Block {
    method BlockVillagerSpawner (line 17) | public BlockVillagerSpawner() {
    method updateTick (line 23) | @Override

FILE: src/main/java/mca/client/MCAGuiFactory.java
  class MCAGuiFactory (line 10) | public class MCAGuiFactory implements IModGuiFactory
    method initialize (line 12) | @Override
    method createConfigGui (line 15) | @Override
    method runtimeGuiCategories (line 20) | @Override
    method hasConfigGui (line 25) | @Override

FILE: src/main/java/mca/client/gui/GuiConfigPage.java
  class GuiConfigPage (line 10) | public class GuiConfigPage extends GuiConfig {
    method GuiConfigPage (line 11) | public GuiConfigPage(GuiScreen parent) {
    method GuiConfigPage (line 17) | public GuiConfigPage(GuiScreen parentScreen, List<IConfigElement> conf...

FILE: src/main/java/mca/client/gui/GuiInteract.java
  class GuiInteract (line 26) | @SideOnly(Side.CLIENT)
    method GuiInteract (line 52) | public GuiInteract(EntityVillagerMCA villager, EntityPlayer player) {
    method initGui (line 59) | @Override
    method onGuiClosed (line 64) | @Override
    method doesGuiPauseGame (line 68) | @Override
    method updateScreen (line 73) | @Override
    method drawScreen (line 80) | @Override
    method handleMouseInput (line 90) | @Override
    method mouseClicked (line 101) | @Override
    method keyTyped (line 109) | @Override
    method drawIcons (line 134) | private void drawIcons() {
    method drawTextPopups (line 162) | private void drawTextPopups() {
    method hoveringOverHeartsIcon (line 187) | private boolean hoveringOverHeartsIcon() {
    method hoveringOverMarriageIcon (line 191) | private boolean hoveringOverMarriageIcon() {
    method hoveringOverParentsIcon (line 195) | private boolean hoveringOverParentsIcon() {
    method hoveringOverGiftIcon (line 199) | private boolean hoveringOverGiftIcon() {
    method canDrawParentsIcon (line 203) | private boolean canDrawParentsIcon() {
    method canDrawGiftIcon (line 209) | private boolean canDrawGiftIcon() {
    method actionPerformed (line 213) | protected void actionPerformed(GuiButton button) {
    method drawMainButtonMenu (line 253) | private void drawMainButtonMenu() {
    method drawInteractButtonMenu (line 263) | private void drawInteractButtonMenu() {
    method drawWorkButtonMenu (line 268) | private void drawWorkButtonMenu() {
    method drawLocationButtonMenu (line 273) | private void drawLocationButtonMenu() {
    method disableButton (line 278) | private void disableButton(String id) {
    method enableAllButtons (line 284) | private void enableAllButtons() {
    method disableAllButtons (line 288) | private void disableAllButtons() {

FILE: src/main/java/mca/client/gui/GuiNameBaby.java
  class GuiNameBaby (line 18) | @SideOnly(Side.CLIENT)
    method GuiNameBaby (line 27) | public GuiNameBaby(EntityPlayer player, ItemStack babyStack) {
    method updateScreen (line 34) | @Override
    method initGui (line 44) | @Override
    method onGuiClosed (line 57) | @Override
    method doesGuiPauseGame (line 62) | @Override
    method actionPerformed (line 67) | @Override
    method keyTyped (line 77) | @Override
    method mouseClicked (line 82) | @Override
    method drawScreen (line 88) | @Override

FILE: src/main/java/mca/client/gui/GuiStaffOfLife.java
  class GuiStaffOfLife (line 19) | @SideOnly(Side.CLIENT)
    method GuiStaffOfLife (line 34) | public GuiStaffOfLife(EntityPlayer player) {
    method initGui (line 39) | @Override
    method doesGuiPauseGame (line 51) | @Override
    method actionPerformed (line 56) | @Override
    method drawScreen (line 66) | @Override
    method setVillagerData (line 74) | public void setVillagerData(Map<String, NBTTagCompound> data) {
    method updateDummy (line 90) | private void updateDummy(NBTTagCompound nbt) {
    method selectData (line 95) | private void selectData(int i) {
    method drawDummy (line 104) | private void drawDummy() {

FILE: src/main/java/mca/client/gui/GuiVillagerEditor.java
  class GuiVillagerEditor (line 22) | @SideOnly(Side.CLIENT)
    method GuiVillagerEditor (line 31) | public GuiVillagerEditor(EntityVillagerMCA EntityHuman, EntityPlayer p...
    method updateScreen (line 37) | @Override
    method initGui (line 45) | @Override
    method onGuiClosed (line 61) | @Override
    method actionPerformed (line 66) | @Override
    method keyTyped (line 93) | @Override
    method mouseClicked (line 108) | @Override
    method doesGuiPauseGame (line 116) | @Override
    method drawEditorGui (line 121) | private void drawEditorGui() {
    method drawScreen (line 126) | @Override

FILE: src/main/java/mca/client/gui/GuiWhistle.java
  class GuiWhistle (line 20) | @SideOnly(Side.CLIENT)
    method updateScreen (line 33) | @Override
    method initGui (line 46) | @Override
    method doesGuiPauseGame (line 57) | @Override
    method actionPerformed (line 62) | @Override
    method drawScreen (line 101) | @Override
    method drawDummyVillager (line 127) | private void drawDummyVillager() {
    method setVillagerDataList (line 133) | public void setVillagerDataList(@NonNull List<NBTTagCompound> dataList) {
    method updateDummyVillagerWithData (line 150) | private void updateDummyVillagerWithData(NBTTagCompound nbt) {

FILE: src/main/java/mca/client/gui/component/GuiButtonEx.java
  class GuiButtonEx (line 9) | public class GuiButtonEx extends GuiButton {
    method GuiButtonEx (line 12) | public GuiButtonEx(GuiScreen gui, APIButton apiButton) {

FILE: src/main/java/mca/client/model/ModelGrimReaper.java
  class ModelGrimReaper (line 11) | public class ModelGrimReaper extends ModelBiped {
    method ModelGrimReaper (line 60) | public ModelGrimReaper() {
    method render (line 245) | @Override
    method setRotateAngle (line 323) | public void setRotateAngle(ModelRenderer modelRenderer, float x, float...

FILE: src/main/java/mca/client/model/ModelVillagerMCA.java
  class ModelVillagerMCA (line 13) | public class ModelVillagerMCA extends ModelBiped {
    method ModelVillagerMCA (line 16) | public ModelVillagerMCA() {
    method render (line 25) | @Override

FILE: src/main/java/mca/client/network/ClientMessageQueue.java
  class ClientMessageQueue (line 18) | public class ClientMessageQueue {
    method processScheduledMessages (line 21) | public static void processScheduledMessages() {
    method add (line 27) | public static void add(IMessage msg) {
    method handle (line 31) | private static void handle(IMessage msg) {
    method handleCareerId (line 37) | private static void handleCareerId(NetMCA.CareerResponse msg) {
    method handleInventory (line 53) | private static void handleInventory(NetMCA.InventoryResponse msg) {
    method getVillagerByUUID (line 61) | private static Optional<EntityVillagerMCA> getVillagerByUUID(World wor...

FILE: src/main/java/mca/client/render/RenderGrimReaper.java
  class RenderGrimReaper (line 10) | public class RenderGrimReaper<T extends EntityGrimReaper> extends Render...
    method RenderGrimReaper (line 13) | public RenderGrimReaper(RenderManager manager) {
    method doRender (line 17) | @Override
    method preRenderCallback (line 22) | @Override
    method getEntityTexture (line 30) | @Override

FILE: src/main/java/mca/client/render/RenderReaperFactory.java
  class RenderReaperFactory (line 8) | public class RenderReaperFactory implements IRenderFactory<EntityGrimRea...
    method createRenderFor (line 11) | @Override

FILE: src/main/java/mca/client/render/RenderVillagerFactory.java
  class RenderVillagerFactory (line 8) | public class RenderVillagerFactory implements IRenderFactory<EntityVilla...
    method createRenderFor (line 11) | @Override

FILE: src/main/java/mca/client/render/RenderVillagerMCA.java
  class RenderVillagerMCA (line 19) | public class RenderVillagerMCA<T extends EntityVillagerMCA> extends Rend...
    method RenderVillagerMCA (line 23) | public RenderVillagerMCA(RenderManager manager) {
    method preRenderCallback (line 29) | @Override
    method renderName (line 41) | @Override
    method renderHealth (line 59) | private void renderHealth(EntityVillagerMCA villager, double posX, dou...
    method getEntityTexture (line 88) | @Override
    method canRenderName (line 93) | @Override
    method drawTexturedRectangle (line 99) | public static void drawTexturedRectangle(ResourceLocation texture, int...
    method renderLivingAt (line 117) | @Override
    method applyRotations (line 126) | @Override

FILE: src/main/java/mca/command/CommandAdminMCA.java
  class CommandAdminMCA (line 25) | public class CommandAdminMCA extends CommandBase {
    method getName (line 26) | @Override
    method getUsage (line 31) | @Override
    method execute (line 36) | @Override
    method forceFullHearts (line 76) | private void forceFullHearts(EntityPlayer player) {
    method forceBabyGrow (line 86) | private void forceBabyGrow(EntityPlayer player) {
    method forceChildGrow (line 95) | private void forceChildGrow(EntityPlayer player) {
    method clearLoadedVillagers (line 102) | private void clearLoadedVillagers(EntityPlayer player) {
    method incrementHearts (line 113) | private void incrementHearts(EntityPlayer player) {
    method decrementHearts (line 123) | private void decrementHearts(EntityPlayer player) {
    method spawnGrimReaper (line 133) | private void spawnGrimReaper(EntityPlayer player) {
    method killGrimReaper (line 139) | private void killGrimReaper(EntityPlayer player) {
    method dumpPlayerData (line 143) | private void dumpPlayerData(EntityPlayer player) {
    method resetVillagerData (line 147) | private void resetVillagerData(EntityPlayer sender, String[] arguments) {
    method resetPlayerData (line 157) | private void resetPlayerData(EntityPlayer sender, String[] arguments) {
    method clearVillagerEditors (line 170) | private void clearVillagerEditors(EntityPlayer sender) {
    method getRequiredPermissionLevel (line 184) | @Override
    method sendMessage (line 189) | private void sendMessage(ICommandSender commandSender, String message) {
    method sendMessage (line 193) | private void sendMessage(ICommandSender commandSender, String message,...
    method displayHelp (line 201) | private void displayHelp(ICommandSender commandSender) {

FILE: src/main/java/mca/command/CommandMCA.java
  class CommandMCA (line 16) | public class CommandMCA extends CommandBase {
    method getName (line 17) | @Override
    method getUsage (line 22) | @Override
    method execute (line 27) | @Override
    method getRequiredPermissionLevel (line 91) | @Override
    method sendMessage (line 96) | private void sendMessage(ICommandSender commandSender, String message) {
    method sendMessage (line 100) | private void sendMessage(ICommandSender commandSender, String message,...
    method displayHelp (line 108) | private void displayHelp(ICommandSender commandSender) {

FILE: src/main/java/mca/core/Config.java
  class Config (line 12) | public final class Config implements Serializable {
    method Config (line 39) | public Config(FMLPreInitializationEvent event) {
    method addConfigValues (line 44) | private void addConfigValues() {
    method getInstance (line 71) | public Configuration getInstance() {
    method getCategories (line 75) | public List<IConfigElement> getCategories() {

FILE: src/main/java/mca/core/Constants.java
  class Constants (line 5) | public class Constants {
    class Color (line 21) | public final class Color {
    class Format (line 43) | public final class Format {

FILE: src/main/java/mca/core/Localizer.java
  class Localizer (line 12) | public class Localizer {
    method Localizer (line 16) | public Localizer() {
    method localize (line 38) | public String localize(String key, String... vars) {
    method localize (line 44) | public String localize(String key, ArrayList<String> vars) {
    method parseVars (line 54) | private String parseVars(String str, ArrayList<String> vars) {

FILE: src/main/java/mca/core/MCA.java
  class MCA (line 40) | @Mod(modid = MCA.MODID, name = MCA.NAME, version = MCA.VERSION, guiFacto...
    method getLog (line 58) | public static Logger getLog() {
    method getInstance (line 62) | public static MCA getInstance() {
    method getLocalizer (line 66) | public static Localizer getLocalizer() {
    method getConfig (line 70) | public static Config getConfig() {
    method getStartupTimestamp (line 74) | public static long getStartupTimestamp() {
    method preInit (line 78) | @EventHandler
    method init (line 108) | @EventHandler
    method postInit (line 119) | @EventHandler
    method serverStarting (line 124) | @EventHandler
    method serverStopping (line 130) | @EventHandler
    method getRandomSupporter (line 135) | public String getRandomSupporter() {
    method checkForCrashReports (line 143) | public void checkForCrashReports() {

FILE: src/main/java/mca/core/MCAServer.java
  class MCAServer (line 19) | public class MCAServer {
    method MCAServer (line 30) | private MCAServer() {
    method get (line 35) | public static MCAServer get() {
    method tick (line 42) | public void tick() {
    method hasProposalFrom (line 80) | private boolean hasProposalFrom(EntityPlayer sender, EntityPlayer rece...
    method getProposalsFor (line 90) | private List<UUID> getProposalsFor(EntityPlayer player) {
    method removeProposalFor (line 100) | private void removeProposalFor(EntityPlayer target, EntityPlayer propo...
    method listProposals (line 111) | public void listProposals(EntityPlayer sender) {
    method sendProposal (line 135) | public void sendProposal(EntityPlayer sender, EntityPlayer receiver) {
    method rejectProposal (line 169) | public void rejectProposal(EntityPlayer sender, EntityPlayer receiver) {
    method acceptProposal (line 187) | public void acceptProposal(EntityPlayer sender, EntityPlayer receiver) {
    method endMarriage (line 215) | public void endMarriage(EntityPlayer sender) {
    method procreate (line 248) | public void procreate(EntityPlayer sender) {
    method successMessage (line 285) | private void successMessage(EntityPlayer player, String message) {
    method failMessage (line 289) | private void failMessage(EntityPlayer player, String message) {
    method infoMessage (line 293) | private void infoMessage(EntityPlayer player, String message) {
    method setReaperSpawnPos (line 297) | public void setReaperSpawnPos(World world, BlockPos pos) {
    method startSpawnReaper (line 302) | public void startSpawnReaper() {

FILE: src/main/java/mca/core/forge/ClientProxy.java
  class ClientProxy (line 11) | public class ClientProxy extends ServerProxy {
    method registerEntityRenderers (line 12) | @Override
    method registerModelMeshers (line 18) | @Override

FILE: src/main/java/mca/core/forge/EventHooks.java
  class EventHooks (line 51) | public class EventHooks {
    method onRegisterItems (line 55) | @SubscribeEvent
    method onRegisterBlocks (line 63) | @SubscribeEvent
    method onWorldLoad (line 68) | @SubscribeEvent
    method onClientTick (line 73) | @SubscribeEvent
    method onServerTick (line 78) | @SubscribeEvent
    method onPlayerLogin (line 83) | @SubscribeEvent
    method onWorldUnload (line 99) | @SubscribeEvent
    method onEntityJoinWorld (line 106) | @SubscribeEvent
    method onEntityInteractSpecific (line 126) | @SubscribeEvent
    method onEntityDamaged (line 145) | @SubscribeEvent
    method onItemToss (line 161) | @SubscribeEvent
    method onPlaceEvent (line 170) | @SubscribeEvent
    method onPlayerRespawn (line 206) | @SubscribeEvent
    method onLivingDeath (line 215) | @SubscribeEvent
    method onLivingSetTarget (line 225) | @SubscribeEvent
    method onPlaySoundAtEntityEvent (line 238) | @SubscribeEvent

FILE: src/main/java/mca/core/forge/GuiHandler.java
  class GuiHandler (line 15) | public class GuiHandler implements IGuiHandler {
    method getServerGuiElement (line 16) | @Override
    method getClientGuiElement (line 28) | @Override

FILE: src/main/java/mca/core/forge/NetMCA.java
  class NetMCA (line 45) | public class NetMCA {
    method registerMessages (line 48) | public static void registerMessages() {
    method getPlayerClient (line 68) | @SideOnly(Side.CLIENT)
    class ButtonAction (line 73) | @AllArgsConstructor
      method toBytes (line 81) | @Override
      method fromBytes (line 92) | @Override
      method targetsServer (line 103) | public boolean targetsServer() {
    class ButtonActionHandler (line 108) | public static class ButtonActionHandler implements IMessageHandler<But...
      method onMessage (line 109) | @Override
    class Say (line 122) | @AllArgsConstructor
      method toBytes (line 128) | @Override
      method fromBytes (line 134) | @Override
    class SayHandler (line 141) | public static class SayHandler implements IMessageHandler<Say, IMessag...
      method onMessage (line 143) | @Override
    class BabyName (line 154) | @AllArgsConstructor
      method toBytes (line 159) | @Override
      method fromBytes (line 164) | @Override
    class BabyNameHandler (line 170) | public static class BabyNameHandler implements IMessageHandler<BabyNam...
      method onMessage (line 172) | @Override
    class CareerResponse (line 183) | @AllArgsConstructor
      method toBytes (line 190) | @Override
      method fromBytes (line 196) | @Override
    class CareerResponseHandler (line 203) | public static class CareerResponseHandler implements IMessageHandler<C...
      method onMessage (line 205) | @Override
    class CareerRequest (line 214) | @AllArgsConstructor
      method toBytes (line 219) | @Override
      method fromBytes (line 224) | @Override
    class CareerRequestHandler (line 230) | public static class CareerRequestHandler implements IMessageHandler<Ca...
      method onMessage (line 232) | @Override
    class InventoryRequest (line 258) | @AllArgsConstructor
      method toBytes (line 263) | @Override
      method fromBytes (line 268) | @Override
    class InventoryRequestHandler (line 274) | public static class InventoryRequestHandler implements IMessageHandler...
      method onMessage (line 276) | @Override
    class InventoryResponse (line 285) | @NoArgsConstructor
      method InventoryResponse (line 291) | public InventoryResponse(UUID entityUUID, InventoryMCA inventory) {
      method toBytes (line 297) | @Override
      method fromBytes (line 303) | @Override
    class InventoryResponseHandler (line 310) | public static class InventoryResponseHandler implements IMessageHandle...
      method onMessage (line 312) | @Override
    class SavedVillagersRequest (line 319) | public static class SavedVillagersRequest implements IMessage {
      method fromBytes (line 321) | @Override
      method toBytes (line 324) | @Override
    class SavedVillagersRequestHandler (line 328) | public static class SavedVillagersRequestHandler implements IMessageHa...
      method onMessage (line 330) | @Override
    class SavedVillagersResponse (line 336) | @NoArgsConstructor
      method SavedVillagersResponse (line 340) | public SavedVillagersResponse(EntityPlayer player) {
      method toBytes (line 344) | @Override
      method fromBytes (line 353) | @Override
    class SavedVillagersResponseHandler (line 364) | public static class SavedVillagersResponseHandler implements IMessageH...
      method onMessage (line 366) | @Override
    class ReviveVillager (line 374) | @AllArgsConstructor
      method toBytes (line 379) | @Override
      method fromBytes (line 384) | @Override
    class ReviveVillagerHandler (line 390) | public static class ReviveVillagerHandler implements IMessageHandler<R...
      method onMessage (line 392) | @Override
    class SetName (line 413) | @AllArgsConstructor
      method toBytes (line 419) | @Override
      method fromBytes (line 425) | @Override
    class SetNameHandler (line 432) | public static class SetNameHandler implements IMessageHandler<SetName,...
      method onMessage (line 434) | @Override
    class SpawnParticles (line 447) | @AllArgsConstructor
      method toBytes (line 453) | @Override
      method fromBytes (line 459) | @Override
    class SpawnParticlesHandler (line 466) | public static class SpawnParticlesHandler implements IMessageHandler<S...
      method onMessage (line 467) | @Override
    class GetFamily (line 480) | @NoArgsConstructor
      method toBytes (line 482) | @Override
      method fromBytes (line 485) | @Override
    class GetFamilyHandler (line 489) | public static class GetFamilyHandler implements IMessageHandler<GetFam...
      method onMessage (line 490) | @Override
    class GetFamilyResponse (line 506) | @AllArgsConstructor
      method toBytes (line 511) | @Override
      method fromBytes (line 517) | @Override
    class GetFamilyResponseHandler (line 527) | public static class GetFamilyResponseHandler implements IMessageHandle...
      method onMessage (line 528) | @Override
    class CallToPlayer (line 539) | @AllArgsConstructor
      method toBytes (line 544) | @Override
      method fromBytes (line 549) | @Override
    class CallToPlayerHandler (line 555) | public static class CallToPlayerHandler implements IMessageHandler<Cal...
      method onMessage (line 556) | @Override
    class SetProfession (line 568) | @AllArgsConstructor
      method toBytes (line 574) | @Override
      method fromBytes (line 580) | @Override
    class SetProfessionHandler (line 587) | public static class SetProfessionHandler implements IMessageHandler<Se...
      method onMessage (line 588) | @Override
    class SetTexture (line 625) | @AllArgsConstructor
      method toBytes (line 631) | @Override
      method fromBytes (line 637) | @Override
    class SetTextureHandler (line 644) | public static class SetTextureHandler implements IMessageHandler<SetTe...
      method onMessage (line 645) | @Override

FILE: src/main/java/mca/core/forge/ServerProxy.java
  class ServerProxy (line 3) | public class ServerProxy {
    method registerEntityRenderers (line 4) | public void registerEntityRenderers() {
    method registerEventHandlers (line 8) | public void registerEventHandlers() {
    method registerModelMeshers (line 12) | public void registerModelMeshers() {

FILE: src/main/java/mca/core/minecraft/BlocksMCA.java
  class BlocksMCA (line 20) | public final class BlocksMCA {
    method register (line 27) | public static void register(RegistryEvent.Register<Block> event) {
    method registerItemBlocks (line 50) | public static void registerItemBlocks(RegistryEvent.Register<Item> eve...
    method setBlockName (line 65) | private static void setBlockName(Block block, String blockName) {
    method registerModelMeshers (line 70) | @SideOnly(Side.CLIENT)

FILE: src/main/java/mca/core/minecraft/ItemsMCA.java
  class ItemsMCA (line 23) | public final class ItemsMCA {
    method register (line 47) | public static void register(RegistryEvent.Register<Item> event) {
    method assignCreativeTabs (line 63) | public static void assignCreativeTabs() {
    method setBookNBT (line 67) | public static void setBookNBT(ItemStack stack) {
    method registerModelMeshers (line 262) | @SideOnly(Side.CLIENT)
    method setItemName (line 269) | private static void setItemName(Item item, String itemName) {

FILE: src/main/java/mca/core/minecraft/ProfessionsMCA.java
  class ProfessionsMCA (line 24) | @GameRegistry.ObjectHolder("mca")
    method registerCareers (line 48) | public static void registerCareers() {
    method getDefaultHeldItem (line 68) | public static ItemStack getDefaultHeldItem(VillagerProfession professi...
    method randomProfession (line 74) | public static VillagerProfession randomProfession() {
    class RegistrationHandler (line 83) | @Mod.EventBusSubscriber(modid = "mca")
      method onEvent (line 90) | @SubscribeEvent
    class BakerTradesLvl1 (line 101) | public static class BakerTradesLvl1 implements EntityVillager.ITradeLi...
      method addMerchantRecipe (line 103) | @Override
    class BakerTradesLvl2 (line 110) | public static class BakerTradesLvl2 implements EntityVillager.ITradeLi...
      method addMerchantRecipe (line 112) | @Override
    class BakerTradesLvl3 (line 120) | public static class BakerTradesLvl3 implements EntityVillager.ITradeLi...
      method addMerchantRecipe (line 122) | @Override
    class MinerTradesLvl1 (line 131) | public static class MinerTradesLvl1 implements EntityVillager.ITradeLi...
      method addMerchantRecipe (line 133) | @Override
    class MinerTradesLvl2 (line 140) | public static class MinerTradesLvl2 implements EntityVillager.ITradeLi...
      method addMerchantRecipe (line 142) | @Override
    class MinerTradesLvl3 (line 149) | public static class MinerTradesLvl3 implements EntityVillager.ITradeLi...
      method addMerchantRecipe (line 151) | @Override
    method inForbiddenProfessions (line 159) | private static boolean inForbiddenProfessions(VillagerProfession profI...

FILE: src/main/java/mca/core/minecraft/RoseGoldOreGenerator.java
  class RoseGoldOreGenerator (line 15) | public final class RoseGoldOreGenerator implements IWorldGenerator {
    method RoseGoldOreGenerator (line 16) | public RoseGoldOreGenerator() {
    method generate (line 19) | public void generate(Random random, int chunkX, int chunkZ, World worl...
    method generateSurface (line 23) | private void generateSurface(World world, Random random, int x, int z) {
    method addOreSpawn (line 27) | public void addOreSpawn(Block block, World world, Random random, int b...

FILE: src/main/java/mca/core/minecraft/SoundsMCA.java
  class SoundsMCA (line 8) | public final class SoundsMCA {
    method register (line 22) | public static void register(RegistryEvent.Register<SoundEvent> event) {

FILE: src/main/java/mca/core/minecraft/VillageHelper.java
  class VillageHelper (line 16) | public class VillageHelper {
    method tick (line 18) | public static void tick(World world) {
    method forceSpawnGuards (line 22) | public static void forceSpawnGuards(EntityPlayerMP player) {
    method forceRaid (line 27) | public static void forceRaid(EntityPlayerMP player) {
    method spawnGuards (line 32) | private static void spawnGuards(World world, Village village) {
    method startRaid (line 63) | private static void startRaid(World world, Village village) {
    method findRandomSpawnPos (line 75) | private static Vec3d findRandomSpawnPos(World world, Village village, ...
    method isAreaClearAround (line 86) | private static boolean isAreaClearAround(World world, BlockPos blockSi...

FILE: src/main/java/mca/core/minecraft/WorldEventListenerMCA.java
  class WorldEventListenerMCA (line 18) | public class WorldEventListenerMCA implements IWorldEventListener {
    method notifyBlockUpdate (line 19) | public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState...
    method notifyLightSet (line 22) | public void notifyLightSet(BlockPos pos) {
    method markBlockRangeForRenderUpdate (line 25) | public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int ...
    method playSoundToAllNearExcept (line 28) | public void playSoundToAllNearExcept(@Nullable EntityPlayer player, So...
    method playRecord (line 31) | public void playRecord(SoundEvent soundIn, BlockPos pos) {
    method spawnParticle (line 34) | public void spawnParticle(int particleID, boolean ignoreRange, double ...
    method spawnParticle (line 37) | public void spawnParticle(int id, boolean ignoreRange, boolean p_19057...
    method onEntityAdded (line 40) | public void onEntityAdded(Entity entityIn) {
    method onEntityRemoved (line 56) | public void onEntityRemoved(Entity entityIn) {
    method broadcastSound (line 59) | public void broadcastSound(int soundID, BlockPos pos, int data) {
    method playEvent (line 62) | public void playEvent(EntityPlayer player, int type, BlockPos blockPos...
    method sendBlockBreakProgress (line 65) | public void sendBlockBreakProgress(int breakerId, BlockPos pos, int pr...

FILE: src/main/java/mca/entity/EntityGrimReaper.java
  class EntityGrimReaper (line 37) | public class EntityGrimReaper extends EntityMob {
    method EntityGrimReaper (line 48) | public EntityGrimReaper(World world) {
    method applyEntityAttributes (line 61) | @Override
    method dropFewItems (line 70) | @Override
    method entityInit (line 75) | @Override
    method getAttackState (line 82) | public EnumReaperAttackState getAttackState() {
    method setAttackState (line 86) | public void setAttackState(EnumReaperAttackState state) {
    method hasEntityToAttack (line 102) | public boolean hasEntityToAttack() {
    method onStruckByLightning (line 106) | @Override
    method attackEntityFrom (line 111) | @Override
    method attackEntity (line 181) | protected void attackEntity(Entity entity, float damage) {
    method findPlayerToAttack (line 250) | protected Entity findPlayerToAttack() {
    method getTalkInterval (line 254) | @Override
    method getAmbientSound (line 259) | @Override
    method getDeathSound (line 264) | @Override
    method getHurtSound (line 269) | @Override
    method onUpdate (line 274) | @Override
    method onDeath (line 386) | @Override
    method getName (line 391) | @Override
    method canDespawn (line 396) | @Override
    method getStateTransitionCooldown (line 401) | public int getStateTransitionCooldown() {
    method setStateTransitionCooldown (line 405) | public void setStateTransitionCooldown(int value) {
    method getFloatingTicks (line 409) | public float getFloatingTicks() {
    method teleportTo (line 413) | private void teleportTo(double x, double y, double z) {
    method isNonBoss (line 421) | @Override
    method addTrackingPlayer (line 430) | @Override
    method removeTrackingPlayer (line 440) | @Override

FILE: src/main/java/mca/entity/EntityVillagerMCA.java
  class EntityVillagerMCA (line 66) | public class EntityVillagerMCA extends EntityVillager {
    method EntityVillagerMCA (line 110) | public EntityVillagerMCA() {
    method EntityVillagerMCA (line 115) | public EntityVillagerMCA(World worldIn) {
    method EntityVillagerMCA (line 120) | public EntityVillagerMCA(World worldIn, Optional<VillagerRegistry.Vill...
    method entityInit (line 135) | @Override
    method applyEntityAttributes (line 165) | @Override
    method get (line 176) | public <T> T get(DataParameter<T> key) {
    method set (line 180) | public <T> void set(DataParameter<T> key, T value) {
    method attackEntityAsMob (line 184) | @Override
    method readEntityFromNBT (line 190) | @Override
    method writeEntityToNBT (line 228) | @Override
    method damageEntity (line 267) | @Override
    method onUpdate (line 281) | @Override
    method getAmbientSound (line 294) | @Override
    method getHurtSound (line 299) | @Override
    method getDeathSound (line 304) | @Override
    method processInteract (line 309) | @Override
    method onDeath (line 315) | @Override
    method onGrowingAdult (line 359) | @Override
    method getDisplayName (line 376) | @Override
    method getCustomNameTag (line 388) | @Override
    method hasCustomName (line 394) | @Override
    method swingArm (line 400) | @Override
    method updateSwinging (line 411) | private void updateSwinging() {
    method getItemStackFromSlot (line 425) | @Override
    method setStartingAge (line 443) | public void setStartingAge(int value) {
    method getPlayerHistoryFor (line 448) | public PlayerHistory getPlayerHistoryFor(UUID uuid) {
    method updatePlayerHistoryMap (line 455) | public void updatePlayerHistoryMap(PlayerHistory history) {
    method reset (line 462) | public void reset() {
    method getVanillaCareer (line 474) | public VillagerRegistry.VillagerCareer getVanillaCareer() {
    method setVanillaCareer (line 478) | public void setVanillaCareer(int careerId) {
    method setSizeForAge (line 482) | private void setSizeForAge() {
    method toggleMount (line 488) | private void toggleMount(EntityPlayerMP player) {
    method goHome (line 502) | private void goHome(EntityPlayerMP player) {
    method getWorkplace (line 513) | public BlockPos getWorkplace() {
    method getHangout (line 517) | public BlockPos getHangout() {
    method forcePositionAsHome (line 525) | public void forcePositionAsHome() {
    method setHome (line 529) | private void setHome(EntityPlayerMP player) {
    method setWorkplace (line 543) | public void setWorkplace(EntityPlayerMP player) {
    method setHangout (line 548) | public void setHangout(EntityPlayerMP player) {
    method say (line 553) | public void say(Optional<EntityPlayer> player, String phraseId, @Nulla...
    method isMarried (line 577) | public boolean isMarried() {
    method isMarriedTo (line 581) | public boolean isMarriedTo(UUID uuid) {
    method marry (line 585) | public void marry(EntityPlayer player) {
    method endMarriage (line 591) | private void endMarriage() {
    method handleInteraction (line 597) | private void handleInteraction(EntityPlayerMP player, PlayerHistory hi...
    method handleButtonClick (line 618) | public void handleButtonClick(EntityPlayerMP player, String guiKey, St...
    method handleSpecialCaseGift (line 741) | private boolean handleSpecialCaseGift(EntityPlayer player, ItemStack s...
    method onEachClientUpdate (line 764) | private void onEachClientUpdate() {
    method onEachClientSecond (line 774) | private void onEachClientSecond() {
    method onEachServerUpdate (line 778) | private void onEachServerUpdate() {
    method onEachServerSecond (line 798) | private void onEachServerSecond() {
    method getTextureResourceLocation (line 820) | public ResourceLocation getTextureResourceLocation() {
    method initEntityAI (line 828) | @Override
    method applySpecialAI (line 846) | private void applySpecialAI() {
    method removeCertainTasks (line 875) | private void removeCertainTasks(Class typ) {
    method spawnParticles (line 888) | public void spawnParticles(EnumParticleTypes particleType) {
    method stopChore (line 901) | public void stopChore() {
    method startChore (line 906) | public void startChore(EnumChore chore, EntityPlayer player) {
    method playerIsParent (line 911) | public boolean playerIsParent(EntityPlayer player) {
    method getHomePosition (line 916) | @Override
    method detachHome (line 921) | @Override
    method getCurrentActivity (line 926) | public String getCurrentActivity() {
    method moveTowardsBlock (line 940) | public void moveTowardsBlock(BlockPos target) {
    method moveTowardsBlock (line 944) | public void moveTowardsBlock(BlockPos target, double speed) {
    method searchBed (line 960) | public BlockPos searchBed() {
    method getBedOrientationInDegrees (line 975) | @SideOnly(Side.CLIENT)
    method isSleeping (line 997) | public boolean isSleeping() {
    method updateSleeping (line 1001) | private void updateSleeping() {
    method setRenderOffsetForSleep (line 1034) | private void setRenderOffsetForSleep(EnumFacing bedDirection) {
    method startSleeping (line 1039) | public void startSleeping() {
    method stopSleeping (line 1053) | public void stopSleeping() {

FILE: src/main/java/mca/entity/ai/AbstractEntityAIChore.java
  class AbstractEntityAIChore (line 10) | public abstract class AbstractEntityAIChore extends EntityAIBase {
    method AbstractEntityAIChore (line 13) | public AbstractEntityAIChore(EntityVillagerMCA entityIn) {
    method updateTask (line 18) | @Override
    method getAssigningPlayer (line 28) | Optional<EntityPlayer> getAssigningPlayer() {

FILE: src/main/java/mca/entity/ai/EntityAIAgeBaby.java
  class EntityAIAgeBaby (line 10) | public class EntityAIAgeBaby extends EntityAIBase {
    method EntityAIAgeBaby (line 13) | public EntityAIAgeBaby(EntityVillagerMCA entityIn) {
    method shouldExecute (line 18) | public boolean shouldExecute() {
    method updateTask (line 22) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAIChopping.java
  class EntityAIChopping (line 18) | public class EntityAIChopping extends AbstractEntityAIChore {
    method EntityAIChopping (line 22) | public EntityAIChopping(EntityVillagerMCA entityIn) {
    method shouldExecute (line 27) | public boolean shouldExecute() {
    method updateTask (line 34) | public void updateTask() {
    method destroyTree (line 73) | private void destroyTree(BlockPos origin) {

FILE: src/main/java/mca/entity/ai/EntityAIDefendFromTarget.java
  class EntityAIDefendFromTarget (line 8) | public class EntityAIDefendFromTarget extends EntityAIBase {
    method EntityAIDefendFromTarget (line 13) | public EntityAIDefendFromTarget(EntityCreature creature) {
    method shouldExecute (line 18) | public boolean shouldExecute() {
    method shouldContinueExecuting (line 34) | public boolean shouldContinueExecuting() {
    method startExecuting (line 38) | public void startExecuting() {
    method resetTask (line 50) | public void resetTask() {
    method updateTask (line 53) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAIFishing.java
  class EntityAIFishing (line 18) | public class EntityAIFishing extends AbstractEntityAIChore {
    method EntityAIFishing (line 23) | public EntityAIFishing(EntityVillagerMCA entityIn) {
    method shouldExecute (line 28) | public boolean shouldExecute() {
    method updateTask (line 35) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAIGoHangout.java
  class EntityAIGoHangout (line 6) | public class EntityAIGoHangout extends AbstractEntityAIChore {
    method EntityAIGoHangout (line 9) | public EntityAIGoHangout(EntityVillagerMCA villagerIn) {
    method shouldExecute (line 14) | public boolean shouldExecute() {
    method shouldContinueExecuting (line 48) | public boolean shouldContinueExecuting() {
    method startExecuting (line 52) | public void startExecuting() {
    method updateTask (line 56) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAIGoWorkplace.java
  class EntityAIGoWorkplace (line 5) | public class EntityAIGoWorkplace extends AbstractEntityAIChore {
    method EntityAIGoWorkplace (line 8) | public EntityAIGoWorkplace(EntityVillagerMCA villagerIn) {
    method shouldExecute (line 13) | public boolean shouldExecute() {
    method shouldContinueExecuting (line 42) | public boolean shouldContinueExecuting() {
    method startExecuting (line 46) | public void startExecuting() {
    method updateTask (line 51) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAIHarvesting.java
  class EntityAIHarvesting (line 18) | public class EntityAIHarvesting extends AbstractEntityAIChore {
    method EntityAIHarvesting (line 22) | public EntityAIHarvesting(EntityVillagerMCA villagerIn) {
    method shouldExecute (line 27) | public boolean shouldExecute() {
    method shouldContinueExecuting (line 34) | public boolean shouldContinueExecuting() {
    method searchCrop (line 38) | private BlockPos searchCrop(int rangeX, int rangeY) {
    method startExecuting (line 53) | public void startExecuting() {

FILE: src/main/java/mca/entity/ai/EntityAIHunting.java
  class EntityAIHunting (line 15) | public class EntityAIHunting extends AbstractEntityAIChore {
    method EntityAIHunting (line 20) | public EntityAIHunting(EntityVillagerMCA entityIn) {
    method shouldExecute (line 25) | public boolean shouldExecute() {
    method updateTask (line 32) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAIMoveState.java
  class EntityAIMoveState (line 10) | public class EntityAIMoveState extends EntityAIBase {
    method EntityAIMoveState (line 13) | public EntityAIMoveState(EntityVillagerMCA entityIn) {
    method shouldExecute (line 18) | public boolean shouldExecute() {
    method updateTask (line 22) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAIProcreate.java
  class EntityAIProcreate (line 16) | @RequiredArgsConstructor
    method shouldExecute (line 21) | @Override
    method updateTask (line 26) | @Override

FILE: src/main/java/mca/entity/ai/EntityAIProspecting.java
  class EntityAIProspecting (line 13) | public class EntityAIProspecting extends AbstractEntityAIChore {
    method EntityAIProspecting (line 16) | public EntityAIProspecting(EntityVillagerMCA entityIn) {
    method shouldExecute (line 21) | public boolean shouldExecute() {
    method updateTask (line 28) | public void updateTask() {

FILE: src/main/java/mca/entity/ai/EntityAISleeping.java
  class EntityAISleeping (line 7) | public class EntityAISleeping extends AbstractEntityAIChore {
    method EntityAISleeping (line 10) | public EntityAISleeping(EntityVillagerMCA villagerIn) {
    method shouldExecute (line 15) | public boolean shouldExecute() {
    method shouldContinueExecuting (line 58) | public boolean shouldContinueExecuting() {
    method startExecuting (line 62) | public void startExecuting() {
    method resetTask (line 88) | public void resetTask() {
    method updateTask (line 95) | public void updateTask() {

FILE: src/main/java/mca/entity/data/ParentData.java
  class ParentData (line 14) | @Getter
    method fromNBT (line 21) | public static ParentData fromNBT(NBTTagCompound nbt) {
    method create (line 30) | public static ParentData create(UUID parent1UUID, UUID parent2UUID, St...
    method fromVillager (line 39) | public static ParentData fromVillager(EntityVillagerMCA villager) {
    method toNBT (line 48) | public NBTTagCompound toNBT() {
    method setParents (line 57) | public ParentData setParents(UUID parent1UUID, String parent1Name, UUI...
    method getParentEntity (line 65) | public Entity getParentEntity(World world, UUID uuid) {
    method getParentEntities (line 69) | public Entity[] getParentEntities(World world) {

FILE: src/main/java/mca/entity/data/PlayerHistory.java
  class PlayerHistory (line 11) | public class PlayerHistory {
    method PlayerHistory (line 21) | private PlayerHistory() {
    method getNew (line 30) | public static PlayerHistory getNew(EntityVillagerMCA villager, UUID uu...
    method fromNBT (line 43) | public static PlayerHistory fromNBT(EntityVillagerMCA villager, UUID u...
    method toNBT (line 57) | public NBTTagCompound toNBT() {
    method setHearts (line 69) | public void setHearts(int value) {
    method changeHearts (line 74) | public void changeHearts(int value) {
    method changeInteractionFatigue (line 79) | public void changeInteractionFatigue(int value) {
    method update (line 84) | public void update() {
    method setDialogueType (line 89) | public void setDialogueType(EnumDialogueType type) {

FILE: src/main/java/mca/entity/data/PlayerSaveData.java
  class PlayerSaveData (line 20) | @Getter
    method PlayerSaveData (line 29) | public PlayerSaveData(String id) {
    method get (line 33) | public static PlayerSaveData get(EntityPlayer player) {
    method getExisting (line 45) | public static PlayerSaveData getExisting(World world, UUID uuid) {
    method writeToNBT (line 49) | @Override
    method readFromNBT (line 58) | @Override
    method isMarriedOrEngaged (line 66) | public boolean isMarriedOrEngaged() {
    method marry (line 70) | public void marry(UUID uuid, String name) {
    method endMarriage (line 77) | public void endMarriage() {
    method setBabyPresent (line 84) | public void setBabyPresent(boolean value) {
    method reset (line 89) | public void reset() {
    method getDataFields (line 95) | public List<Field> getDataFields() {
    method dump (line 99) | public void dump(EntityPlayer player) {

FILE: src/main/java/mca/entity/data/SavedVillagers.java
  class SavedVillagers (line 15) | public class SavedVillagers extends WorldSavedData {
    method SavedVillagers (line 19) | public SavedVillagers(String id) {
    method get (line 23) | public static SavedVillagers get(World world) {
    method save (line 32) | public void save(EntityVillagerMCA villager) {
    method remove (line 37) | public void remove(UUID uuid) {
    method getMap (line 42) | public Map<String, NBTTagCompound> getMap() {
    method loadByUUID (line 46) | public NBTTagCompound loadByUUID(UUID uuid) {
    method writeToNBT (line 50) | @Override
    method readFromNBT (line 56) | @Override

FILE: src/main/java/mca/entity/inventory/InventoryMCA.java
  class InventoryMCA (line 16) | public class InventoryMCA extends InventoryBasic {
    method InventoryMCA (line 19) | public InventoryMCA(EntityVillagerMCA villager) {
    method getFirstSlotContainingItem (line 24) | public int getFirstSlotContainingItem(Item item) {
    method contains (line 33) | public boolean contains(Class clazz) {
    method getBestItemOfType (line 49) | public ItemStack getBestItemOfType(@Nullable Class type) {
    method getBestArmorOfType (line 54) | public ItemStack getBestArmorOfType(EntityEquipmentSlot slot) {
    method getBestItemOfTypeSlot (line 76) | public int getBestItemOfTypeSlot(Class type) {
    method dropAllItems (line 94) | public void dropAllItems() {
    method readInventoryFromNBT (line 101) | public void readInventoryFromNBT(NBTTagList tagList) {
    method writeInventoryToNBT (line 116) | public NBTTagList writeInventoryToNBT() {

FILE: src/main/java/mca/enums/EnumAgeState.java
  type EnumAgeState (line 10) | @AllArgsConstructor
    method byId (line 25) | public static EnumAgeState byId(int id) {
    method byCurrentAge (line 30) | public static EnumAgeState byCurrentAge(int startingAge, int growingAg...
    method localizedName (line 39) | public String localizedName() {

FILE: src/main/java/mca/enums/EnumChore.java
  type EnumChore (line 11) | @AllArgsConstructor
    method byId (line 24) | public static EnumChore byId(int id) {
    method getFriendlyName (line 29) | public String getFriendlyName() {

FILE: src/main/java/mca/enums/EnumConstraint.java
  type EnumConstraint (line 11) | @AllArgsConstructor
    method fromStringList (line 23) | public static List<EnumConstraint> fromStringList(String constraints) {
    method byValue (line 40) | public static EnumConstraint byValue(String value) {

FILE: src/main/java/mca/enums/EnumDialogueType.java
  type EnumDialogueType (line 8) | @AllArgsConstructor
    method byValue (line 18) | public static EnumDialogueType byValue(String value) {

FILE: src/main/java/mca/enums/EnumGender.java
  type EnumGender (line 10) | @AllArgsConstructor
    method byId (line 20) | public static EnumGender byId(int id) {
    method getRandom (line 25) | public static EnumGender getRandom() {
    method byName (line 29) | public static EnumGender byName(String name) {

FILE: src/main/java/mca/enums/EnumMarriageState.java
  type EnumMarriageState (line 9) | @AllArgsConstructor
    method byId (line 18) | public static EnumMarriageState byId(int id) {

FILE: src/main/java/mca/enums/EnumMoveState.java
  type EnumMoveState (line 9) | @AllArgsConstructor
    method byId (line 18) | public static EnumMoveState byId(int id) {
    method getFriendlyName (line 22) | public String getFriendlyName() {

FILE: src/main/java/mca/enums/EnumReaperAttackState.java
  type EnumReaperAttackState (line 8) | @AllArgsConstructor
    method fromId (line 19) | public static EnumReaperAttackState fromId(int id) {

FILE: src/main/java/mca/items/ItemBaby.java
  class ItemBaby (line 33) | public class ItemBaby extends Item {
    method ItemBaby (line 36) | public ItemBaby(boolean isMale) {
    method onUpdate (line 41) | @Override
    method onItemRightClick (line 62) | @Override
    method getBabyName (line 98) | private String getBabyName(ItemStack stack) {
    method onEntityItemUpdate (line 102) | @Override
    method addInformation (line 111) | @SideOnly(Side.CLIENT)
    method updateBabyGrowth (line 138) | private void updateBabyGrowth(ItemStack itemStack) {
    method isReadyToGrowUp (line 146) | private boolean isReadyToGrowUp(ItemStack itemStack) {
    method getGender (line 150) | public EnumGender getGender() {

FILE: src/main/java/mca/items/ItemEngagementRing.java
  class ItemEngagementRing (line 14) | public class ItemEngagementRing extends ItemWeddingRing {
    method handle (line 15) | public boolean handle(EntityPlayer player, EntityVillagerMCA villager) {
    method addInformation (line 19) | @SideOnly(Side.CLIENT)

FILE: src/main/java/mca/items/ItemGuideBook.java
  class ItemGuideBook (line 24) | public class ItemGuideBook extends ItemWrittenBook {
    method ItemGuideBook (line 26) | public ItemGuideBook() {
    method onUpdate (line 30) | @Override
    method onItemRightClick (line 37) | @Override
    method resolveContents (line 46) | private void resolveContents(ItemStack stack, EntityPlayer player) {

FILE: src/main/java/mca/items/ItemMatchmakersRing.java
  class ItemMatchmakersRing (line 13) | public class ItemMatchmakersRing extends ItemSpecialCaseGift {
    method handle (line 14) | public boolean handle(EntityPlayer player, EntityVillagerMCA villager) {

FILE: src/main/java/mca/items/ItemSpawnEgg.java
  class ItemSpawnEgg (line 15) | public class ItemSpawnEgg extends Item {
    method ItemSpawnEgg (line 18) | public ItemSpawnEgg(boolean isMale) {
    method onItemUse (line 23) | @Override

FILE: src/main/java/mca/items/ItemSpecialCaseGift.java
  class ItemSpecialCaseGift (line 7) | public abstract class ItemSpecialCaseGift extends Item {
    method handle (line 8) | public abstract boolean handle(EntityPlayer player, EntityVillagerMCA ...

FILE: src/main/java/mca/items/ItemStaffOfLife.java
  class ItemStaffOfLife (line 20) | public class ItemStaffOfLife extends Item {
    method ItemStaffOfLife (line 21) | public ItemStaffOfLife() {
    method onItemRightClick (line 28) | @Override
    method addInformation (line 37) | @Override
    method hasEffect (line 47) | @SideOnly(Side.CLIENT)

FILE: src/main/java/mca/items/ItemVillagerEditor.java
  class ItemVillagerEditor (line 8) | public class ItemVillagerEditor extends Item {
    method ItemVillagerEditor (line 10) | public ItemVillagerEditor() {
    method hasEffect (line 17) | @SideOnly(Side.CLIENT)

FILE: src/main/java/mca/items/ItemWeddingRing.java
  class ItemWeddingRing (line 12) | public class ItemWeddingRing extends ItemSpecialCaseGift {
    method handle (line 13) | public boolean handle(EntityPlayer player, EntityVillagerMCA villager) {

FILE: src/main/java/mca/items/ItemWhistle.java
  class ItemWhistle (line 15) | public class ItemWhistle extends Item {
    method ItemWhistle (line 16) | public ItemWhistle() {
    method onItemRightClick (line 21) | @Override
    method addInformation (line 27) | @Override

FILE: src/main/java/mca/server/ServerMessageHandler.java
  class ServerMessageHandler (line 8) | public class ServerMessageHandler {
    method handleMessage (line 10) | public static void handleMessage(EntityPlayerMP player, NetMCA.ButtonA...
    method startRaid (line 24) | private static void startRaid(EntityPlayerMP player) {
    method spawnGuards (line 29) | private static void spawnGuards(EntityPlayerMP player) {
    method rebuildVillage (line 34) | private static void rebuildVillage(EntityPlayerMP player) {

FILE: src/main/java/mca/util/ItemStackCache.java
  class ItemStackCache (line 9) | public class ItemStackCache {
    method get (line 12) | public static ItemStack get(Item item) {

FILE: src/main/java/mca/util/ResourceLocationCache.java
  class ResourceLocationCache (line 8) | public class ResourceLocationCache {
    method getResourceLocationFor (line 11) | public static ResourceLocation getResourceLocationFor(String location) {

FILE: src/main/java/mca/util/Util.java
  class Util (line 25) | public class Util {
    method getSpawnSafeTopLevel (line 37) | public static int getSpawnSafeTopLevel(World world, int x, int y, int z)
    method readResource (line 48) | public static String readResource(String path) {
    method readResourceAsJSON (line 61) | public static <T> T readResourceAsJSON(String path, Class<T> type) {
    method getEntityByUUID (line 67) | public static Optional<Entity> getEntityByUUID(World world, UUID uuid) {
    method getEntityByUUID (line 76) | public static <T extends Entity> Optional<T> getEntityByUUID(World wor...
    method getNearbyBlocks (line 85) | public static List<BlockPos> getNearbyBlocks(BlockPos origin, World wo...
    method getNearestPoint (line 104) | public static BlockPos getNearestPoint(BlockPos origin, List<BlockPos>...
    method httpGet (line 118) | public static String httpGet(String url) {
Condensed preview — 150 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (636K chars).
[
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.md",
    "chars": 1097,
    "preview": "---\nname: Bug Report\nabout: Found a bug that you wish to tell us about? Start here. [MCA 6.0.0+ ONLY]\ntitle: ''\nlabels: "
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature-change-request.md",
    "chars": 804,
    "preview": "---\nname: Feature Change Request\nabout: Suggest your idea for MCA relating to a current problem in the mod.\ntitle: \"[REQ"
  },
  {
    "path": ".gitignore",
    "chars": 152,
    "preview": "# eclipse\nbin\n*.launch\n.settings\n.metadata\n.classpath\n.project\n\n# idea\nout\n*.ipr\n*.iws\n*.iml\n.idea\n\n# gradle\nbuild\n.grad"
  },
  {
    "path": "CHANGELOG",
    "chars": 3725,
    "preview": "6.0.1\nFeature: Whistle to call your family has been added back into the game.\nFeature: Special skins for naming your chi"
  },
  {
    "path": "LICENSE",
    "chars": 35149,
    "preview": "                    GNU GENERAL PUBLIC LICENSE\n                       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free "
  },
  {
    "path": "README.md",
    "chars": 1382,
    "preview": "Minecraft Comes Alive\n=====================\nMinecraft Comes Alive (MCA) is a Minecraft mod that replaces Minecraft's vil"
  },
  {
    "path": "build.gradle",
    "chars": 3148,
    "preview": "buildscript {\n    repositories {\n        mavenCentral()\n        jcenter()\n        maven { url = \"http://files.minecraftf"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 237,
    "preview": "#Tue Jun 18 00:42:38 PDT 2019\r\ndistributionBase=GRADLE_USER_HOME\r\ndistributionPath=wrapper/dists\r\nzipStoreBase=GRADLE_US"
  },
  {
    "path": "gradle.properties",
    "chars": 213,
    "preview": "# Sets default memory used for gradle commands. Can be overridden by user or command line properties.\n# This is required"
  },
  {
    "path": "gradlew",
    "chars": 5080,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2404,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "src/main/java/mca/api/API.java",
    "chars": 9643,
    "preview": "package mca.api;\n\nimport com.google.common.base.Charsets;\nimport mca.api.types.APIButton;\nimport mca.api.types.Gift;\nimp"
  },
  {
    "path": "src/main/java/mca/api/types/APIButton.java",
    "chars": 2822,
    "preview": "package mca.api.types;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport mca.entity.EntityVillagerMCA;\nimp"
  },
  {
    "path": "src/main/java/mca/api/types/Gift.java",
    "chars": 868,
    "preview": "package mca.api.types;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport mca.core.MCA;\nimport net.minecraf"
  },
  {
    "path": "src/main/java/mca/api/types/SkinsGroup.java",
    "chars": 345,
    "preview": "package mca.api.types;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport mca.enums.EnumGender;\n\n@AllArgsCo"
  },
  {
    "path": "src/main/java/mca/blocks/BlockVillagerSpawner.java",
    "chars": 1858,
    "preview": "package mca.blocks;\n\nimport com.google.common.base.Optional;\nimport mca.core.MCA;\nimport mca.entity.EntityVillagerMCA;\ni"
  },
  {
    "path": "src/main/java/mca/client/MCAGuiFactory.java",
    "chars": 656,
    "preview": "package mca.client;\n\nimport mca.client.gui.GuiConfigPage;\nimport net.minecraft.client.Minecraft;\nimport net.minecraft.cl"
  },
  {
    "path": "src/main/java/mca/client/gui/GuiConfigPage.java",
    "chars": 803,
    "preview": "package mca.client.gui;\n\nimport mca.core.MCA;\nimport net.minecraft.client.gui.GuiScreen;\nimport net.minecraftforge.fml.c"
  },
  {
    "path": "src/main/java/mca/client/gui/GuiInteract.java",
    "chars": 10289,
    "preview": "package mca.client.gui;\n\nimport mca.api.API;\nimport mca.client.gui.component.GuiButtonEx;\nimport mca.core.Constants;\nimp"
  },
  {
    "path": "src/main/java/mca/client/gui/GuiNameBaby.java",
    "chars": 3109,
    "preview": "package mca.client.gui;\n\nimport mca.api.API;\nimport mca.core.MCA;\nimport mca.core.forge.NetMCA;\nimport mca.items.ItemBab"
  },
  {
    "path": "src/main/java/mca/client/gui/GuiStaffOfLife.java",
    "chars": 3858,
    "preview": "package mca.client.gui;\n\nimport mca.core.MCA;\nimport mca.core.forge.NetMCA;\nimport mca.entity.EntityVillagerMCA;\nimport "
  },
  {
    "path": "src/main/java/mca/client/gui/GuiVillagerEditor.java",
    "chars": 5558,
    "preview": "package mca.client.gui;\n\nimport mca.api.API;\nimport mca.api.types.APIButton;\nimport mca.client.gui.component.GuiButtonEx"
  },
  {
    "path": "src/main/java/mca/client/gui/GuiWhistle.java",
    "chars": 5515,
    "preview": "package mca.client.gui;\n\nimport lombok.NonNull;\nimport mca.core.forge.NetMCA;\nimport net.minecraft.nbt.NBTTagCompound;\ni"
  },
  {
    "path": "src/main/java/mca/client/gui/component/GuiButtonEx.java",
    "chars": 597,
    "preview": "package mca.client.gui.component;\n\nimport lombok.Getter;\nimport mca.api.types.APIButton;\nimport mca.core.MCA;\nimport net"
  },
  {
    "path": "src/main/java/mca/client/model/ModelGrimReaper.java",
    "chars": 18139,
    "preview": "package mca.client.model;\n\nimport mca.entity.EntityGrimReaper;\nimport mca.enums.EnumReaperAttackState;\nimport net.minecr"
  },
  {
    "path": "src/main/java/mca/client/model/ModelVillagerMCA.java",
    "chars": 1477,
    "preview": "package mca.client.model;\n\nimport mca.enums.EnumGender;\nimport org.lwjgl.opengl.GL11;\n\nimport mca.entity.EntityVillagerM"
  },
  {
    "path": "src/main/java/mca/client/network/ClientMessageQueue.java",
    "chars": 2983,
    "preview": "package mca.client.network;\n\nimport mca.core.MCA;\nimport mca.core.forge.NetMCA;\nimport mca.entity.EntityVillagerMCA;\nimp"
  },
  {
    "path": "src/main/java/mca/client/render/RenderGrimReaper.java",
    "chars": 1126,
    "preview": "package mca.client.render;\n\nimport mca.client.model.ModelGrimReaper;\nimport mca.entity.EntityGrimReaper;\nimport net.mine"
  },
  {
    "path": "src/main/java/mca/client/render/RenderReaperFactory.java",
    "chars": 552,
    "preview": "package mca.client.render;\n\nimport mca.entity.EntityGrimReaper;\nimport net.minecraft.client.renderer.entity.Render;\nimpo"
  },
  {
    "path": "src/main/java/mca/client/render/RenderVillagerFactory.java",
    "chars": 562,
    "preview": "package mca.client.render;\n\nimport mca.entity.EntityVillagerMCA;\nimport net.minecraft.client.renderer.entity.Render;\nimp"
  },
  {
    "path": "src/main/java/mca/client/render/RenderVillagerMCA.java",
    "chars": 6063,
    "preview": "package mca.client.render;\n\nimport mca.client.model.ModelVillagerMCA;\nimport mca.entity.EntityVillagerMCA;\nimport mca.en"
  },
  {
    "path": "src/main/java/mca/command/CommandAdminMCA.java",
    "chars": 10734,
    "preview": "package mca.command;\n\nimport com.google.common.base.Optional;\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport mca"
  },
  {
    "path": "src/main/java/mca/command/CommandMCA.java",
    "chars": 5579,
    "preview": "package mca.command;\n\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport mca.core.MCAServer;\nimport net.minecraft.co"
  },
  {
    "path": "src/main/java/mca/core/Config.java",
    "chars": 5461,
    "preview": "package mca.core;\n\nimport net.minecraftforge.common.config.ConfigElement;\nimport net.minecraftforge.common.config.Config"
  },
  {
    "path": "src/main/java/mca/core/Constants.java",
    "chars": 2194,
    "preview": "package mca.core;\n\nimport java.util.UUID;\n\npublic class Constants {\n    public static final int GUI_ID_INTERACT = 1;\n   "
  },
  {
    "path": "src/main/java/mca/core/Localizer.java",
    "chars": 2580,
    "preview": "package mca.core;\n\nimport com.google.common.base.Charsets;\nimport net.minecraft.util.StringUtils;\nimport org.apache.comm"
  },
  {
    "path": "src/main/java/mca/core/MCA.java",
    "chars": 8187,
    "preview": "package mca.core;\n\nimport com.google.gson.Gson;\nimport mca.api.API;\nimport mca.command.CommandAdminMCA;\nimport mca.comma"
  },
  {
    "path": "src/main/java/mca/core/MCAServer.java",
    "chars": 12213,
    "preview": "package mca.core;\n\nimport mca.core.minecraft.ItemsMCA;\nimport mca.core.minecraft.VillageHelper;\nimport mca.entity.Entity"
  },
  {
    "path": "src/main/java/mca/core/forge/ClientProxy.java",
    "chars": 816,
    "preview": "package mca.core.forge;\n\nimport mca.client.render.RenderReaperFactory;\nimport mca.client.render.RenderVillagerFactory;\ni"
  },
  {
    "path": "src/main/java/mca/core/forge/EventHooks.java",
    "chars": 11330,
    "preview": "package mca.core.forge;\n\nimport mca.client.network.ClientMessageQueue;\nimport mca.core.Constants;\nimport mca.core.MCA;\ni"
  },
  {
    "path": "src/main/java/mca/core/forge/GuiHandler.java",
    "chars": 2391,
    "preview": "package mca.core.forge;\n\nimport mca.client.gui.*;\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport mca.entity.Enti"
  },
  {
    "path": "src/main/java/mca/core/forge/NetMCA.java",
    "chars": 25770,
    "preview": "package mca.core.forge;\n\nimport io.netty.buffer.ByteBuf;\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport "
  },
  {
    "path": "src/main/java/mca/core/forge/ServerProxy.java",
    "chars": 240,
    "preview": "package mca.core.forge;\n\npublic class ServerProxy {\n    public void registerEntityRenderers() {\n        // Server-side, "
  },
  {
    "path": "src/main/java/mca/core/minecraft/BlocksMCA.java",
    "chars": 2970,
    "preview": "package mca.core.minecraft;\n\nimport mca.blocks.BlockVillagerSpawner;\nimport mca.core.MCA;\nimport net.minecraft.block.Blo"
  },
  {
    "path": "src/main/java/mca/core/minecraft/ItemsMCA.java",
    "chars": 16571,
    "preview": "package mca.core.minecraft;\n\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport mca.items.*;\nimport net.minecraft.cl"
  },
  {
    "path": "src/main/java/mca/core/minecraft/ProfessionsMCA.java",
    "chars": 8417,
    "preview": "package mca.core.minecraft;\n\nimport mca.util.ItemStackCache;\nimport mca.util.ResourceLocationCache;\nimport net.minecraft"
  },
  {
    "path": "src/main/java/mca/core/minecraft/RoseGoldOreGenerator.java",
    "chars": 1620,
    "preview": "package mca.core.minecraft;\n\nimport mca.core.MCA;\nimport net.minecraft.block.Block;\nimport net.minecraft.init.Blocks;\nim"
  },
  {
    "path": "src/main/java/mca/core/minecraft/SoundsMCA.java",
    "chars": 2184,
    "preview": "package mca.core.minecraft;\n\nimport net.minecraft.util.ResourceLocation;\nimport net.minecraft.util.SoundEvent;\nimport ne"
  },
  {
    "path": "src/main/java/mca/core/minecraft/VillageHelper.java",
    "chars": 4605,
    "preview": "package mca.core.minecraft;\n\nimport com.google.common.base.Optional;\nimport mca.core.MCA;\nimport mca.entity.EntityVillag"
  },
  {
    "path": "src/main/java/mca/core/minecraft/WorldEventListenerMCA.java",
    "chars": 3311,
    "preview": "package mca.core.minecraft;\n\nimport mca.core.forge.NetMCA;\nimport mca.entity.EntityVillagerMCA;\nimport net.minecraft.blo"
  },
  {
    "path": "src/main/java/mca/entity/EntityGrimReaper.java",
    "chars": 17849,
    "preview": "package mca.entity;\n\n\nimport mca.core.MCA;\nimport mca.core.minecraft.ItemsMCA;\nimport mca.core.minecraft.SoundsMCA;\nimpo"
  },
  {
    "path": "src/main/java/mca/entity/EntityVillagerMCA.java",
    "chars": 48697,
    "preview": "package mca.entity;\n\nimport com.google.common.base.Optional;\nimport com.google.common.base.Predicate;\nimport mca.api.API"
  },
  {
    "path": "src/main/java/mca/entity/ai/AbstractEntityAIChore.java",
    "chars": 1015,
    "preview": "package mca.entity.ai;\n\nimport com.google.common.base.Optional;\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport m"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIAgeBaby.java",
    "chars": 1208,
    "preview": "package mca.entity.ai;\n\nimport com.google.common.base.Optional;\nimport mca.core.MCA;\nimport mca.entity.EntityVillagerMCA"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIChopping.java",
    "chars": 3164,
    "preview": "package mca.entity.ai;\n\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumChore;\nimport mca.util.Util;\nimport ne"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIDefendFromTarget.java",
    "chars": 1572,
    "preview": "package mca.entity.ai;\n\nimport net.minecraft.entity.EntityCreature;\nimport net.minecraft.entity.EntityLivingBase;\nimport"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIFishing.java",
    "chars": 2780,
    "preview": "package mca.entity.ai;\n\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumChore;\nimport mca.util.Util;\nimport ne"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIGoHangout.java",
    "chars": 1621,
    "preview": "package mca.entity.ai;\n\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumChore;\n\npublic class EntityAIGoHangout"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIGoWorkplace.java",
    "chars": 1535,
    "preview": "package mca.entity.ai;\n\nimport mca.entity.EntityVillagerMCA;\n\npublic class EntityAIGoWorkplace extends AbstractEntityAIC"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIHarvesting.java",
    "chars": 5119,
    "preview": "package mca.entity.ai;\n\nimport mca.core.MCA;\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumChore;\nimport mca"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIHunting.java",
    "chars": 3072,
    "preview": "package mca.entity.ai;\n\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumChore;\nimport net.minecraft.entity.ite"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIMoveState.java",
    "chars": 1843,
    "preview": "package mca.entity.ai;\n\nimport mca.core.Constants;\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumMoveState;\n"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIProcreate.java",
    "chars": 1850,
    "preview": "package mca.entity.ai;\n\nimport lombok.RequiredArgsConstructor;\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport mc"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAIProspecting.java",
    "chars": 1872,
    "preview": "package mca.entity.ai;\n\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumChore;\nimport mca.util.Util;\nimport ne"
  },
  {
    "path": "src/main/java/mca/entity/ai/EntityAISleeping.java",
    "chars": 3604,
    "preview": "package mca.entity.ai;\n\nimport mca.core.minecraft.ProfessionsMCA;\nimport mca.entity.EntityVillagerMCA;\nimport net.minecr"
  },
  {
    "path": "src/main/java/mca/entity/data/ParentData.java",
    "chars": 2678,
    "preview": "package mca.entity.data;\n\nimport lombok.Getter;\nimport mca.core.Constants;\nimport mca.entity.EntityVillagerMCA;\nimport n"
  },
  {
    "path": "src/main/java/mca/entity/data/PlayerHistory.java",
    "chars": 2851,
    "preview": "package mca.entity.data;\n\nimport lombok.Getter;\nimport mca.core.Constants;\nimport mca.entity.EntityVillagerMCA;\nimport m"
  },
  {
    "path": "src/main/java/mca/entity/data/PlayerSaveData.java",
    "chars": 3383,
    "preview": "package mca.entity.data;\n\nimport lombok.Getter;\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport mca.enums.EnumMar"
  },
  {
    "path": "src/main/java/mca/entity/data/SavedVillagers.java",
    "chars": 1711,
    "preview": "package mca.entity.data;\n\nimport mca.entity.EntityVillagerMCA;\nimport net.minecraft.nbt.NBTTagCompound;\nimport net.minec"
  },
  {
    "path": "src/main/java/mca/entity/inventory/InventoryMCA.java",
    "chars": 4314,
    "preview": "package mca.entity.inventory;\n\nimport mca.entity.EntityVillagerMCA;\nimport net.minecraft.inventory.EntityEquipmentSlot;\n"
  },
  {
    "path": "src/main/java/mca/enums/EnumAgeState.java",
    "chars": 1268,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport mca.core.MCA;\n\nimport java.util.Array"
  },
  {
    "path": "src/main/java/mca/enums/EnumChore.java",
    "chars": 893,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport mca.core.MCA;\nimport net.minecraft.it"
  },
  {
    "path": "src/main/java/mca/enums/EnumConstraint.java",
    "chars": 1135,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport java.util.ArrayList;\nimport java.uti"
  },
  {
    "path": "src/main/java/mca/enums/EnumDialogueType.java",
    "chars": 433,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport java.util.Arrays;\n\n@AllArgsConstruct"
  },
  {
    "path": "src/main/java/mca/enums/EnumGender.java",
    "chars": 844,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport java.util.Arrays;\nimport java.util.O"
  },
  {
    "path": "src/main/java/mca/enums/EnumMarriageState.java",
    "chars": 465,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport java.util.Arrays;\nimport java.util.O"
  },
  {
    "path": "src/main/java/mca/enums/EnumMoveState.java",
    "chars": 556,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\nimport mca.core.MCA;\n\nimport java.util.Array"
  },
  {
    "path": "src/main/java/mca/enums/EnumReaperAttackState.java",
    "chars": 400,
    "preview": "package mca.enums;\n\nimport lombok.AllArgsConstructor;\nimport lombok.Getter;\n\nimport java.util.Arrays;\n\n@AllArgsConstruct"
  },
  {
    "path": "src/main/java/mca/items/ItemBaby.java",
    "chars": 6939,
    "preview": "package mca.items;\n\nimport com.google.common.base.Optional;\nimport mca.api.API;\nimport mca.core.Constants;\nimport mca.co"
  },
  {
    "path": "src/main/java/mca/items/ItemEngagementRing.java",
    "chars": 792,
    "preview": "package mca.items;\n\nimport mca.entity.EntityVillagerMCA;\nimport net.minecraft.client.util.ITooltipFlag;\nimport net.minec"
  },
  {
    "path": "src/main/java/mca/items/ItemGuideBook.java",
    "chars": 3352,
    "preview": "package mca.items;\n\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport mca.core.minecraft.ItemsMCA;\nimport net.minec"
  },
  {
    "path": "src/main/java/mca/items/ItemMatchmakersRing.java",
    "chars": 2503,
    "preview": "package mca.items;\n\nimport com.google.common.base.Optional;\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumMa"
  },
  {
    "path": "src/main/java/mca/items/ItemSpawnEgg.java",
    "chars": 1478,
    "preview": "package mca.items;\n\nimport com.google.common.base.Optional;\nimport mca.entity.EntityVillagerMCA;\nimport mca.enums.EnumGe"
  },
  {
    "path": "src/main/java/mca/items/ItemSpecialCaseGift.java",
    "chars": 283,
    "preview": "package mca.items;\n\nimport mca.entity.EntityVillagerMCA;\nimport net.minecraft.entity.player.EntityPlayer;\nimport net.min"
  },
  {
    "path": "src/main/java/mca/items/ItemStaffOfLife.java",
    "chars": 1978,
    "preview": "package mca.items;\n\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport net.minecraft.client.util.ITooltipFlag;\nimpor"
  },
  {
    "path": "src/main/java/mca/items/ItemVillagerEditor.java",
    "chars": 489,
    "preview": "package mca.items;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\nimport net.minecraftforge.fml.r"
  },
  {
    "path": "src/main/java/mca/items/ItemWeddingRing.java",
    "chars": 1802,
    "preview": "package mca.items;\n\nimport com.google.common.base.Optional;\nimport mca.core.MCA;\nimport mca.entity.EntityVillagerMCA;\nim"
  },
  {
    "path": "src/main/java/mca/items/ItemWhistle.java",
    "chars": 1072,
    "preview": "package mca.items;\n\nimport java.util.List;\n\nimport mca.core.Constants;\nimport mca.core.MCA;\nimport net.minecraft.client."
  },
  {
    "path": "src/main/java/mca/server/ServerMessageHandler.java",
    "chars": 1257,
    "preview": "package mca.server;\n\nimport mca.core.forge.NetMCA;\nimport mca.core.minecraft.VillageHelper;\nimport net.minecraft.entity."
  },
  {
    "path": "src/main/java/mca/util/ItemStackCache.java",
    "chars": 398,
    "preview": "package mca.util;\n\nimport net.minecraft.item.Item;\nimport net.minecraft.item.ItemStack;\n\nimport java.util.HashMap;\nimpor"
  },
  {
    "path": "src/main/java/mca/util/ResourceLocationCache.java",
    "chars": 552,
    "preview": "package mca.util;\n\nimport net.minecraft.util.ResourceLocation;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic "
  },
  {
    "path": "src/main/java/mca/util/Util.java",
    "chars": 4910,
    "preview": "package mca.util;\n\nimport com.google.common.base.Optional;\nimport com.google.gson.Gson;\nimport mca.core.MCA;\nimport net."
  },
  {
    "path": "src/main/resources/assets/mca/api/gifts.json",
    "chars": 7425,
    "preview": "[\n  {\"type\":\"item\", \"name\":\"minecraft:wooden_sword\", \"value\":3},\n  {\"type\":\"item\", \"name\":\"minecraft:wooden_axe\", \"value"
  },
  {
    "path": "src/main/resources/assets/mca/api/gui/debug.json",
    "chars": 3031,
    "preview": "[\n    {\n      \"id\": 1,\n      \"identifier\": \"gui.button.debug.startraid\",\n      \"x\": 120,\n      \"y\": -115,\n      \"width\":"
  },
  {
    "path": "src/main/resources/assets/mca/api/gui/editor.json",
    "chars": 1275,
    "preview": "[\n  {\n    \"id\": 1,\n    \"identifier\": \"gui.button.random\",\n    \"x\": -50,\n    \"y\": -95,\n    \"width\": 60,\n    \"height\": 20,"
  },
  {
    "path": "src/main/resources/assets/mca/api/gui/interact.json",
    "chars": 2210,
    "preview": "[\n    {\n      \"id\": 1,\n      \"identifier\": \"gui.button.backarrow\",\n      \"x\": 120,\n      \"y\": -115,\n      \"width\": 15,\n "
  },
  {
    "path": "src/main/resources/assets/mca/api/gui/location.json",
    "chars": 814,
    "preview": "[\n  {\n    \"id\": 1,\n    \"identifier\": \"gui.button.backarrow\",\n    \"x\": 140,\n    \"y\": -115,\n    \"width\": 65,\n    \"height\":"
  },
  {
    "path": "src/main/resources/assets/mca/api/gui/main.json",
    "chars": 2538,
    "preview": "[\n    {\n      \"id\": 1,\n      \"identifier\": \"gui.button.interact\",\n      \"x\": 140,\n      \"y\": -115,\n      \"width\": 65,\n  "
  },
  {
    "path": "src/main/resources/assets/mca/api/gui/work.json",
    "chars": 1572,
    "preview": "[\n    {\n      \"id\": 1,\n      \"identifier\": \"gui.button.backarrow\",\n      \"x\": 140,\n      \"y\": -115,\n      \"width\": 15,\n "
  },
  {
    "path": "src/main/resources/assets/mca/api/skins.json",
    "chars": 14591,
    "preview": "[\n  {\n    \"gender\": \"male\",\n    \"profession\": \"minecraft:farmer\",\n    \"paths\": [\n        \"mca:skins/male/farmer/farmerm1"
  },
  {
    "path": "src/main/resources/assets/mca/blockstates/rose_gold_block.json",
    "chars": 131,
    "preview": "{\n\t\"forge_marker\": 1,\n\t\"defaults\": {\n\t\t\"model\": \"mca:rose_gold_block\"\n\t},\n\t\"variants\": {\n\t\t\"normal\": [{}],\n\t\t\"inventory\""
  },
  {
    "path": "src/main/resources/assets/mca/blockstates/rose_gold_ore.json",
    "chars": 129,
    "preview": "{\n\t\"forge_marker\": 1,\n\t\"defaults\": {\n\t\t\"model\": \"mca:rose_gold_ore\"\n\t},\n\t\"variants\": {\n\t\t\"normal\": [{}],\n\t\t\"inventory\": "
  },
  {
    "path": "src/main/resources/assets/mca/blockstates/villager_spawner.json",
    "chars": 132,
    "preview": "{\n\t\"forge_marker\": 1,\n\t\"defaults\": {\n\t\t\"model\": \"mca:villager_spawner\"\n\t},\n\t\"variants\": {\n\t\t\"normal\": [{}],\n\t\t\"inventory"
  },
  {
    "path": "src/main/resources/assets/mca/lang/en_us.lang",
    "chars": 33673,
    "preview": "#X-Generator: crowdin.com\nitemGroup.MCA=Minecraft Comes Alive\n\nenum.agestate.baby=Baby\nenum.agestate.toddler=Toddler\nenu"
  },
  {
    "path": "src/main/resources/assets/mca/lang/names.lang",
    "chars": 123911,
    "preview": "name.male1=Aaron\nname.male2=Abdul\nname.male3=Abe\nname.male4=Abel\nname.male5=Abraham\nname.male6=Abram\nname.male7=Adalbert"
  },
  {
    "path": "src/main/resources/assets/mca/models/block/rose_gold_block.json",
    "chars": 88,
    "preview": "{\n\t\"parent\": \"block/cube_all\",\n\t\"textures\": {\n\t\t\"all\": \"mca:blocks/rose_gold_block\"\n\t}\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/block/rose_gold_ore.json",
    "chars": 86,
    "preview": "{\n\t\"parent\": \"block/cube_all\",\n\t\"textures\": {\n\t\t\"all\": \"mca:blocks/rose_gold_ore\"\n\t}\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/block/villager_spawner.json",
    "chars": 89,
    "preview": "{\n\t\"parent\": \"block/cube_all\",\n\t\"textures\": {\n\t\t\"all\": \"mca:blocks/villager_spawner\"\n\t}\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/baby_boy.json",
    "chars": 88,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/baby_boy\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/baby_girl.json",
    "chars": 89,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/baby_girl\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/book_death.json",
    "chars": 86,
    "preview": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"mca:items/book_death\"\n\t}\n}\n"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/book_family.json",
    "chars": 87,
    "preview": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"mca:items/book_family\"\n\t}\n}\n"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/book_infection.json",
    "chars": 90,
    "preview": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"mca:items/book_infection\"\n\t}\n}\n"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/book_romance.json",
    "chars": 88,
    "preview": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"mca:items/book_romance\"\n\t}\n}\n"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/book_rose_gold.json",
    "chars": 90,
    "preview": "{\n\t\"parent\": \"item/generated\",\n\t\"textures\": {\n\t\t\"layer0\": \"mca:items/book_rose_gold\"\n\t}\n}\n"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/egg_female.json",
    "chars": 90,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/egg_female\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/egg_male.json",
    "chars": 88,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/egg_male\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/engagement_ring.json",
    "chars": 95,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/engagement_ring\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/engagement_ring_rg.json",
    "chars": 98,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/engagement_ring_rg\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/gold_dust.json",
    "chars": 89,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/gold_dust\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/matchmakers_ring.json",
    "chars": 96,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/matchmakers_ring\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/rose_gold_block.json",
    "chars": 205,
    "preview": "{\n  \"parent\": \"mca:block/rose_gold_block\",\n  \"display\": {\n    \"thirdperson\": {\n      \"rotation\": [ 10, -45, 170 ],\n     "
  },
  {
    "path": "src/main/resources/assets/mca/models/item/rose_gold_dust.json",
    "chars": 94,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/rose_gold_dust\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/rose_gold_ingot.json",
    "chars": 95,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/rose_gold_ingot\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/staff_of_life.json",
    "chars": 93,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/staff_of_life\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/villager_editor.json",
    "chars": 95,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/villager_editor\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/wedding_ring.json",
    "chars": 92,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/wedding_ring\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/wedding_ring_rg.json",
    "chars": 95,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/wedding_ring_rg\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/models/item/whistle.json",
    "chars": 87,
    "preview": "{\n  \"parent\": \"item/generated\",\n  \"textures\": {\n    \"layer0\": \"mca:items/whistle\"\n  }\n}"
  },
  {
    "path": "src/main/resources/assets/mca/recipes/engagement_ring.json",
    "chars": 321,
    "preview": "\n{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GDG\",\n    \"G G\",\n    \"GGG\"\n  ],\n  \"key\": {\n    \"G\": [\n    "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/engagement_ring_rg.json",
    "chars": 322,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GDG\",\n    \"G G\",\n    \"GGG\"\n  ],\n  \"key\": {\n    \"G\": [\n     "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/gold_dust.json",
    "chars": 230,
    "preview": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"mca:rose_gold_dust\"\n    },\n    {\n   "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/gold_nugget_from_dust.json",
    "chars": 245,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GGG\",\n    \"GGG\",\n    \"GGG\"\n  ],\n  \"key\": {\n    \"G\": [\n     "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/matchmakers_ring.json",
    "chars": 251,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"III\",\n    \"I I\",\n    \"III\"\n  ],\n  \"key\": {\n    \"I\": [\n     "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/rose_gold_block.json",
    "chars": 249,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"III\",\n    \"III\",\n    \"III\"\n  ],\n  \"key\": {\n    \"I\": [\n     "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/rose_gold_dust_from_ingot.json",
    "chars": 184,
    "preview": "{\n  \"type\": \"minecraft:crafting_shapeless\",\n  \"ingredients\": [\n    {\n      \"item\": \"mca:rose_gold_ingot\"\n    }\n  ],\n  \"r"
  },
  {
    "path": "src/main/resources/assets/mca/recipes/rose_gold_ingot_from_dust.json",
    "chars": 248,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GGG\",\n    \"GGG\",\n    \"GGG\"\n  ],\n  \"key\": {\n    \"G\": [\n     "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/wedding_ring.json",
    "chars": 247,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GGG\",\n    \"G G\",\n    \"GGG\"\n  ],\n  \"key\": {\n    \"G\": [\n     "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/wedding_ring_rg.json",
    "chars": 249,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \"GGG\",\n    \"G G\",\n    \"GGG\"\n  ],\n  \"key\": {\n    \"G\": [\n     "
  },
  {
    "path": "src/main/resources/assets/mca/recipes/whistle.json",
    "chars": 693,
    "preview": "{\n  \"type\": \"minecraft:crafting_shaped\",\n  \"pattern\": [\n    \" W#\",\n    \"###\"\n  ],\n  \"key\": {\n    \"#\": [\n      {\n        "
  },
  {
    "path": "src/main/resources/assets/mca/sounds.json",
    "chars": 685,
    "preview": "{\n    \"reaper.scythe.out\": { \"category\": \"hostile\", \"subtitle\": \"Draws scythe\", \"sounds\": [ \"mca:reaper-scythe-out\" ] },"
  },
  {
    "path": "src/main/resources/mcmod.info",
    "chars": 448,
    "preview": "[\n{\n  \"modid\": \"mca\",\n  \"name\": \"Minecraft Comes Alive\",\n  \"description\": \"Replaces villagers with humans, adds marriage"
  },
  {
    "path": "src/main/resources/pack.mcmeta",
    "chars": 107,
    "preview": "{\n    \"pack\": {\n        \"description\": \"Minecraft Comes Alive resources\",\n        \"pack_format\": 3\n    }\n}\n"
  }
]

// ... and 7 more files (download for full content)

About this extraction

This page contains the full source code of the WildBamaBoy/minecraft-comes-alive GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 150 files (587.0 KB), approximately 168.9k tokens, and a symbol index with 669 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!