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. 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. Copyright (C) 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 . 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: Copyright (C) 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 . 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 . ================================================ 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 giftMap = new HashMap<>(); private static Map buttonMap = new HashMap<>(); private static List maleNames = new ArrayList<>(); private static List femaleNames = new ArrayList<>(); private static List 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 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 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 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 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 getButton(String id, GuiScreen screen) { List buttonList = ObfuscationReflectionHelper.getPrivateValue(GuiScreen.class, screen, Constants.GUI_SCREEN_BUTTON_LIST_FIELD_INDEX); Optional 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/* *

* 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 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 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 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 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 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 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 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 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 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 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 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 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 villager = getVillagerByUUID(player.world, msg.getEntityUUID()); villager.ifPresent(entityVillagerMCA -> entityVillagerMCA.inventory.readInventoryFromNBT(msg.getInventoryNBT().getTagList("inventory", 10))); } } private static Optional 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 extends RenderBiped { 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 { public static final RenderReaperFactory INSTANCE = new RenderReaperFactory(); @Override public Render 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 { public static final RenderVillagerFactory INSTANCE = new RenderVillagerFactory(); @Override public Render 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 extends RenderBiped { 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 "; } @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 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 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 " + Constants.Color.GOLD + " - Resets the given villager.", true); sendMessage(commandSender, Constants.Color.WHITE + " /mca-admin rpd " + 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 "; } @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 " + 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 " + Constants.Color.GOLD + " - Accepts the player's marriage request.", true); sendMessage(commandSender, Constants.Color.WHITE + " /mca reject " + 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 getCategories() { List 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 localizerMap = new HashMap<>(); private static final ArrayList EMPTY_LIST = new ArrayList<>(); public Localizer() { InputStream inStream = StringUtils.class.getResourceAsStream("/assets/mca/lang/en_us.lang"); try { List 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 list = new ArrayList<>(); Collections.addAll(list, vars); return localize(key, vars != null ? list : EMPTY_LIST); } public String localize(String key, ArrayList vars) { String result = localizerMap.getOrDefault(key, key); if (result.equals(key)) { List 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 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 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 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> proposals; // List of UUIDs that initiated procreation mapped to the time the request expires. private static Map 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 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 */ private List 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 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 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 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 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 limbo = new HashMap<>(); @SubscribeEvent public void onRegisterItems(RegistryEvent.Register 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 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 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(BabyNameHandler.class, BabyName.class, 2, Side.SERVER); INSTANCE.registerMessage(CareerResponseHandler.class, CareerResponse.class, 3, Side.CLIENT); INSTANCE.registerMessage(CareerRequestHandler.class, CareerRequest.class, 4, Side.SERVER); INSTANCE.registerMessage(InventoryRequestHandler.class, InventoryRequest.class, 5, Side.SERVER); INSTANCE.registerMessage(InventoryResponseHandler.class, InventoryResponse.class, 6, Side.CLIENT); INSTANCE.registerMessage(SavedVillagersRequestHandler.class, SavedVillagersRequest.class, 7, Side.SERVER); INSTANCE.registerMessage(SavedVillagersResponseHandler.class, SavedVillagersResponse.class, 8, Side.CLIENT); INSTANCE.registerMessage(ReviveVillagerHandler.class, ReviveVillager.class, 9, Side.SERVER); INSTANCE.registerMessage(SetNameHandler.class, SetName.class, 10, Side.SERVER); INSTANCE.registerMessage(SpawnParticlesHandler.class, SpawnParticles.class, 11, Side.CLIENT); INSTANCE.registerMessage(GetFamilyHandler.class, GetFamily.class, 12, Side.SERVER); INSTANCE.registerMessage(GetFamilyResponseHandler.class, GetFamilyResponse.class, 13, Side.CLIENT); INSTANCE.registerMessage(CallToPlayerHandler.class, CallToPlayer.class, 14, Side.SERVER); INSTANCE.registerMessage(SetTextureHandler.class, SetTexture.class, 15, Side.SERVER); INSTANCE.registerMessage(SetProfessionHandler.class, SetProfession.class, 16, Side.SERVER); } @SideOnly(Side.CLIENT) private static EntityPlayer getPlayerClient() { return Minecraft.getMinecraft().player; } @AllArgsConstructor @NoArgsConstructor @Getter public static class ButtonAction implements IMessage { private String guiKey; private String buttonId; private UUID targetUUID; @Override public void toBytes(ByteBuf buf) { buf.writeBoolean(targetUUID != null); ByteBufUtils.writeUTF8String(buf, this.guiKey); ByteBufUtils.writeUTF8String(buf, this.buttonId); if (targetUUID != null) { ByteBufUtils.writeUTF8String(buf, this.targetUUID.toString()); } } @Override public void fromBytes(ByteBuf buf) { boolean hasTarget = buf.readBoolean(); this.guiKey = ByteBufUtils.readUTF8String(buf); this.buttonId = ByteBufUtils.readUTF8String(buf); if (hasTarget) { this.targetUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); } } public boolean targetsServer() { return getTargetUUID() == null; } } public static class ButtonActionHandler implements IMessageHandler { @Override public IMessage onMessage(ButtonAction message, MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().player; // The message can target a particular villager, or the server itself. if (!message.targetsServer()) { EntityVillagerMCA villager = (EntityVillagerMCA) player.getServerWorld().getEntityFromUuid(message.targetUUID); if (villager != null) player.getServerWorld().addScheduledTask(() -> villager.handleButtonClick(player, message.guiKey, message.buttonId)); } else ServerMessageHandler.handleMessage(player, message); return null; } } @AllArgsConstructor @NoArgsConstructor public static class Say implements IMessage { private String phraseId; private int speakingEntityId; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, this.phraseId); buf.writeInt(this.speakingEntityId); } @Override public void fromBytes(ByteBuf buf) { this.phraseId = ByteBufUtils.readUTF8String(buf); this.speakingEntityId = buf.readInt(); } } public static class SayHandler implements IMessageHandler { @Override public IMessage onMessage(Say message, MessageContext ctx) { EntityPlayer player = getPlayerClient(); EntityVillagerMCA villager = (EntityVillagerMCA) player.getEntityWorld().getEntityByID(message.speakingEntityId); if (villager != null) villager.say(com.google.common.base.Optional.of(player), message.phraseId); return null; } } @AllArgsConstructor @NoArgsConstructor public static class BabyName implements IMessage { private String babyName; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, this.babyName); } @Override public void fromBytes(ByteBuf buf) { this.babyName = ByteBufUtils.readUTF8String(buf); } } public static class BabyNameHandler implements IMessageHandler { @Override public IMessage onMessage(BabyName message, MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().player; ItemStack stack = player.inventory.getStackInSlot(player.inventory.currentItem); if (stack.getItem() instanceof ItemBaby) stack.getTagCompound().setString("name", message.babyName); return null; } } @AllArgsConstructor @NoArgsConstructor @Getter public static class CareerResponse implements IMessage { private int careerId; private UUID entityUUID; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeVarInt(buf, careerId, 4); ByteBufUtils.writeUTF8String(buf, entityUUID.toString()); } @Override public void fromBytes(ByteBuf buf) { this.careerId = ByteBufUtils.readVarInt(buf, 4); this.entityUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); } } public static class CareerResponseHandler implements IMessageHandler { @Override public IMessage onMessage(CareerResponse message, MessageContext ctx) { // must be thrown in the queue and processed on the main thread since we must loop through the loaded entity list // it could change while looping and cause a ConcurrentModificationException. ClientMessageQueue.add(message); return null; } } @AllArgsConstructor @NoArgsConstructor public static class CareerRequest implements IMessage { private UUID entityUUID; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, entityUUID.toString()); } @Override public void fromBytes(ByteBuf buf) { this.entityUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); } } public static class CareerRequestHandler implements IMessageHandler { @Override public IMessage onMessage(CareerRequest message, MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().player; int careerId = -255; try { EntityVillagerMCA villager = (EntityVillagerMCA) player.getServerWorld().getEntityFromUuid(message.entityUUID); if (villager != null) careerId = ObfuscationReflectionHelper.getPrivateValue(EntityVillager.class, villager, EntityVillagerMCA.VANILLA_CAREER_ID_FIELD_INDEX); } catch (ClassCastException ignored) { MCA.getLog().error("UUID provided in career request does not match an MCA villager!: " + message.entityUUID.toString()); return null; } catch (NullPointerException ignored) { MCA.getLog().error("UUID provided in career request does not match a loaded MCA villager!: " + message.entityUUID.toString()); return null; } if (careerId == -255) { MCA.getLog().error("Career ID wasn't assigned for UUID: " + message.entityUUID); return null; } return new CareerResponse(careerId, message.entityUUID); } } @AllArgsConstructor @NoArgsConstructor public static class InventoryRequest implements IMessage { private UUID entityUUID; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, entityUUID.toString()); } @Override public void fromBytes(ByteBuf buf) { this.entityUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); } } public static class InventoryRequestHandler implements IMessageHandler { @Override public IMessage onMessage(InventoryRequest message, MessageContext ctx) { EntityPlayerMP player = ctx.getServerHandler().player; EntityVillagerMCA villager = (EntityVillagerMCA) player.getServerWorld().getEntityFromUuid(message.entityUUID); if (villager != null && villager.inventory != null) return new InventoryResponse(villager.getUniqueID(), villager.inventory); return null; } } @NoArgsConstructor @Getter public static class InventoryResponse implements IMessage { private UUID entityUUID; private NBTTagCompound inventoryNBT; public InventoryResponse(UUID entityUUID, InventoryMCA inventory) { this.inventoryNBT = new NBTTagCompound(); this.entityUUID = entityUUID; this.inventoryNBT.setTag("inventory", inventory.writeInventoryToNBT()); } @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, entityUUID.toString()); ByteBufUtils.writeTag(buf, inventoryNBT); } @Override public void fromBytes(ByteBuf buf) { this.entityUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); this.inventoryNBT = ByteBufUtils.readTag(buf); } } public static class InventoryResponseHandler implements IMessageHandler { @Override public IMessage onMessage(InventoryResponse message, MessageContext ctx) { ClientMessageQueue.add(message); return null; } } public static class SavedVillagersRequest implements IMessage { @Override public void fromBytes(ByteBuf buf) {} @Override public void toBytes(ByteBuf buf) {} } public static class SavedVillagersRequestHandler implements IMessageHandler { @Override public IMessage onMessage(SavedVillagersRequest message, MessageContext ctx) { return new SavedVillagersResponse(ctx.getServerHandler().player); } } @NoArgsConstructor public static class SavedVillagersResponse implements IMessage { private Map villagers = new HashMap<>(); public SavedVillagersResponse(EntityPlayer player) { villagers = SavedVillagers.get(player.world).getMap(); } @Override public void toBytes(ByteBuf buf) { buf.writeInt(villagers.size()); villagers.forEach((k,v) -> { ByteBufUtils.writeUTF8String(buf, k); ByteBufUtils.writeTag(buf, v); }); } @Override public void fromBytes(ByteBuf buf) { int size = buf.readInt(); for (int i = 0; i < size; i++) { String k = ByteBufUtils.readUTF8String(buf); NBTTagCompound v = ByteBufUtils.readTag(buf); villagers.put(k, v); } } } public static class SavedVillagersResponseHandler implements IMessageHandler { @Override public IMessage onMessage(SavedVillagersResponse message, MessageContext ctx) { GuiScreen screen = Minecraft.getMinecraft().currentScreen; if (screen instanceof GuiStaffOfLife) ((GuiStaffOfLife) screen).setVillagerData(message.villagers); return null; } } @AllArgsConstructor @NoArgsConstructor public static class ReviveVillager implements IMessage { private UUID target; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, target.toString()); } @Override public void fromBytes(ByteBuf buf) { target = UUID.fromString(ByteBufUtils.readUTF8String(buf)); } } public static class ReviveVillagerHandler implements IMessageHandler { @Override public IMessage onMessage(ReviveVillager message, MessageContext ctx) { EntityPlayer player = ctx.getServerHandler().player; SavedVillagers villagers = SavedVillagers.get(player.world); NBTTagCompound nbt = SavedVillagers.get(player.world).loadByUUID(message.target); if (nbt != null) { EntityVillagerMCA villager = new EntityVillagerMCA(player.world); villager.setPosition(player.posX, player.posY, player.posZ); player.world.spawnEntity(villager); villager.readEntityFromNBT(nbt); villager.reset(); villagers.remove(message.target); player.inventory.mainInventory.get(player.inventory.currentItem).damageItem(1, player); } return null; } } @AllArgsConstructor @NoArgsConstructor public static class SetName implements IMessage { private String name; private UUID entityUUID; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, entityUUID.toString()); ByteBufUtils.writeUTF8String(buf, name); } @Override public void fromBytes(ByteBuf buf) { entityUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); name = ByteBufUtils.readUTF8String(buf); } } public static class SetNameHandler implements IMessageHandler { @Override public IMessage onMessage(SetName message, MessageContext ctx) { World world = ctx.getServerHandler().player.world; java.util.Optional entity = world.loadedEntityList.stream().filter((e) -> e.getUniqueID().equals(message.entityUUID)).findFirst(); if (!entity.isPresent()) return null; if (entity.get() instanceof EntityVillagerMCA) { EntityVillagerMCA villager = (EntityVillagerMCA) entity.get(); villager.set(EntityVillagerMCA.VILLAGER_NAME, message.name); } return null; } } @AllArgsConstructor @NoArgsConstructor public static class SpawnParticles implements IMessage { private UUID entityUUID; private EnumParticleTypes particleType; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, entityUUID.toString()); buf.writeInt(particleType.getParticleID()); } @Override public void fromBytes(ByteBuf buf) { entityUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); particleType = EnumParticleTypes.getParticleFromId(buf.readInt()); } } public static class SpawnParticlesHandler implements IMessageHandler { @Override public IMessage onMessage(SpawnParticles message, MessageContext ctx) { World world = getPlayerClient().world; java.util.Optional entity = world.loadedEntityList.stream().filter((e) -> e.getUniqueID().equals(message.entityUUID)).findFirst(); if (!entity.isPresent()) return null; if (entity.get() instanceof EntityVillagerMCA) { EntityVillagerMCA villager = (EntityVillagerMCA) entity.get(); villager.spawnParticles(message.particleType); } return null; } } @NoArgsConstructor public static class GetFamily implements IMessage { @Override public void toBytes(ByteBuf buf) {} @Override public void fromBytes(ByteBuf buf) {} } public static class GetFamilyHandler implements IMessageHandler { @Override public IMessage onMessage(GetFamily message, MessageContext ctx) { EntityPlayer player = ctx.getServerHandler().player; List villagers = new ArrayList<>(); List familyData = new ArrayList<>(); player.world.loadedEntityList.stream().filter(e -> e instanceof EntityVillagerMCA).forEach(e -> villagers.add((EntityVillagerMCA)e)); villagers.stream().filter(e -> e.isMarriedTo(player.getUniqueID()) || e.playerIsParent(player)).forEach(e -> { NBTTagCompound nbt = new NBTTagCompound(); e.writeEntityToNBT(nbt); familyData.add(nbt); }); return new GetFamilyResponse(familyData); } } @AllArgsConstructor @NoArgsConstructor public static class GetFamilyResponse implements IMessage { private List familyData; @Override public void toBytes(ByteBuf buf) { buf.writeInt(familyData.size()); familyData.stream().forEach(n -> ByteBufUtils.writeTag(buf, n)); } @Override public void fromBytes(ByteBuf buf) { familyData = new ArrayList<>(); int size = buf.readInt(); for (int i = 0; i < size; i++) { familyData.add(ByteBufUtils.readTag(buf)); } } } public static class GetFamilyResponseHandler implements IMessageHandler { @Override public IMessage onMessage(GetFamilyResponse message, MessageContext ctx) { GuiScreen screen = Minecraft.getMinecraft().currentScreen; if (screen instanceof GuiWhistle) { GuiWhistle whistleScreen = (GuiWhistle)screen; whistleScreen.setVillagerDataList(message.familyData); } return null; } } @AllArgsConstructor @NoArgsConstructor public static class CallToPlayer implements IMessage { private UUID targetUUID; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, targetUUID.toString()); } @Override public void fromBytes(ByteBuf buf) { targetUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); } } public static class CallToPlayerHandler implements IMessageHandler { @Override public IMessage onMessage(CallToPlayer message, MessageContext ctx) { EntityPlayer player = ctx.getServerHandler().player; Optional entity = player.world.loadedEntityList.stream().filter(e -> e.getUniqueID().equals(message.targetUUID)).findFirst(); entity.ifPresent(e -> { e.setPosition(player.posX, player.posY, player.posZ); ((EntityLiving)e).getNavigator().clearPath(); }); return null; } } @AllArgsConstructor @NoArgsConstructor public static class SetProfession implements IMessage { private UUID targetUUID; private String profession; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, targetUUID.toString()); ByteBufUtils.writeUTF8String(buf, profession); } @Override public void fromBytes(ByteBuf buf) { targetUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); profession = ByteBufUtils.readUTF8String(buf); } } public static class SetProfessionHandler implements IMessageHandler { @Override public IMessage onMessage(SetProfession message, MessageContext ctx) { boolean isCareerSet = false; EntityPlayer player = ctx.getServerHandler().player; Optional entity = player.world.loadedEntityList.stream().filter(e -> e.getUniqueID().equals(message.targetUUID)).findFirst(); if (entity.isPresent()) { // Loop through all professions in the registry for (Map.Entry professionEntry : ProfessionsMCA.registry.getEntries()) { List careers = ObfuscationReflectionHelper.getPrivateValue(VillagerRegistry.VillagerProfession.class, professionEntry.getValue(), 3); // Career ids are based on their index in the careers list for (int i = 0; i < careers.size(); i++) { VillagerRegistry.VillagerCareer career = careers.get(i); // If we found the correct career, set the profession and career accordingly if (career.getName().equals(message.profession)) { EntityVillagerMCA villager = (EntityVillagerMCA)entity.get(); villager.setProfession(professionEntry.getValue()); villager.setVanillaCareer(i); player.sendMessage(new TextComponentString("Career set to " + message.profession)); isCareerSet = true; break; } } } } else { MCA.getLog().error("Entity not found on career set!: " + message.targetUUID.toString()); return null; } if (!isCareerSet) { player.sendMessage(new TextComponentString("Career not found: " + message.profession)); } return null; } } @AllArgsConstructor @NoArgsConstructor public static class SetTexture implements IMessage { private UUID targetUUID; private String texture; @Override public void toBytes(ByteBuf buf) { ByteBufUtils.writeUTF8String(buf, targetUUID.toString()); ByteBufUtils.writeUTF8String(buf, texture); } @Override public void fromBytes(ByteBuf buf) { targetUUID = UUID.fromString(ByteBufUtils.readUTF8String(buf)); texture = ByteBufUtils.readUTF8String(buf); } } public static class SetTextureHandler implements IMessageHandler { @Override public IMessage onMessage(SetTexture message, MessageContext ctx) { EntityPlayer player = ctx.getServerHandler().player; Optional entity = player.world.loadedEntityList.stream().filter(e -> e.getUniqueID().equals(message.targetUUID)).findFirst(); entity.ifPresent(e -> ((EntityVillagerMCA)e).set(EntityVillagerMCA.TEXTURE, message.texture)); return null; } } } ================================================ FILE: src/main/java/mca/core/forge/ServerProxy.java ================================================ package mca.core.forge; public class ServerProxy { public void registerEntityRenderers() { // Server-side, no rendering. } public void registerEventHandlers() { } public void registerModelMeshers() { } } ================================================ FILE: src/main/java/mca/core/minecraft/BlocksMCA.java ================================================ package mca.core.minecraft; import mca.blocks.BlockVillagerSpawner; import mca.core.MCA; import net.minecraft.block.Block; import net.minecraft.block.BlockOre; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ItemModelMesher; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.item.Item; import net.minecraft.item.ItemBlock; import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import net.minecraftforge.registries.IForgeRegistry; import java.util.ArrayList; public final class BlocksMCA { public static final Block ROSE_GOLD_BLOCK = new BlockOre(); public static final Block ROSE_GOLD_ORE = new BlockOre(); public static final BlockVillagerSpawner VILLAGER_SPAWNER = new BlockVillagerSpawner(); private static final ArrayList BLOCKS = new ArrayList<>(); public static void register(RegistryEvent.Register event) { ROSE_GOLD_BLOCK.setHardness(3.0F).setResistance(5.0F).setCreativeTab(MCA.creativeTab); ROSE_GOLD_BLOCK.setHarvestLevel("pickaxe", 2); ROSE_GOLD_ORE.setHardness(3.0F).setResistance(5.0F).setCreativeTab(MCA.creativeTab); ROSE_GOLD_ORE.setHarvestLevel("pickaxe", 2); VILLAGER_SPAWNER.setCreativeTab(MCA.creativeTab); Block[] blocks = { ROSE_GOLD_BLOCK, ROSE_GOLD_ORE, VILLAGER_SPAWNER }; setBlockName(ROSE_GOLD_BLOCK, "rose_gold_block"); setBlockName(ROSE_GOLD_ORE, "rose_gold_ore"); setBlockName(VILLAGER_SPAWNER, "villager_spawner"); for (Block block : blocks) { event.getRegistry().register(block); BLOCKS.add(block); } } public static void registerItemBlocks(RegistryEvent.Register event) { IForgeRegistry registry = event.getRegistry(); ItemBlock[] items = { new ItemBlock(ROSE_GOLD_BLOCK), new ItemBlock(ROSE_GOLD_ORE), new ItemBlock(VILLAGER_SPAWNER) }; for (ItemBlock item : items) { Block block = item.getBlock(); ResourceLocation registryName = block.getRegistryName(); registry.register(item.setRegistryName(registryName)); } } private static void setBlockName(Block block, String blockName) { block.setRegistryName(MCA.MODID, blockName); block.setUnlocalizedName(block.getRegistryName().toString()); } @SideOnly(Side.CLIENT) public static void registerModelMeshers() { ItemModelMesher mesher = Minecraft.getMinecraft().getRenderItem().getItemModelMesher(); for (Block block : BLOCKS) { mesher.register(Item.getItemFromBlock(block), 0, new ModelResourceLocation(block.getRegistryName(), "inventory")); } } } ================================================ FILE: src/main/java/mca/core/minecraft/ItemsMCA.java ================================================ package mca.core.minecraft; import mca.core.Constants; import mca.core.MCA; import mca.items.*; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.ItemModelMesher; import net.minecraft.client.renderer.block.model.ModelResourceLocation; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; import net.minecraft.util.ResourceLocation; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.List; public final class ItemsMCA { public static final ItemSpawnEgg EGG_MALE = new ItemSpawnEgg(true); public static final ItemSpawnEgg EGG_FEMALE = new ItemSpawnEgg(false); public static final Item WEDDING_RING = new ItemWeddingRing().setMaxStackSize(1); public static final Item WEDDING_RING_RG = new ItemWeddingRing().setMaxStackSize(1); public static final Item ENGAGEMENT_RING = new ItemEngagementRing().setMaxStackSize(1); public static final Item ENGAGEMENT_RING_RG = new ItemEngagementRing().setMaxStackSize(1); public static final Item MATCHMAKERS_RING = new ItemMatchmakersRing().setMaxStackSize(2); public static final Item BABY_BOY = new ItemBaby(true); public static final Item BABY_GIRL = new ItemBaby(false); public static final Item ROSE_GOLD_INGOT = new Item().setUnlocalizedName("rose_gold_ingot"); public static final Item ROSE_GOLD_DUST = new Item().setUnlocalizedName("rose_gold_dust"); public static final Item GOLD_DUST = new Item().setUnlocalizedName("gold_dust"); public static final Item VILLAGER_EDITOR = new ItemVillagerEditor(); public static final Item STAFF_OF_LIFE = new ItemStaffOfLife(); public static final Item WHISTLE = new ItemWhistle(); public static final ItemGuideBook BOOK_DEATH = new ItemGuideBook(); public static final ItemGuideBook BOOK_ROMANCE = new ItemGuideBook(); public static final ItemGuideBook BOOK_FAMILY = new ItemGuideBook(); public static final ItemGuideBook BOOK_ROSE_GOLD = new ItemGuideBook(); public static final ItemGuideBook BOOK_INFECTION = new ItemGuideBook(); private static final List ITEMS = new ArrayList<>(); public static void register(RegistryEvent.Register event) { for (Field f : ItemsMCA.class.getFields()) { try { Object instance = f.get(null); if (instance instanceof Item) { Item item = (Item) instance; setItemName(item, f.getName().toLowerCase()); event.getRegistry().register(item); ITEMS.add(item); } } catch (Exception e) { MCA.getLog().error("Error while registering items: ", e); } } } public static void assignCreativeTabs() { ITEMS.stream().forEach(i -> i.setCreativeTab(MCA.creativeTab)); } public static void setBookNBT(ItemStack stack) { Item book = stack.getItem(); NBTTagCompound nbt = new NBTTagCompound(); if (book == BOOK_DEATH) { nbt.setString("title", "Death, and How to Cure It!"); nbt.setString("author", "Ozzie the Warrior"); nbt.setBoolean("resolved", true); NBTTagList pages = new NBTTagList(); pages.appendTag(new NBTTagString("" + "I couldn't count how many times my family has been blown to pieces by creepers.\n\nHow are they still around, you may ask?" + "\n\nEasy! I, dear reader, have discovered a CURE for death itself! And through this book, I can share it with you.")); /* pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Memorials\n\n" + Constants.Format.RESET + "When a family member dies, they will drop a chest - and inside will be an " + Constants.Format.BOLD + "item" + Constants.Format.RESET + " that was important to them.\n\n" + "This is the key to reviving someone, don't lose it! Only your spouse and children will drop these items.")); */ pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Staff Of Life\n\n" + Constants.Format.RESET + "The Staff is a powerful item that can revive up to 5 people. Wave the staff around and speak the name of the villager you wish to revive. Within moments, your loved one will be fully revived!\n\n")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Summoning Grim\n\n" + Constants.Format.RESET + "Unfortunately, you must obtain the Staff from the Grim Reaper himself.\n\n" + "To summon him, you must build an altar consisting of 3 obsidian columns that are at least 2 blocks high. They may be higher if you like.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Summoning Grim pt. 2\n\n" + Constants.Format.RESET + " # # # X # # #\n" + " # # # # # # #\n" + " # # # # # # #\n" + " X # # E # # X\n\n" + "X = Obsidian Column\n" + "E = Emerald\n" + "# = Empty")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Summoning Grim pt. 3\n\n" + Constants.Format.RESET + "After building the altar, wait until night and light all 3 columns.\n\n" + "When you're ready to fight, light the emerald block and run!")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Fighting Grim\n\n" + Constants.Format.RESET + "Grim is tough. Use full diamond armor, lots of potions, and lots of enchantments.\n\n" + "He can:\n" + "- Fly\n" + "- Block attacks\n" + "- Blind you\n" + "- Move your items\n" + "- Teleport\n")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Fighting Grim pt. 2\n\n" + Constants.Format.RESET + "If you hit Grim while he's blocking, he will teleport behind you and strike.\n\n" + "Do not try to use arrows or poison, he is immune!\n\n")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Fighting Grim pt. 3\n\n" + Constants.Format.RESET + "When Grim is at " + Constants.Format.BOLD + "half health" + Constants.Format.RESET + " he will teleport into the air and begin healing.\n\n" + "While healing, he will summon his minions from the underworld to fight you.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Fighting Grim pt. 4\n\n" + Constants.Format.RESET + "When Grim is healed, he will continue attacking you, but he won't be able to heal again for 3 minutes and 30 seconds.\n\n" + "Each time Grim heals, he will not be able to restore as much health has he did previously.")); nbt.setTag("pages", pages); } else if (book == BOOK_ROMANCE) { nbt.setString("title", "Relationships and You"); nbt.setString("author", "Gerry the Librarian"); nbt.setBoolean("resolved", true); NBTTagList pages = new NBTTagList(); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Introduction\n\n" + Constants.Format.RESET + "Interaction is key to building relationships and finding the love of your life.\n\n" + "I've happily written this book in order to share my knowledge of interaction, love, and, unfortunately, divorce, to anyone who may need a little push in the right direction.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Interacting\n" + Constants.Format.RESET + "Choose wisely when interacting with a villager!\n\n" + "If choosing a romantic interaction, be sure that the villager you are talking to likes you a lot.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Interacting pt. 2\n" + Constants.Format.RESET + "Don't be annoying! Talking to someone for too long will bore them, and your interactions may stop succeeding.\n\n" + "If this happens, simply wait a few minutes before trying to talk to them again.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Marriage\n" + Constants.Format.RESET + "To get married, simply gift a villager a wedding ring once you feel you have reached the highest relationship level.\n\n" + "Once you're married, you can then procreate and have children of your own!")); nbt.setTag("pages", pages); } else if (book == BOOK_FAMILY) { nbt.setString("title", "Managing Your Family Vol. XI"); nbt.setString("author", "Leanne the Cleric"); nbt.setBoolean("resolved", true); NBTTagList pages = new NBTTagList(); pages.appendTag(new NBTTagString("" + "Children are our future! Make sure to have as many as you possibly can.\n\nNot only do you get to experience the joy of" + " raising a child, but once they are past the baby stage, put them to work!")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Babies\n\n" + Constants.Format.RESET + "When you are married, simply approach your spouse and offer to 'Procreate'.\n\n" + "After a short dance, you'll be the proud owner of a new baby boy or girl (or maybe even both)!")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Growth\n\n" + Constants.Format.RESET + "Babies take time to grow, make sure to hold them until they are ready, or give them to your spouse to take care of.\n\n" + "Once a baby is ready to grow, you may place it on the ground and it will grow into a child!")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Adolescence\n\n" + Constants.Format.RESET + "Children will grow slowly from a baby to a teen.\n\nHowever, the magical properties of Golden Apples are said to accelerate " + "any child's growth. I have yet to try this myself.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Chores\n\n" + Constants.Format.RESET + "Any child can harvest, chop wood, prospect, hunt, and fish. You'll need to provide them with the tools they need to do so.\n\n" + "If a tool breaks and the child doesn't have another, they will have no choice but to stop working.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Adulthood\n\n" + Constants.Format.RESET + "As sad as it may be, children will eventually grow into adults.\n\n" + "Adults can be married off by using Matchmaker's Rings, or they will eventually get married on their own.")); nbt.setTag("pages", pages); } else if (book == BOOK_ROSE_GOLD) { nbt.setString("title", "On Rose Gold"); nbt.setString("author", "William the Miner"); nbt.setBoolean("resolved", true); NBTTagList pages = new NBTTagList(); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Warning!\nTOP SECRET\n\n" + Constants.Format.RESET + "This manual is the property of William Mining Co.\n\nIf you are not a William Mining Co. employee, please refrain from " + "reading this manual and return promptly to William the Miner.")); pages.appendTag(new NBTTagString("" + "Ah, rose gold - a lovely combination of silver, copper, and gold that smelts into a pinkish orange metal.\n\n" + "Most use it as an alternative to gold for crafting rings as it is much less expensive.\n\n" + "However, it has some interesting qualities that are easy to miss.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Creating Dust\n\n" + Constants.Format.RESET + "Rose gold, once smelted, can be crushed into a fine dust.\n\n" + "Look closely at rose gold dust in bright light, and you'll see shiny flecks of pure gold!\n\n")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Washing Dust\n\n" + Constants.Format.RESET + "With a little work, we can actually extract the gold from the dust and create pure gold ingots. Simply mix dust with a bucket of water.\n\n" + "The lighter silver and copper components will wash away, leaving you with about 6 smaller piles of gold dust.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Extracting Gold\n\n" + Constants.Format.RESET + "Arrange 9 piles of dust on your crafting table, and if you're lucky, you'll find a gold nugget in one of them!\n\n" + "And of course, once you have 9 gold nuggets, you'll be able to craft them into a solid gold ingot.")); nbt.setTag("pages", pages); } else if (book == BOOK_INFECTION) { nbt.setString("title", "Beware the Infection!"); nbt.setString("author", "Richard the Zombie"); nbt.setBoolean("resolved", true); NBTTagList pages = new NBTTagList(); pages.appendTag(new NBTTagString("" + "Good day, readers! I've written this book so that you may not end up suffering the same fate as I.\n\n" + "Although I caught the infection, I was luckily able to keep all of my mental faculties.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "What is the Infection?\n\n" + Constants.Format.RESET + "I discovered long ago that the zombies that appear at night are actually villagers in the late stages of infection!\n\n" + "Newly infected villagers turn green, are unable to speak, and occasionally try to bite!")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Curing\n\n" + Constants.Format.RESET + "Contrary to popular belief, the infection can be cured if caught in time.\n\n" + "You must first weaken the villager or zombie with a potion.\n\n" + "Then, immediately feed them a golden apple.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Curing pt. 2\n\n" + Constants.Format.RESET + "Zombies that can be cured often have enlarged heads and noses.\n\n" + "Any other zombies you see unfortunately are too far gone, and cannot be cured.")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Curing pt. 3\n\n" + Constants.Format.RESET + "Zombies will take a couple of minutes to be fully cured.\n\n" + "Villagers who were recently infected, though, and haven't had time to degrade into a full zombie, will be cured instantly!")); pages.appendTag(new NBTTagString(Constants.Format.BOLD + "Warnings\n\n" + Constants.Format.RESET + "Villagers are highly susceptible to infection, and children even more so!\n\n" + "If you carry a baby with you while fighting zombies, there is a chance it can become infected.")); nbt.setTag("pages", pages); } stack.setTagCompound(nbt); } @SideOnly(Side.CLIENT) public static void registerModelMeshers() { ItemModelMesher mesher = Minecraft.getMinecraft().getRenderItem().getItemModelMesher(); for (Item item : ITEMS) mesher.register(item, 0, new ModelResourceLocation(item.getRegistryName(), "inventory")); } private static void setItemName(Item item, String itemName) { item.setUnlocalizedName(itemName); item.setRegistryName(new ResourceLocation(MCA.MODID + ":" + itemName)); } } ================================================ FILE: src/main/java/mca/core/minecraft/ProfessionsMCA.java ================================================ package mca.core.minecraft; import mca.util.ItemStackCache; import mca.util.ResourceLocationCache; import net.minecraft.entity.IMerchant; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.util.ResourceLocation; import net.minecraft.village.MerchantRecipe; import net.minecraft.village.MerchantRecipeList; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.fml.common.Mod; import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; import net.minecraftforge.fml.common.registry.GameRegistry; import net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerCareer; import net.minecraftforge.fml.common.registry.VillagerRegistry.VillagerProfession; import net.minecraftforge.registries.IForgeRegistry; import java.util.Arrays; import java.util.Random; @GameRegistry.ObjectHolder("mca") public class ProfessionsMCA { public static final VillagerProfession guard = new VillagerProfession("mca:guard", "minecraft:textures/entity/villager/villager.png", "minecraft:textures/entity/zombie_villager/zombie_villager.png"); public static final VillagerProfession bandit = new VillagerProfession("mca:bandit", "minecraft:textures/entity/villager/villager.png", "minecraft:textures/entity/zombie_villager/zombie_villager.png"); public static final VillagerProfession child = new VillagerProfession("mca:child", "minecraft:textures/entity/villager/villager.png", "minecraft:textures/entity/zombie_villager/zombie_villager.png"); public static final VillagerProfession baker = new VillagerProfession("mca:baker", "minecraft:textures/entity/villager/farmer.png", "minecraft:textures/entity/zombie_villager/zombie_farmer.png"); public static final VillagerProfession miner = new VillagerProfession("mca:miner", "minecraft:textures/entity/villager/smith.png", "minecraft:textures/entity/zombie_villager/zombie_smith.png"); public static VillagerCareer guard_warrior; public static VillagerCareer guard_archer; public static VillagerCareer guard_hero; public static VillagerCareer bandit_marauder; public static VillagerCareer bandit_outlaw; public static VillagerCareer bandit_pillager; public static VillagerCareer child_child; public static VillagerCareer baker_baker; public static VillagerCareer miner_miner; public static IForgeRegistry registry; private static final VillagerProfession[] FORBIDDEN_RANDOM_PROFESSIONS = { bandit, child }; public static void registerCareers() { guard_warrior = new VillagerCareer(guard, "warrior"); guard_archer = new VillagerCareer(guard, "archer"); guard_hero = new VillagerCareer(guard, "hero"); bandit_marauder = new VillagerCareer(bandit, "marauder"); bandit_outlaw = new VillagerCareer(bandit, "outlaw"); bandit_pillager = new VillagerCareer(bandit, "pillager"); child_child = new VillagerCareer(child, "child"); baker_baker = new VillagerCareer(baker, "baker"); miner_miner = new VillagerCareer(miner, "miner"); baker_baker.addTrade(1, new BakerTradesLvl1()); baker_baker.addTrade(2, new BakerTradesLvl2()); baker_baker.addTrade(3, new BakerTradesLvl3()); miner_miner.addTrade(1, new MinerTradesLvl1()); miner_miner.addTrade(2, new MinerTradesLvl2()); miner_miner.addTrade(3, new MinerTradesLvl3()); } public static ItemStack getDefaultHeldItem(VillagerProfession profession, VillagerCareer career) { if (profession == ProfessionsMCA.guard) return career == ProfessionsMCA.guard_archer ? ItemStackCache.get(Items.BOW) : ItemStackCache.get(Items.IRON_SWORD); else if (profession == ProfessionsMCA.bandit) return ItemStackCache.get(Items.IRON_SWORD); return ItemStack.EMPTY; } public static VillagerProfession randomProfession() { ResourceLocation resource = null; while (resource == null || resource.getResourcePath().contains("nitwit") || inForbiddenProfessions(registry.getValue(resource))) { int i = new Random().nextInt(registry.getKeys().size() - 1); resource = (ResourceLocation)registry.getKeys().toArray()[i]; } return registry.getValue(resource); } @Mod.EventBusSubscriber(modid = "mca") public static class RegistrationHandler { /** * Register this mod's {@link VillagerProfession}s. * * @param event The event */ @SubscribeEvent public static void onEvent(final RegistryEvent.Register event) { registry = event.getRegistry(); registry.register(guard); registry.register(bandit); registry.register(child); registry.register(baker); registry.register(miner); } } public static class BakerTradesLvl1 implements EntityVillager.ITradeList { @Override public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random) { recipeList.add(new MerchantRecipe(new ItemStack(Items.EMERALD, 1), new ItemStack(Items.WHEAT, 6))); recipeList.add(new MerchantRecipe(new ItemStack(Items.MILK_BUCKET, 1), new ItemStack(Items.BREAD, 2))); } } public static class BakerTradesLvl2 implements EntityVillager.ITradeList { @Override public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random) { recipeList.add(new MerchantRecipe(new ItemStack(Items.EMERALD, 2), new ItemStack(Items.EGG, 12))); recipeList.add(new MerchantRecipe(new ItemStack(Items.SUGAR, 2), new ItemStack(Items.CAKE, 1))); recipeList.add(new MerchantRecipe(new ItemStack(Items.STONE_HOE, 1), new ItemStack(Items.WHEAT, 10))); } } public static class BakerTradesLvl3 implements EntityVillager.ITradeList { @Override public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random) { recipeList.add(new MerchantRecipe(new ItemStack(Items.CAKE, 1), new ItemStack(Items.EMERALD, 5))); recipeList.add(new MerchantRecipe(new ItemStack(Items.EMERALD, 2), new ItemStack(Items.BREAD, 4))); recipeList.add(new MerchantRecipe(new ItemStack(Items.EMERALD, 3), new ItemStack(Items.COOKIE, 6))); recipeList.add(new MerchantRecipe(new ItemStack(Blocks.PUMPKIN, 1), new ItemStack(Items.PUMPKIN_PIE, 1))); } } public static class MinerTradesLvl1 implements EntityVillager.ITradeList { @Override public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random) { recipeList.add(new MerchantRecipe(new ItemStack(Blocks.COBBLESTONE, 8), new ItemStack(Blocks.STONE, 4))); recipeList.add(new MerchantRecipe(new ItemStack(Items.EMERALD, 1), new ItemStack(Blocks.TORCH, 8))); } } public static class MinerTradesLvl2 implements EntityVillager.ITradeList { @Override public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random) { recipeList.add(new MerchantRecipe(new ItemStack(Items.GOLD_INGOT, 3), new ItemStack(Items.EMERALD, 2))); recipeList.add(new MerchantRecipe(new ItemStack(Items.EMERALD, 1), new ItemStack(Items.COAL, 3))); } } public static class MinerTradesLvl3 implements EntityVillager.ITradeList { @Override public void addMerchantRecipe(IMerchant merchant, MerchantRecipeList recipeList, Random random) { recipeList.add(new MerchantRecipe(new ItemStack(Items.EMERALD, 4), new ItemStack(Items.IRON_PICKAXE, 1))); recipeList.add(new MerchantRecipe(new ItemStack(Blocks.EMERALD_BLOCK, 1), new ItemStack(Items.DIAMOND_PICKAXE, 1))); recipeList.add(new MerchantRecipe(new ItemStack(Items.IRON_INGOT, 8), new ItemStack(Items.DIAMOND, 1))); } } private static boolean inForbiddenProfessions(VillagerProfession profIn) { for (VillagerProfession profession : FORBIDDEN_RANDOM_PROFESSIONS) { if (profession == profIn) { return true; } } return false; } } ================================================ FILE: src/main/java/mca/core/minecraft/RoseGoldOreGenerator.java ================================================ package mca.core.minecraft; import mca.core.MCA; import net.minecraft.block.Block; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.gen.IChunkGenerator; import net.minecraft.world.gen.feature.WorldGenMinable; import net.minecraftforge.fml.common.IWorldGenerator; import java.util.Random; public final class RoseGoldOreGenerator implements IWorldGenerator { public RoseGoldOreGenerator() { } public void generate(Random random, int chunkX, int chunkZ, World world, IChunkGenerator chunkGenerator, IChunkProvider chunkProvider) { if (world.provider.getDimension() == 0) generateSurface(world, random, chunkX * 16, chunkZ * 16); } private void generateSurface(World world, Random random, int x, int z) { this.addOreSpawn(BlocksMCA.ROSE_GOLD_ORE, world, random, x, z, 16, 16, 6, 5); } public void addOreSpawn(Block block, World world, Random random, int blockPosX, int blockPosZ, int maxX, int maxZ, int maxVeinSize, int chancesToSpawn) { if (block == BlocksMCA.ROSE_GOLD_ORE && !MCA.getConfig().allowRoseGoldGeneration) block = Blocks.STONE; int range = 25; for (int x = 0; x < chancesToSpawn; x++) { int posX = blockPosX + random.nextInt(maxX); int posY = 12 + random.nextInt(range); int posZ = blockPosZ + random.nextInt(maxZ); (new WorldGenMinable(block.getDefaultState(), maxVeinSize)).generate(world, random, new BlockPos(posX, posY, posZ)); } } } ================================================ FILE: src/main/java/mca/core/minecraft/SoundsMCA.java ================================================ package mca.core.minecraft; import net.minecraft.util.ResourceLocation; import net.minecraft.util.SoundEvent; import net.minecraftforge.event.RegistryEvent; import net.minecraftforge.registries.IForgeRegistry; public final class SoundsMCA { private static final ResourceLocation loc_reaper_scythe_out = new ResourceLocation("mca:reaper.scythe.out"); public static final SoundEvent reaper_scythe_out = new SoundEvent(loc_reaper_scythe_out); private static final ResourceLocation loc_reaper_scythe_swing = new ResourceLocation("mca:reaper.scythe.swing"); public static final SoundEvent reaper_scythe_swing = new SoundEvent(loc_reaper_scythe_swing); private static final ResourceLocation loc_reaper_idle = new ResourceLocation("mca:reaper.idle"); public static final SoundEvent reaper_idle = new SoundEvent(loc_reaper_idle); private static final ResourceLocation loc_reaper_death = new ResourceLocation("mca:reaper.death"); public static final SoundEvent reaper_death = new SoundEvent(loc_reaper_death); private static final ResourceLocation loc_reaper_block = new ResourceLocation("mca:reaper.block"); public static final SoundEvent reaper_block = new SoundEvent(loc_reaper_block); private static final ResourceLocation loc_reaper_summon = new ResourceLocation("mca:reaper.summon"); public static final SoundEvent reaper_summon = new SoundEvent(loc_reaper_summon); public static void register(RegistryEvent.Register event) { IForgeRegistry registry = event.getRegistry(); reaper_scythe_out.setRegistryName(loc_reaper_scythe_out); reaper_scythe_swing.setRegistryName(loc_reaper_scythe_swing); reaper_idle.setRegistryName(loc_reaper_idle); reaper_death.setRegistryName(loc_reaper_death); reaper_block.setRegistryName(loc_reaper_block); reaper_summon.setRegistryName(loc_reaper_summon); registry.register(reaper_scythe_out); registry.register(reaper_scythe_swing); registry.register(reaper_idle); registry.register(reaper_death); registry.register(reaper_block); registry.register(reaper_summon); } } ================================================ FILE: src/main/java/mca/core/minecraft/VillageHelper.java ================================================ package mca.core.minecraft; import com.google.common.base.Optional; import mca.core.MCA; import mca.entity.EntityVillagerMCA; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.TextComponentString; import net.minecraft.village.Village; import net.minecraft.world.World; import java.util.List; public class VillageHelper { public static void tick(World world) { world.getVillageCollection().getVillageList().forEach(v -> spawnGuards(world, v)); } public static void forceSpawnGuards(EntityPlayerMP player) { Village nearestVillage = player.world.getVillageCollection().getNearestVillage(player.getPosition(), 100); spawnGuards(player.world, nearestVillage); } public static void forceRaid(EntityPlayerMP player) { Village nearestVillage = player.world.getVillageCollection().getNearestVillage(player.getPosition(), 100); startRaid(player.world, nearestVillage); } private static void spawnGuards(World world, Village village) { int guardCapacity = village.getNumVillagers() / MCA.getConfig().guardSpawnRate; int guards = 0; // Grab all villagers in the area List list = world.getEntitiesWithinAABB(EntityVillagerMCA.class, new AxisAlignedBB((double) (village.getCenter().getX() - village.getVillageRadius()), (double) (village.getCenter().getY() - 4), (double) (village.getCenter().getZ() - village.getVillageRadius()), (double) (village.getCenter().getX() + village.getVillageRadius()), (double) (village.getCenter().getY() + 4), (double) (village.getCenter().getZ() + village.getVillageRadius()))); // Count up the guards for (EntityVillagerMCA villager : list) { if (villager.getProfessionForge().getRegistryName().equals(ProfessionsMCA.guard.getRegistryName())) guards++; } // Spawn a new guard if we don't have enough, up to 10 if (guards < guardCapacity && guards < 10) { Vec3d spawnPos = findRandomSpawnPos(world, village, village.getCenter(), 2, 4, 2); if (spawnPos != null) { EntityVillagerMCA guard = new EntityVillagerMCA(world, Optional.of(ProfessionsMCA.guard), Optional.absent()); guard.setPosition(spawnPos.x + 0.5D, spawnPos.y + 1.0D, spawnPos.z + 0.5D); guard.finalizeMobSpawn(world.getDifficultyForLocation(guard.getPos()), null, false); world.spawnEntity(guard); } } } private static void startRaid(World world, Village village) { int banditsToSpawn = world.rand.nextInt(5) + 1; while (banditsToSpawn > 0) { EntityVillagerMCA bandit = new EntityVillagerMCA(world, Optional.of(ProfessionsMCA.bandit), Optional.absent()); BlockPos spawnLocation = village.getCenter(); bandit.setPosition(spawnLocation.getX(), spawnLocation.getY(), spawnLocation.getZ()); world.spawnEntity(bandit); banditsToSpawn--; } } private static Vec3d findRandomSpawnPos(World world, Village village, BlockPos pos, int x, int y, int z) { for (int i = 0; i < 10; ++i) { BlockPos blockpos = pos.add(world.rand.nextInt(16) - 8, world.rand.nextInt(6) - 3, world.rand.nextInt(16) - 8); if (village.isBlockPosWithinSqVillageRadius(blockpos) && isAreaClearAround(world, new BlockPos(x, y, z), blockpos)) return new Vec3d((double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ()); } return null; } private static boolean isAreaClearAround(World world, BlockPos blockSize, BlockPos blockLocation) { if (!world.getBlockState(blockLocation.down()).isTopSolid()) return false; int i = blockLocation.getX() - blockSize.getX() / 2; int j = blockLocation.getZ() - blockSize.getZ() / 2; for (int k = i; k < i + blockSize.getX(); ++k) { for (int l = blockLocation.getY(); l < blockLocation.getY() + blockSize.getY(); ++l) { for (int i1 = j; i1 < j + blockSize.getZ(); ++i1) { if (world.getBlockState(new BlockPos(k, l, i1)).isNormalCube()) { return false; } } } } return true; } } ================================================ FILE: src/main/java/mca/core/minecraft/WorldEventListenerMCA.java ================================================ package mca.core.minecraft; import mca.core.forge.NetMCA; import mca.entity.EntityVillagerMCA; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.SoundCategory; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.BlockPos; import net.minecraft.world.IWorldEventListener; import net.minecraft.world.World; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import javax.annotation.Nullable; public class WorldEventListenerMCA implements IWorldEventListener { public void notifyBlockUpdate(World worldIn, BlockPos pos, IBlockState oldState, IBlockState newState, int flags) { } public void notifyLightSet(BlockPos pos) { } public void markBlockRangeForRenderUpdate(int x1, int y1, int z1, int x2, int y2, int z2) { } public void playSoundToAllNearExcept(@Nullable EntityPlayer player, SoundEvent soundIn, SoundCategory category, double x, double y, double z, float volume, float pitch) { } public void playRecord(SoundEvent soundIn, BlockPos pos) { } public void spawnParticle(int particleID, boolean ignoreRange, double xCoord, double yCoord, double zCoord, double xSpeed, double ySpeed, double zSpeed, int... parameters) { } public void spawnParticle(int id, boolean ignoreRange, boolean p_190570_3_, double x, double y, double z, double xSpeed, double ySpeed, double zSpeed, int... parameters) { } public void onEntityAdded(Entity entityIn) { // Ask the server to send the villager's career ID when it is loaded into the world client-side if (entityIn instanceof EntityVillagerMCA) { // Career ID is not data managed, but we depend on it to display the proper profession for the villager alongside their name. // The ID is randomized client-side with populateBuyingList(), which doesn't affect anything. This throws off the career ID that we send the client. // To stop this, we default the career ID and level client-side to 1. This prevents populateBuyingList() from running and allows our career ID sent from the server to apply. ObfuscationReflectionHelper.setPrivateValue(EntityVillager.class, (EntityVillagerMCA) entityIn, 1, EntityVillagerMCA.VANILLA_CAREER_ID_FIELD_INDEX); ObfuscationReflectionHelper.setPrivateValue(EntityVillager.class, (EntityVillagerMCA) entityIn, 1, EntityVillagerMCA.VANILLA_CAREER_LEVEL_FIELD_INDEX); NetMCA.INSTANCE.sendToServer(new NetMCA.CareerRequest(entityIn.getUniqueID())); // The villager's inventory is also not synced to the client until it is opened in a Container. // When the entity joins the client world, ask the server to send over the inventory data. NetMCA.INSTANCE.sendToServer(new NetMCA.InventoryRequest(entityIn.getUniqueID())); } } public void onEntityRemoved(Entity entityIn) { } public void broadcastSound(int soundID, BlockPos pos, int data) { } public void playEvent(EntityPlayer player, int type, BlockPos blockPosIn, int data) { } public void sendBlockBreakProgress(int breakerId, BlockPos pos, int progress) { } } ================================================ FILE: src/main/java/mca/entity/EntityGrimReaper.java ================================================ package mca.entity; import mca.core.MCA; import mca.core.minecraft.ItemsMCA; import mca.core.minecraft.SoundsMCA; import mca.enums.EnumReaperAttackState; import mca.util.Util; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.*; import net.minecraft.entity.effect.EntityLightningBolt; import net.minecraft.entity.monster.EntityMob; import net.minecraft.entity.monster.EntitySkeleton; import net.minecraft.entity.monster.EntityZombie; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.projectile.EntityArrow; import net.minecraft.init.Items; import net.minecraft.init.MobEffects; import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.ItemStack; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.potion.PotionEffect; import net.minecraft.util.DamageSource; import net.minecraft.util.SoundEvent; import net.minecraft.util.math.MathHelper; import net.minecraft.world.BossInfo; import net.minecraft.world.BossInfoServer; import net.minecraft.world.World; public class EntityGrimReaper extends EntityMob { private static final DataParameter ATTACK_STATE = EntityDataManager.createKey(EntityGrimReaper.class, DataSerializers.VARINT); private static final DataParameter STATE_TRANSITION_COOLDOWN = EntityDataManager.createKey(EntityGrimReaper.class, DataSerializers.VARINT); private final BossInfoServer bossInfo = (BossInfoServer) (new BossInfoServer(this.getDisplayName(), BossInfo.Color.PURPLE, BossInfo.Overlay.PROGRESS)).setDarkenSky(true); private EntityAINearestAttackableTarget aiNearestAttackableTarget = new EntityAINearestAttackableTarget(this, EntityPlayer.class, true); private int healingCooldown; private int timesHealed; private float floatingTicks; public EntityGrimReaper(World world) { super(world); setSize(1.0F, 2.6F); this.experienceValue = 100; this.tasks.addTask(1, new EntityAISwimming(this)); this.tasks.addTask(4, new EntityAIWander(this, 1.0D)); this.tasks.addTask(6, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); this.tasks.addTask(6, new EntityAILookIdle(this)); this.targetTasks.addTask(1, new EntityAIHurtByTarget(this, false, new Class[0])); this.targetTasks.addTask(2, aiNearestAttackableTarget); } @Override protected final void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(40.0D); this.getEntityAttribute(SharedMonsterAttributes.MOVEMENT_SPEED).setBaseValue(0.30F); this.getEntityAttribute(SharedMonsterAttributes.ATTACK_DAMAGE).setBaseValue(12.5F); this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(225.0F); } @Override protected void dropFewItems(boolean hitByPlayer, int lootingLvl) { dropItem(ItemsMCA.STAFF_OF_LIFE, 1); } @Override protected void entityInit() { super.entityInit(); this.dataManager.register(ATTACK_STATE, 0); this.dataManager.register(STATE_TRANSITION_COOLDOWN, 0); } public EnumReaperAttackState getAttackState() { return EnumReaperAttackState.fromId(this.dataManager.get(ATTACK_STATE)); } public void setAttackState(EnumReaperAttackState state) { // Only update if needed so that sounds only play once. if (this.dataManager.get(ATTACK_STATE) != state.getId()) { this.dataManager.set(ATTACK_STATE, state.getId()); switch (state) { case PRE: this.playSound(SoundsMCA.reaper_scythe_out, 1.0F, 1.0F); break; case POST: this.playSound(SoundsMCA.reaper_scythe_swing, 1.0F, 1.0F); break; } } } public boolean hasEntityToAttack() { return this.getAttackTarget() != null; } @Override public void onStruckByLightning(EntityLightningBolt entity) { return; } @Override public boolean attackEntityFrom(DamageSource source, float damage) { bossInfo.setPercent(this.getHealth() / this.getMaxHealth()); // Ignore wall damage and fire damage. if (source == DamageSource.IN_WALL || source == DamageSource.ON_FIRE || source.isExplosion() || source == DamageSource.IN_FIRE) { // Teleport out of any walls we may end up in. if (source == DamageSource.IN_WALL) { teleportTo(this.posX, this.posY + 3, this.posZ); } return false; } // Ignore damage when blocking, and teleport behind the player when they attempt to block. else if (!world.isRemote && this.getAttackState() == EnumReaperAttackState.BLOCK && source.getImmediateSource() instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer) source.getImmediateSource(); double deltaX = this.posX - player.posX; double deltaZ = this.posZ - player.posZ; this.playSound(SoundsMCA.reaper_block, 1.0F, 1.0F); teleportTo(player.posX - (deltaX * 2), player.posY + 2, this.posZ - (deltaZ * 2)); setStateTransitionCooldown(0); return false; } // Randomly portal behind the player who just attacked. else if (!world.isRemote && source.getImmediateSource() instanceof EntityPlayer && rand.nextFloat() >= 0.30F) { EntityPlayer player = (EntityPlayer) source.getImmediateSource(); double deltaX = this.posX - player.posX; double deltaZ = this.posZ - player.posZ; teleportTo(player.posX - (deltaX * 2), player.posY + 2, this.posZ - (deltaZ * 2)); } // Teleport behind the player who fired an arrow and ignore its damage. else if (source.getImmediateSource() instanceof EntityArrow) { EntityArrow arrow = (EntityArrow) source.getImmediateSource(); if (arrow.shootingEntity instanceof EntityPlayer && getAttackState() != EnumReaperAttackState.REST) { EntityPlayer player = (EntityPlayer) arrow.shootingEntity; double newX = player.posX + rand.nextFloat() >= 0.50F ? 2 : -2; double newZ = player.posZ + rand.nextFloat() >= 0.50F ? 2 : -2; teleportTo(newX, player.posY, newZ); } arrow.setDead(); return false; } // Still take damage when healing, but reduced by a third. else if (this.getAttackState() == EnumReaperAttackState.REST) { damage /= 3; } super.attackEntityFrom(source, damage); if (!world.isRemote && this.getHealth() <= (this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).getBaseValue() / 2) && healingCooldown == 0) { setAttackState(EnumReaperAttackState.REST); healingCooldown = 4200; // 3 minutes 30 seconds teleportTo(this.posX, this.posY + 8, this.posZ); setStateTransitionCooldown(1200); // 1 minute } return true; } protected void attackEntity(Entity entity, float damage) { EntityLivingBase entityToAttack = this.getAttackTarget(); if (entityToAttack == null) return; // Set attack state to post attack. // If we're blocking, we will teleport away instead of attacking to prevent an unfair attack. // Attacking us WHILE we're blocking will cause us to attack, however. if (this.getDistance(entityToAttack) <= 0.8D && getAttackState() == EnumReaperAttackState.PRE) { if (getAttackState() == EnumReaperAttackState.BLOCK) { int rX = this.getRNG().nextInt(10); int rZ = this.getRNG().nextInt(10); teleportTo(this.posX + 5 + rX, this.posY, this.posZ + rZ); } else { entity.attackEntityFrom(DamageSource.causeMobDamage(this), this.world.getDifficulty().getDifficultyId() * 5.75F); if (entity instanceof EntityLivingBase) { ((EntityLivingBase) entity).addPotionEffect(new PotionEffect(MobEffects.WITHER, this.world.getDifficulty().getDifficultyId() * 20, 1)); } setAttackState(EnumReaperAttackState.POST); setStateTransitionCooldown(10); // For preventing immediate return to the PRE or IDLE stage. Ticked down in onUpdate() } } // Check if we're waiting for cooldown from the last attack. if (getStateTransitionCooldown() == 0) { // Within 3 blocks from the target, ready the scythe if (getDistance(entityToAttack) <= 3.5D) { // Check to see if the player's blocking, then teleport behind them. // Also randomly swap their selected item with something else in the hotbar and apply blindness. if (entityToAttack instanceof EntityPlayer) { EntityPlayer player = (EntityPlayer) entityToAttack; if (player.isActiveItemStackBlocking()) { double dX = this.posX - player.posX; double dZ = this.posZ - player.posZ; teleportTo(player.posX - (dX * 2), player.posY + 2, this.posZ - (dZ * 2)); if (!world.isRemote && rand.nextFloat() >= 0.20F) { int currentItem = player.inventory.currentItem; int randomItem = rand.nextInt(InventoryPlayer.getHotbarSize()); ItemStack currentItemStack = player.inventory.mainInventory.get(currentItem); ItemStack randomItemStack = player.inventory.mainInventory.get(randomItem); player.inventory.mainInventory.set(currentItem, randomItemStack); player.inventory.mainInventory.set(randomItem, currentItemStack); player.addPotionEffect(new PotionEffect(MobEffects.BLINDNESS, this.world.getDifficulty().getDifficultyId() * 40, 1)); } } else // If the player is not blocking, ready the scythe, or randomly block their attack. { // Don't block if we've already committed to an attack. if (rand.nextFloat() >= 40.0F && getAttackState() != EnumReaperAttackState.PRE) { setStateTransitionCooldown(20); setAttackState(EnumReaperAttackState.BLOCK); } else { setAttackState(EnumReaperAttackState.PRE); setStateTransitionCooldown(20); } } } } else // Reset the attacking state when we're more than 3 blocks away. { setAttackState(EnumReaperAttackState.IDLE); } } } protected Entity findPlayerToAttack() { return world.getClosestPlayerToEntity(this, 48.0D); } @Override public int getTalkInterval() { return 300; } @Override protected SoundEvent getAmbientSound() { return SoundsMCA.reaper_idle; } @Override protected SoundEvent getDeathSound() { return SoundsMCA.reaper_death; } @Override protected SoundEvent getHurtSound(DamageSource source) { return SoundEvents.ENTITY_WITHER_HURT; } @Override public void onUpdate() { super.onUpdate(); extinguish(); // No fire. if (!MCA.getConfig().allowGrimReaper) { setDead(); } EntityLivingBase entityToAttack = this.getAttackTarget(); if (entityToAttack != null && getAttackState() != EnumReaperAttackState.REST) { attackEntity(entityToAttack, 5.0F); this.getMoveHelper().setMoveTo(entityToAttack.posX, entityToAttack.posY, entityToAttack.posZ, 6.0F); } // Increment floating ticks on the client when resting. if (world.isRemote && getAttackState() == EnumReaperAttackState.REST) { floatingTicks += 0.1F; } // Increase health when resting and check to stop rest state. // Runs on common to spawn lightning. if (getAttackState() == EnumReaperAttackState.REST) { if (!world.isRemote && getStateTransitionCooldown() == 1) { setAttackState(EnumReaperAttackState.IDLE); timesHealed++; } else if (!world.isRemote && getStateTransitionCooldown() % 100 == 0) { this.setHealth(this.getHealth() + MathHelper.clamp(10.5F - (timesHealed * 3.5F), 3.0F, 10.5F)); // Let's have a light show. int dX = rand.nextInt(8) + 4 * rand.nextFloat() >= 0.50F ? 1 : -1; int dZ = rand.nextInt(8) + 4 * rand.nextFloat() >= 0.50F ? 1 : -1; int y = Util.getSpawnSafeTopLevel(world, (int) posX + dX, 256, (int) posZ + dZ); EntityLightningBolt bolt = new EntityLightningBolt(world, dX, y, dZ, false); world.addWeatherEffect(bolt); // Also spawn a random skeleton or zombie. if (!world.isRemote) { EntityMob mob = rand.nextFloat() >= 0.50F ? new EntityZombie(world) : new EntitySkeleton(world); mob.setPosition(posX + dX + 4, y, posZ + dZ + 4); if (mob instanceof EntitySkeleton) { mob.setItemStackToSlot(EntityEquipmentSlot.MAINHAND, new ItemStack(Items.BOW)); } world.spawnEntity(mob); } } } // Prevent flying off into oblivion on death... if (this.getHealth() <= 0.0F) { motionX = 0; motionY = 0; motionZ = 0; return; } // Stop at our current position if resting if (getAttackState() == EnumReaperAttackState.REST) { motionX = 0; motionY = 0; motionZ = 0; } // Logic for flying. fallDistance = 0.0F; if (motionY > 0) { motionY = motionY * 1.04F; } else { double yMod = Math.sqrt((motionX * motionX) + (motionZ * motionZ)); motionY = motionY * 0.6F + yMod * 0.3F; } // Tick down cooldowns. if (getStateTransitionCooldown() > 0) { setStateTransitionCooldown(getStateTransitionCooldown() - 1); } if (healingCooldown > 0) { healingCooldown--; } // See if our entity to attack has died at any point. if (entityToAttack != null && entityToAttack.isDead) { this.setAttackTarget(null); setAttackState(EnumReaperAttackState.IDLE); } // Move towards target if we're not resting if (entityToAttack != null && getAttackState() != EnumReaperAttackState.REST) { // If we have a creature to attack, we need to move downwards if we're above it, and vice-versa. double sqDistanceTo = Math.sqrt(Math.pow(entityToAttack.posX - posX, 2) + Math.pow(entityToAttack.posZ - posZ, 2)); float moveAmount = 0.0F; if (sqDistanceTo < 8F) { moveAmount = MathHelper.clamp(((8F - (float) sqDistanceTo) / 8F) * 4F, 0, 2.5F); } if (entityToAttack.posY + 0.2F < posY) { motionY = motionY - 0.05F * moveAmount; } if (entityToAttack.posY - 0.5F > posY) { motionY = motionY + 0.01F * moveAmount; } } } @Override public void onDeath(DamageSource source) { super.onDeath(source); } @Override public String getName() { return "Grim Reaper"; } @Override protected boolean canDespawn() { return true; } public int getStateTransitionCooldown() { return this.dataManager.get(STATE_TRANSITION_COOLDOWN); } public void setStateTransitionCooldown(int value) { this.dataManager.set(STATE_TRANSITION_COOLDOWN, value); } public float getFloatingTicks() { return floatingTicks; } private void teleportTo(double x, double y, double z) { if (!world.isRemote) { this.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 2.0F, 1.0F); this.setPosition(x, y, z); this.playSound(SoundEvents.ENTITY_ENDERMEN_TELEPORT, 2.0F, 1.0F); } } @Override public boolean isNonBoss() { return false; } /** * Add the given player to the list of players tracking this entity. For instance, a player may track a boss in * order to view its associated boss bar. */ @Override public void addTrackingPlayer(EntityPlayerMP player) { super.addTrackingPlayer(player); this.bossInfo.addPlayer(player); } /** * Removes the given player from the list of players tracking this entity. See {@link Entity#addTrackingPlayer} for * more information on tracking. */ @Override public void removeTrackingPlayer(EntityPlayerMP player) { super.removeTrackingPlayer(player); this.bossInfo.removePlayer(player); } } ================================================ FILE: src/main/java/mca/entity/EntityVillagerMCA.java ================================================ package mca.entity; import com.google.common.base.Optional; import com.google.common.base.Predicate; import mca.api.API; import mca.api.types.APIButton; import mca.core.Constants; import mca.core.MCA; import mca.core.forge.NetMCA; import mca.core.minecraft.ItemsMCA; import mca.core.minecraft.ProfessionsMCA; import mca.entity.ai.*; import mca.entity.data.ParentData; import mca.entity.data.PlayerHistory; import mca.entity.data.PlayerSaveData; import mca.entity.data.SavedVillagers; import mca.entity.inventory.InventoryMCA; import mca.enums.*; import mca.items.ItemSpecialCaseGift; import mca.util.ItemStackCache; import mca.util.ResourceLocationCache; import mca.util.Util; import net.minecraft.block.BlockBed; import net.minecraft.block.BlockHorizontal; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.Entity; import net.minecraft.entity.SharedMonsterAttributes; import net.minecraft.entity.ai.*; import net.minecraft.entity.monster.EntityVex; import net.minecraft.entity.monster.EntityVindicator; import net.minecraft.entity.monster.EntityZombie; import net.minecraft.entity.passive.EntityHorse; import net.minecraft.entity.passive.EntityVillager; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.init.SoundEvents; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.datasync.DataParameter; import net.minecraft.network.datasync.DataSerializers; import net.minecraft.network.datasync.EntityDataManager; import net.minecraft.util.*; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.registry.RegistryNamespaced; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; import net.minecraftforge.fml.common.ObfuscationReflectionHelper; import net.minecraftforge.fml.common.registry.VillagerRegistry; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nonnull; import javax.annotation.Nullable; import java.util.*; import static net.minecraft.block.BlockBed.OCCUPIED; import static net.minecraft.block.BlockBed.PART; public class EntityVillagerMCA extends EntityVillager { public static final int VANILLA_CAREER_ID_FIELD_INDEX = 13; public static final int VANILLA_CAREER_LEVEL_FIELD_INDEX = 14; public static final DataParameter VILLAGER_NAME = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.STRING); public static final DataParameter TEXTURE = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.STRING); public static final DataParameter GENDER = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.VARINT); public static final DataParameter GIRTH = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.FLOAT); public static final DataParameter TALLNESS = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.FLOAT); public static final DataParameter PLAYER_HISTORY_MAP = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.COMPOUND_TAG); public static final DataParameter MOVE_STATE = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.VARINT); public static final DataParameter SPOUSE_NAME = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.STRING); public static final DataParameter> SPOUSE_UUID = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.OPTIONAL_UNIQUE_ID); public static final DataParameter MARRIAGE_STATE = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.VARINT); public static final DataParameter IS_PROCREATING = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BOOLEAN); public static final DataParameter PARENTS = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.COMPOUND_TAG); public static final DataParameter IS_INFECTED = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BOOLEAN); public static final DataParameter AGE_STATE = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.VARINT); public static final DataParameter ACTIVE_CHORE = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.VARINT); public static final DataParameter IS_SWINGING = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BOOLEAN); public static final DataParameter HAS_BABY = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BOOLEAN); public static final DataParameter BABY_IS_MALE = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BOOLEAN); public static final DataParameter BABY_AGE = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.VARINT); public static final DataParameter> CHORE_ASSIGNING_PLAYER = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.OPTIONAL_UNIQUE_ID); public static final DataParameter BED_POS = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BLOCK_POS); public static final DataParameter WORKPLACE_POS = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BLOCK_POS); public static final DataParameter HANGOUT_POS = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BLOCK_POS); public static final DataParameter SLEEPING = EntityDataManager.createKey(EntityVillagerMCA.class, DataSerializers.BOOLEAN); private static final Predicate BANDIT_TARGET_SELECTOR = (v) -> v.getProfessionForge() != ProfessionsMCA.bandit && v.getProfessionForge() != ProfessionsMCA.child; private static final Predicate GUARD_TARGET_SELECTOR = (v) -> v.getProfessionForge() == ProfessionsMCA.bandit; public final InventoryMCA inventory; public int babyAge = 0; public UUID playerToFollowUUID = Constants.ZERO_UUID; private BlockPos home = BlockPos.ORIGIN; private int startingAge = 0; private float swingProgressTicks; public float renderOffsetX; public float renderOffsetY; public float renderOffsetZ; public EntityVillagerMCA() { super(null); inventory = null; } public EntityVillagerMCA(World worldIn) { super(worldIn); inventory = new InventoryMCA(this); } public EntityVillagerMCA(World worldIn, Optional profession, Optional gender) { this(worldIn); if (!worldIn.isRemote) { EnumGender eGender = gender.isPresent() ? gender.get() : EnumGender.getRandom(); set(GENDER, eGender.getId()); set(VILLAGER_NAME, API.getRandomName(eGender)); setProfession(profession.isPresent() ? profession.get() : ProfessionsMCA.randomProfession()); setVanillaCareer(getProfessionForge().getRandomCareer(worldIn.rand)); set(TEXTURE, API.getRandomSkin(this)); applySpecialAI(); } } @Override protected void entityInit() { super.entityInit(); this.dataManager.register(VILLAGER_NAME, ""); this.dataManager.register(TEXTURE, ""); this.dataManager.register(GENDER, EnumGender.MALE.getId()); this.dataManager.register(GIRTH, 0.0F); this.dataManager.register(TALLNESS, 0.0F); this.dataManager.register(PLAYER_HISTORY_MAP, new NBTTagCompound()); this.dataManager.register(MOVE_STATE, EnumMoveState.MOVE.getId()); this.dataManager.register(SPOUSE_NAME, ""); this.dataManager.register(SPOUSE_UUID, Optional.of(Constants.ZERO_UUID)); this.dataManager.register(MARRIAGE_STATE, EnumMarriageState.NOT_MARRIED.getId()); this.dataManager.register(IS_PROCREATING, false); this.dataManager.register(PARENTS, new NBTTagCompound()); this.dataManager.register(IS_INFECTED, false); this.dataManager.register(AGE_STATE, EnumAgeState.ADULT.getId()); this.dataManager.register(ACTIVE_CHORE, EnumChore.NONE.getId()); this.dataManager.register(IS_SWINGING, false); this.dataManager.register(HAS_BABY, false); this.dataManager.register(BABY_IS_MALE, false); this.dataManager.register(BABY_AGE, 0); this.dataManager.register(CHORE_ASSIGNING_PLAYER, Optional.of(Constants.ZERO_UUID)); this.dataManager.register(BED_POS, BlockPos.ORIGIN); this.dataManager.register(WORKPLACE_POS, BlockPos.ORIGIN); this.dataManager.register(HANGOUT_POS, BlockPos.ORIGIN); this.dataManager.register(SLEEPING, false); this.setSilent(false); } @Override protected void applyEntityAttributes() { super.applyEntityAttributes(); this.getEntityAttribute(SharedMonsterAttributes.MAX_HEALTH).setBaseValue(MCA.getConfig().villagerMaxHealth); this.getEntityAttribute(SharedMonsterAttributes.FOLLOW_RANGE).setBaseValue(32.0D); if (this.getHealth() <= MCA.getConfig().villagerMaxHealth) { this.setHealth(MCA.getConfig().villagerMaxHealth); } } public T get(DataParameter key) { return this.dataManager.get(key); } public void set(DataParameter key, T value) { this.dataManager.set(key, value); } @Override public boolean attackEntityAsMob(@Nonnull Entity entityIn) { super.attackEntityAsMob(entityIn); return entityIn.attackEntityFrom(DamageSource.causeMobDamage(this), this.getProfessionForge() == ProfessionsMCA.guard ? 9.0F : 2.0F); } @Override public void readEntityFromNBT(NBTTagCompound nbt) { super.readEntityFromNBT(nbt); set(VILLAGER_NAME, nbt.getString("name")); set(GENDER, nbt.getInteger("gender")); set(TEXTURE, nbt.getString("texture")); set(GIRTH, nbt.getFloat("girth")); set(TALLNESS, nbt.getFloat("tallness")); set(PLAYER_HISTORY_MAP, nbt.getCompoundTag("playerHistoryMap")); set(MOVE_STATE, nbt.getInteger("moveState")); set(MARRIAGE_STATE, nbt.getInteger("marriageState")); set(SPOUSE_UUID, Optional.of(nbt.getUniqueId("spouseUUID"))); set(SPOUSE_NAME, nbt.getString("spouseName")); set(IS_PROCREATING, nbt.getBoolean("isProcreating")); set(IS_INFECTED, nbt.getBoolean("infected")); set(AGE_STATE, nbt.getInteger("ageState")); set(ACTIVE_CHORE, nbt.getInteger("activeChore")); set(CHORE_ASSIGNING_PLAYER, Optional.of(nbt.getUniqueId("choreAssigningPlayer"))); set(HAS_BABY, nbt.getBoolean("hasBaby")); set(BABY_IS_MALE, nbt.getBoolean("babyIsMale")); set(PARENTS, nbt.getCompoundTag("parents")); set(BED_POS, new BlockPos(nbt.getInteger("bedX"), nbt.getInteger("bedY"), nbt.getInteger("bedZ"))); set(HANGOUT_POS, new BlockPos(nbt.getInteger("hangoutX"), nbt.getInteger("hangoutY"), nbt.getInteger("hangoutZ"))); set(WORKPLACE_POS, new BlockPos(nbt.getInteger("workplaceX"), nbt.getInteger("workplaceY"), nbt.getInteger("workplaceZ"))); set(SLEEPING, nbt.getBoolean("sleeping")); inventory.readInventoryFromNBT(nbt.getTagList("inventory", 10)); // Vanilla Age doesn't apply from the superclass call. Causes children to revert to the starting age on world reload. this.startingAge = nbt.getInteger("startingAge"); setGrowingAge(nbt.getInteger("Age")); this.home = new BlockPos(nbt.getDouble("homePositionX"), nbt.getDouble("homePositionY"), nbt.getDouble("homePositionZ")); this.playerToFollowUUID = nbt.getUniqueId("playerToFollowUUID"); this.babyAge = nbt.getInteger("babyAge"); applySpecialAI(); } @Override public void writeEntityToNBT(NBTTagCompound nbt) { super.writeEntityToNBT(nbt); nbt.setUniqueId("uuid", this.getUniqueID()); // for SavedVillagers nbt.setString("name", get(VILLAGER_NAME)); nbt.setString("texture", get(TEXTURE)); nbt.setInteger("gender", get(GENDER)); nbt.setFloat("girth", get(GIRTH)); nbt.setFloat("tallness", get(TALLNESS)); nbt.setTag("playerHistoryMap", get(PLAYER_HISTORY_MAP)); nbt.setInteger("moveState", get(MOVE_STATE)); nbt.setInteger("marriageState", get(MARRIAGE_STATE)); nbt.setDouble("homePositionX", home.getX()); nbt.setDouble("homePositionY", home.getY()); nbt.setDouble("homePositionZ", home.getZ()); nbt.setUniqueId("playerToFollowUUID", playerToFollowUUID); nbt.setUniqueId("spouseUUID", get(SPOUSE_UUID).or(Constants.ZERO_UUID)); nbt.setString("spouseName", get(SPOUSE_NAME)); nbt.setBoolean("isProcreating", get(IS_PROCREATING)); nbt.setBoolean("infected", get(IS_INFECTED)); nbt.setInteger("ageState", get(AGE_STATE)); nbt.setInteger("startingAge", startingAge); nbt.setInteger("activeChore", get(ACTIVE_CHORE)); nbt.setUniqueId("choreAssigningPlayer", get(CHORE_ASSIGNING_PLAYER).or(Constants.ZERO_UUID)); nbt.setTag("inventory", inventory.writeInventoryToNBT()); nbt.setInteger("babyAge", babyAge); nbt.setTag("parents", get(PARENTS)); nbt.setInteger("bedX", get(BED_POS).getX()); nbt.setInteger("bedY", get(BED_POS).getY()); nbt.setInteger("bedZ", get(BED_POS).getZ()); nbt.setInteger("workplaceX", get(WORKPLACE_POS).getX()); nbt.setInteger("workplaceY", get(WORKPLACE_POS).getY()); nbt.setInteger("workplaceZ", get(WORKPLACE_POS).getZ()); nbt.setInteger("hangoutX", get(HANGOUT_POS).getX()); nbt.setInteger("hangoutY", get(HANGOUT_POS).getY()); nbt.setInteger("hangoutZ", get(HANGOUT_POS).getZ()); nbt.setBoolean("sleeping", get(SLEEPING)); } @Override protected void damageEntity(@Nonnull DamageSource damageSource, float damageAmount) { // Guards take 50% less damage if (getProfessionForge() == ProfessionsMCA.guard) { damageAmount *= 0.50; } super.damageEntity(damageSource, damageAmount); // Check for infection to apply. Does not affect guards. if (MCA.getConfig().enableInfection && getProfessionForge() != ProfessionsMCA.guard && damageSource.getImmediateSource() instanceof EntityZombie && getRNG().nextFloat() < MCA.getConfig().infectionChance / 100) { set(IS_INFECTED, true); } } @Override public void onUpdate() { super.onUpdate(); updateSwinging(); updateSleeping(); if (this.isServerWorld()) { onEachServerUpdate(); } else { onEachClientUpdate(); } } @Override protected SoundEvent getAmbientSound() { return null; } @Override protected SoundEvent getHurtSound(DamageSource damageSourceIn) { return SoundEvents.ENTITY_GENERIC_HURT; } @Override protected SoundEvent getDeathSound() { return get(IS_INFECTED) ? SoundEvents.ENTITY_ZOMBIE_DEATH : null; } @Override public boolean processInteract(EntityPlayer player, @Nonnull EnumHand hand) { // No-op, handled by EventHooks return true; } @Override public void onDeath(@Nonnull DamageSource cause) { if (!world.isRemote) { if (MCA.getConfig().logVillagerDeaths) { String causeName = cause.getImmediateSource() == null ? "Unknown" : cause.getImmediateSource().getName(); MCA.getLog().info("Villager death: " + get(VILLAGER_NAME) + ". Caused by: " + causeName + ". UUID: " + this.getUniqueID().toString()); } //TODO: player history gets lsot on revive //TODO: childp becomes to child on revive (needs verification) inventory.dropAllItems(); inventory.clear(); //fixes issue #1227, dropAllItems() should clear, but it does not work if (isMarried()) { UUID spouseUUID = get(SPOUSE_UUID).or(Constants.ZERO_UUID); Optional spouse = Util.getEntityByUUID(world, spouseUUID, EntityVillagerMCA.class); PlayerSaveData playerSaveData = PlayerSaveData.getExisting(world, spouseUUID); // Notify spouse of the death if (spouse.isPresent()) { spouse.get().endMarriage(); } else if (playerSaveData != null) { playerSaveData.endMarriage(); EntityPlayer player = world.getPlayerEntityByUUID(spouseUUID); if (player != null) { player.sendMessage(new TextComponentString(Constants.Color.RED + MCA.getLocalizer().localize("notify.spousedied", get(VILLAGER_NAME), cause.getImmediateSource().getName()))); } } } // Notify all parents of the death ParentData parents = ParentData.fromNBT(get(PARENTS)); Arrays.stream(parents.getParentEntities(world)) .filter(e -> e instanceof EntityPlayer) .forEach(e -> { EntityPlayer player = (EntityPlayer) e; player.sendMessage(new TextComponentString(Constants.Color.RED + MCA.getLocalizer().localize("notify.childdied", get(VILLAGER_NAME), cause.getImmediateSource().getName()))); }); SavedVillagers.get(world).save(this); } } @Override protected void onGrowingAdult() { Entity[] parents = ParentData.fromNBT(get(PARENTS)).getParentEntities(world); set(AGE_STATE, EnumAgeState.ADULT.getId()); Arrays.stream(parents).filter((e) -> e instanceof EntityPlayer).forEach((e) -> { PlayerHistory history = getPlayerHistoryFor(e.getUniqueID()); history.setDialogueType(EnumDialogueType.ADULT); e.sendMessage(new TextComponentString(MCA.getLocalizer().localize("notify.child.grownup", this.get(VILLAGER_NAME)))); }); // set profession away from child for villager children if (getProfessionForge() == ProfessionsMCA.child) { setProfession(ProfessionsMCA.randomProfession()); setVanillaCareer(getProfessionForge().getRandomCareer(world.rand)); } } @Override @Nonnull public ITextComponent getDisplayName() { // translate profession name ITextComponent careerName = new TextComponentTranslation("entity.Villager." + getVanillaCareer().getName()); EnumAgeState age = EnumAgeState.byId(get(AGE_STATE)); String professionName = age != EnumAgeState.ADULT ? age.localizedName() : careerName.getUnformattedText(); String color = this.getProfessionForge() == ProfessionsMCA.bandit ? Constants.Color.RED : this.getProfessionForge() == ProfessionsMCA.guard ? Constants.Color.GREEN : ""; return new TextComponentString(String.format("%1$s%2$s%3$s (%4$s)", color, MCA.getConfig().villagerChatPrefix, get(VILLAGER_NAME), professionName)); } @Override @Nonnull public String getCustomNameTag() { return get(VILLAGER_NAME); } @Override @Nonnull public boolean hasCustomName() { return true; } @Override public void swingArm(EnumHand hand) { this.setActiveHand(EnumHand.MAIN_HAND); super.swingArm(EnumHand.MAIN_HAND); if (!get(IS_SWINGING) || swingProgressTicks >= 8 / 2 || swingProgressTicks < 0) { swingProgressTicks = -1; set(IS_SWINGING, true); } } private void updateSwinging() { if (get(IS_SWINGING)) { swingProgressTicks++; if (swingProgressTicks >= 8) { swingProgressTicks = 0; set(IS_SWINGING, false); } } else { swingProgressTicks = 0; } swingProgress = swingProgressTicks / (float) 8; } @Override @Nonnull public ItemStack getItemStackFromSlot(EntityEquipmentSlot slotIn) { if (slotIn == EntityEquipmentSlot.MAINHAND) { VillagerRegistry.VillagerProfession profession = getProfessionForge(); EnumChore chore = EnumChore.byId(get(ACTIVE_CHORE)); if (get(HAS_BABY)) { return ItemStackCache.get(get(BABY_IS_MALE) ? ItemsMCA.BABY_BOY : ItemsMCA.BABY_GIRL); } else if (chore != EnumChore.NONE) { return inventory.getBestItemOfType(chore.getToolType()); } else { return ProfessionsMCA.getDefaultHeldItem(profession, getVanillaCareer()); } } else { return inventory.getBestArmorOfType(slotIn); } } public void setStartingAge(int value) { this.startingAge = value; setGrowingAge(value); } public PlayerHistory getPlayerHistoryFor(UUID uuid) { if (!get(PLAYER_HISTORY_MAP).hasKey(uuid.toString())) { updatePlayerHistoryMap(PlayerHistory.getNew(this, uuid)); } return PlayerHistory.fromNBT(this, uuid, get(PLAYER_HISTORY_MAP).getCompoundTag(uuid.toString())); } public void updatePlayerHistoryMap(PlayerHistory history) { NBTTagCompound nbt = get(PLAYER_HISTORY_MAP); nbt.setTag(history.getPlayerUUID().toString(), history.toNBT()); set(PLAYER_HISTORY_MAP, nbt); this.dataManager.setDirty(PLAYER_HISTORY_MAP); } public void reset() { set(PLAYER_HISTORY_MAP, new NBTTagCompound()); dataManager.setDirty(PLAYER_HISTORY_MAP); setHealth(20.0F); set(SPOUSE_NAME, ""); set(SPOUSE_UUID, Optional.of(Constants.ZERO_UUID)); set(MARRIAGE_STATE, EnumMarriageState.NOT_MARRIED.getId()); set(HAS_BABY, false); } public VillagerRegistry.VillagerCareer getVanillaCareer() { return this.getProfessionForge().getCareer(ObfuscationReflectionHelper.getPrivateValue(EntityVillager.class, this, VANILLA_CAREER_ID_FIELD_INDEX)); } public void setVanillaCareer(int careerId) { ObfuscationReflectionHelper.setPrivateValue(EntityVillager.class, this, careerId, VANILLA_CAREER_ID_FIELD_INDEX); } private void setSizeForAge() { EnumAgeState age = EnumAgeState.byId(get(AGE_STATE)); this.setSize(age.getWidth(), age.getHeight()); this.setScale(1.0F); // trigger rebuild of the bounding box } private void toggleMount(EntityPlayerMP player) { if (getRidingEntity() != null) { dismountRidingEntity(); } else { try { List horses = world.getEntities(EntityHorse.class, h -> (h.isHorseSaddled() && !h.isBeingRidden() && h.getDistance(this) < 3.0D)); startRiding(horses.stream().min(Comparator.comparingDouble(this::getDistance)).get(), true); getNavigator().clearPath(); } catch (NoSuchElementException e) { say(Optional.of(player), "interaction.ridehorse.fail.notnearby"); } } } private void goHome(EntityPlayerMP player) { if (home.equals(Vec3d.ZERO)) { say(Optional.of(player), "interaction.gohome.fail"); } else { say(Optional.of(player), "interaction.gohome.success"); if (!getNavigator().setPath(getNavigator().getPathToXYZ(home.getX(), home.getY(), home.getZ()), 1.0D)) { attemptTeleport(home.getX(), home.getY(), home.getZ()); } } } public BlockPos getWorkplace() { return get(WORKPLACE_POS); } public BlockPos getHangout() { return get(HANGOUT_POS); } /** * Forces the villager's home to be set to their position. No checks for safety are made. * This is used on overwriting the original villager. */ public void forcePositionAsHome() { this.home = this.getPosition(); } private void setHome(EntityPlayerMP player) { if (attemptTeleport(player.posX, player.posY, player.posZ)) { say(Optional.of(player), "interaction.sethome.success"); this.home = player.getPosition(); this.setHomePosAndDistance(this.home, 32); BlockPos bed = searchBed(); if (bed != null) { set(BED_POS, bed); } } else { say(Optional.of(player), "interaction.sethome.fail"); } } public void setWorkplace(EntityPlayerMP player) { say(Optional.of(player), "interaction.setworkplace.success"); set(WORKPLACE_POS, player.getPosition()); } public void setHangout(EntityPlayerMP player) { say(Optional.of(player), "interaction.sethangout.success"); set(HANGOUT_POS, player.getPosition()); } public void say(Optional player, String phraseId, @Nullable String... params) { ArrayList paramsList = new ArrayList<>(); if (params != null) Collections.addAll(paramsList, params); if (player.isPresent()) { EntityPlayer thePlayer = player.get(); // Provide player as the first param, always paramsList.add(0, thePlayer.getName()); // Infected villagers do not speak. if (get(IS_INFECTED)) { thePlayer.sendMessage(new TextComponentString(getDisplayName().getFormattedText() + ": " + "???")); this.playSound(SoundEvents.ENTITY_ZOMBIE_AMBIENT, 0.5F, rand.nextFloat() + 0.5F); } else { String dialogueType = getPlayerHistoryFor(player.get().getUniqueID()).getDialogueType().getId(); String phrase = MCA.getLocalizer().localize(dialogueType + "." + phraseId, paramsList); thePlayer.sendMessage(new TextComponentString(String.format("%1$s: %2$s", getDisplayName().getFormattedText(), phrase))); } } else { MCA.getLog().warn(new Throwable("Say called on player that is not present!")); } } public boolean isMarried() { return !get(SPOUSE_UUID).or(Constants.ZERO_UUID).equals(Constants.ZERO_UUID); } public boolean isMarriedTo(UUID uuid) { return get(SPOUSE_UUID).or(Constants.ZERO_UUID).equals(uuid); } public void marry(EntityPlayer player) { set(SPOUSE_UUID, Optional.of(player.getUniqueID())); set(SPOUSE_NAME, player.getName()); set(MARRIAGE_STATE, EnumMarriageState.MARRIED.getId()); } private void endMarriage() { set(SPOUSE_UUID, Optional.of(Constants.ZERO_UUID)); set(SPOUSE_NAME, ""); set(MARRIAGE_STATE, EnumMarriageState.NOT_MARRIED.getId()); } private void handleInteraction(EntityPlayerMP player, PlayerHistory history, APIButton button) { float successChance = 0.85F; int heartsBoost = button.getConstraints().contains(EnumConstraint.ADULTS) ? 15 : 5; String interactionName = button.getIdentifier().replace("gui.button.", ""); successChance -= button.getConstraints().contains(EnumConstraint.ADULTS) ? 0.25F : 0.0F; successChance += (history.getHearts() / 10.0D) * 0.025F; if (MCA.getConfig().enableDiminishingReturns) successChance -= history.getInteractionFatigue() * 0.05F; boolean succeeded = rand.nextFloat() < successChance; if (MCA.getConfig().enableDiminishingReturns && succeeded) heartsBoost -= history.getInteractionFatigue() * 0.05F; history.changeInteractionFatigue(1); history.changeHearts(succeeded ? heartsBoost : (heartsBoost * -1)); String responseId = String.format("%s.%s", interactionName, succeeded ? "success" : "fail"); say(Optional.of(player), responseId); } public void handleButtonClick(EntityPlayerMP player, String guiKey, String buttonId) { PlayerHistory history = getPlayerHistoryFor(player.getUniqueID()); java.util.Optional button = API.getButtonById(guiKey, buttonId); if (!button.isPresent()) { MCA.getLog().warn("Button not found for key and ID: " + guiKey + ", " + buttonId); } else if (button.get().isInteraction()) handleInteraction(player, history, button.get()); switch (buttonId) { case "gui.button.move": set(MOVE_STATE, EnumMoveState.MOVE.getId()); this.playerToFollowUUID = Constants.ZERO_UUID; break; case "gui.button.stay": set(MOVE_STATE, EnumMoveState.STAY.getId()); break; case "gui.button.follow": set(MOVE_STATE, EnumMoveState.FOLLOW.getId()); this.playerToFollowUUID = player.getUniqueID(); stopChore(); break; case "gui.button.ridehorse": toggleMount(player); break; case "gui.button.sethome": setHome(player); break; case "gui.button.gohome": goHome(player); break; case "gui.button.setworkplace": setWorkplace(player); break; case "gui.button.sethangout": setHangout(player); break; case "gui.button.trade": if (MCA.getConfig().allowTrading) { setCustomer(player); player.displayVillagerTradeGui(this); } else { player.sendMessage(new TextComponentString(MCA.getLocalizer().localize("info.trading.disabled"))); } break; case "gui.button.inventory": player.openGui(MCA.getInstance(), Constants.GUI_ID_INVENTORY, player.world, this.getEntityId(), 0, 0); break; case "gui.button.gift": ItemStack stack = player.inventory.getStackInSlot(player.inventory.currentItem); int giftValue = API.getGiftValueFromStack(stack); if (!handleSpecialCaseGift(player, stack)) { if (stack.getItem() == Items.GOLDEN_APPLE) set(IS_INFECTED, false); else { history.changeHearts(giftValue); say(Optional.of(player), API.getResponseForGift(stack)); } } if (giftValue > 0) { player.inventory.decrStackSize(player.inventory.currentItem, 1); } break; case "gui.button.procreate": if (PlayerSaveData.get(player).isBabyPresent()) say(Optional.of(player), "interaction.procreate.fail.hasbaby"); else if (history.getHearts() < 100) say(Optional.of(player), "interaction.procreate.fail.lowhearts"); else { EntityAITasks.EntityAITaskEntry task = tasks.taskEntries.stream().filter((ai) -> ai.action instanceof EntityAIProcreate).findFirst().orElse(null); if (task != null) { ((EntityAIProcreate) task.action).procreateTimer = 20 * 3; // 3 seconds set(IS_PROCREATING, true); } } break; case "gui.button.infected": set(IS_INFECTED, !get(IS_INFECTED)); break; case "gui.button.texture.randomize": set(TEXTURE, API.getRandomSkin(this)); break; case "gui.button.profession.randomize": setProfession(ProfessionsMCA.randomProfession()); setVanillaCareer(getProfessionForge().getRandomCareer(world.rand)); break; case "gui.button.gender": EnumGender gender = EnumGender.byId(get(GENDER)); if (gender == EnumGender.MALE) { set(GENDER, EnumGender.FEMALE.getId()); } else { set(GENDER, EnumGender.MALE.getId()); } // intentional fall-through here case "gui.button.texture": set(TEXTURE, API.getRandomSkin(this)); break; case "gui.button.random": set(VILLAGER_NAME, API.getRandomName(EnumGender.byId(get(GENDER)))); break; case "gui.button.profession": RegistryNamespaced registry = ObfuscationReflectionHelper.getPrivateValue(VillagerRegistry.class, VillagerRegistry.instance(), "REGISTRY"); setProfession(ProfessionsMCA.randomProfession()); setVanillaCareer(getProfessionForge().getRandomCareer(world.rand)); applySpecialAI(); break; case "gui.button.prospecting": startChore(EnumChore.PROSPECT, player); break; case "gui.button.hunting": startChore(EnumChore.HUNT, player); break; case "gui.button.fishing": startChore(EnumChore.FISH, player); break; case "gui.button.chopping": startChore(EnumChore.CHOP, player); break; case "gui.button.harvesting": startChore(EnumChore.HARVEST, player); break; case "gui.button.stopworking": stopChore(); break; } } private boolean handleSpecialCaseGift(EntityPlayer player, ItemStack stack) { Item item = stack.getItem(); if (item instanceof ItemSpecialCaseGift && !this.isChild()) { // special case gifts are rings so far so prevent giving them to children boolean decStackSize = ((ItemSpecialCaseGift) item).handle(player, this); if (decStackSize) player.inventory.decrStackSize(player.inventory.currentItem, -1); return true; } else if (item == Items.CAKE) { Optional spouse = Util.getEntityByUUID(world, get(SPOUSE_UUID).or(Constants.ZERO_UUID)); if (spouse.isPresent()) { EntityVillagerMCA progressor = this.get(GENDER) == EnumGender.FEMALE.getId() ? this : (EntityVillagerMCA) spouse.get(); progressor.set(HAS_BABY, true); progressor.set(BABY_IS_MALE, rand.nextBoolean()); progressor.spawnParticles(EnumParticleTypes.HEART); } else say(Optional.of(player), "gift.cake.fail"); } else if (item == Items.GOLDEN_APPLE && this.isChild()) { this.addGrowth(((startingAge / 4) / 20 * -1)); return true; } return false; } private void onEachClientUpdate() { if (get(IS_PROCREATING)) { this.rotationYawHead += 50.0F; } if (this.ticksExisted % 20 == 0) { onEachClientSecond(); } } private void onEachClientSecond() { this.setSizeForAge(); } private void onEachServerUpdate() { if (this.ticksExisted % 20 == 0) { // Every second onEachServerSecond(); } if (this.ticksExisted % 200 == 0 && this.getHealth() > 0.0F) { // Every 10 seconds and when we're not already dead if (this.getHealth() < this.getMaxHealth()) { this.setHealth(this.getHealth() + 1.0F); // heal } } if (isChild()) { EnumAgeState current = EnumAgeState.byId(get(AGE_STATE)); EnumAgeState target = EnumAgeState.byCurrentAge(startingAge, getGrowingAge()); if (current != target) { set(AGE_STATE, target.getId()); } } } private void onEachServerSecond() { NBTTagCompound memories = get(PLAYER_HISTORY_MAP); memories.getKeySet().forEach((key) -> PlayerHistory.fromNBT(this, UUID.fromString(key), memories.getCompoundTag(key)).update()); if (get(HAS_BABY)) { set(BABY_AGE, get(BABY_AGE) + 1); if (get(BABY_AGE) >= MCA.getConfig().babyGrowUpTime * 60) { // grow up time is in minutes and we measure age in seconds EntityVillagerMCA child = new EntityVillagerMCA(world, Optional.absent(), Optional.of(get(BABY_IS_MALE) ? EnumGender.MALE : EnumGender.FEMALE)); child.set(EntityVillagerMCA.AGE_STATE, EnumAgeState.BABY.getId()); child.setStartingAge(MCA.getConfig().childGrowUpTime * 60 * 20 * -1); child.setScaleForAge(true); child.setPosition(this.posX, this.posY, this.posZ); child.set(EntityVillagerMCA.PARENTS, ParentData.create(this.getUniqueID(), this.get(SPOUSE_UUID).get(), this.get(VILLAGER_NAME), this.get(SPOUSE_NAME)).toNBT()); world.spawnEntity(child); set(HAS_BABY, false); set(BABY_AGE, 0); } } } public ResourceLocation getTextureResourceLocation() { if (get(IS_INFECTED)) { return ResourceLocationCache.getResourceLocationFor(String.format("mca:skins/%s/zombievillager.png", get(GENDER) == EnumGender.MALE.getId() ? "male" : "female")); } else { return ResourceLocationCache.getResourceLocationFor(get(TEXTURE)); } } @Override protected void initEntityAI() { super.initEntityAI(); this.tasks.addTask(0, new EntityAIProspecting(this)); this.tasks.addTask(0, new EntityAIHunting(this)); this.tasks.addTask(0, new EntityAIChopping(this)); this.tasks.addTask(0, new EntityAIHarvesting(this)); this.tasks.addTask(0, new EntityAIFishing(this)); this.tasks.addTask(0, new EntityAIMoveState(this)); this.tasks.addTask(0, new EntityAIAgeBaby(this)); this.tasks.addTask(0, new EntityAIProcreate(this)); this.tasks.addTask(5, new EntityAIGoWorkplace(this)); this.tasks.addTask(5, new EntityAIGoHangout(this)); this.tasks.addTask(1, new EntityAISleeping(this)); this.tasks.addTask(10, new EntityAIWatchClosest(this, EntityPlayer.class, 8.0F)); this.tasks.addTask(10, new EntityAILookIdle(this)); } private void applySpecialAI() { if (getProfessionForge() == ProfessionsMCA.bandit) { this.tasks.taskEntries.clear(); this.tasks.addTask(1, new EntityAIAttackMelee(this, 0.8D, false)); this.tasks.addTask(2, new EntityAIMoveThroughVillage(this, 0.6D, false)); this.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(this, EntityVillagerMCA.class, 100, false, false, BANDIT_TARGET_SELECTOR)); this.targetTasks.addTask(1, new EntityAINearestAttackableTarget<>(this, EntityPlayer.class, true)); } else if (getProfessionForge() == ProfessionsMCA.guard) { removeCertainTasks(EntityAIAvoidEntity.class); this.tasks.addTask(1, new EntityAIAttackMelee(this, 0.8D, false)); this.tasks.addTask(2, new EntityAIMoveThroughVillage(this, 0.6D, false)); this.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(this, EntityVillagerMCA.class, 100, false, false, GUARD_TARGET_SELECTOR)); this.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(this, EntityZombie.class, 100, false, false, null)); this.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(this, EntityVex.class, 100, false, false, null)); this.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(this, EntityVindicator.class, 100, false, false, null)); } else { //every other villager is allowed to defend itself from zombies while fleeing this.tasks.addTask(0, new EntityAIDefendFromTarget(this)); this.targetTasks.taskEntries.clear(); this.targetTasks.addTask(0, new EntityAINearestAttackableTarget<>(this, EntityZombie.class, 100, false, false, null)); } } //guards should not run away from zombies //TODO: should only avoid zombies when low on health private void removeCertainTasks(Class typ) { Iterator iterator = this.tasks.taskEntries.iterator(); while (iterator.hasNext()) { EntityAITasks.EntityAITaskEntry entityaitasks$entityaitaskentry = iterator.next(); EntityAIBase entityaibase = entityaitasks$entityaitaskentry.action; if (entityaibase.getClass().equals(typ)) { iterator.remove(); } } } public void spawnParticles(EnumParticleTypes particleType) { if (this.world.isRemote) { for (int i = 0; i < 5; ++i) { double d0 = this.rand.nextGaussian() * 0.02D; double d1 = this.rand.nextGaussian() * 0.02D; double d2 = this.rand.nextGaussian() * 0.02D; this.world.spawnParticle(particleType, this.posX + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, this.posY + 1.0D + (double) (this.rand.nextFloat() * this.height), this.posZ + (double) (this.rand.nextFloat() * this.width * 2.0F) - (double) this.width, d0, d1, d2); } } else { NetMCA.INSTANCE.sendToAll(new NetMCA.SpawnParticles(this.getUniqueID(), particleType)); } } public void stopChore() { set(ACTIVE_CHORE, EnumChore.NONE.getId()); set(CHORE_ASSIGNING_PLAYER, Optional.of(Constants.ZERO_UUID)); } public void startChore(EnumChore chore, EntityPlayer player) { set(ACTIVE_CHORE, chore.getId()); set(CHORE_ASSIGNING_PLAYER, Optional.of(player.getUniqueID())); } public boolean playerIsParent(EntityPlayer player) { ParentData data = ParentData.fromNBT(get(PARENTS)); return data.getParent1UUID().equals(player.getUniqueID()) || data.getParent2UUID().equals(player.getUniqueID()); } @Override public BlockPos getHomePosition() { return home; } @Override public void detachHome() { // no-op, skip EntityVillager's detaching homes which messes up MoveTowardsRestriction. } public String getCurrentActivity() { EnumMoveState moveState = EnumMoveState.byId(get(MOVE_STATE)); if (moveState != EnumMoveState.MOVE) { return moveState.getFriendlyName(); } EnumChore chore = EnumChore.byId(get(ACTIVE_CHORE)); if (chore != EnumChore.NONE) { return chore.getFriendlyName(); } return null; } public void moveTowardsBlock(BlockPos target) { moveTowardsBlock(target, 0.5D); } public void moveTowardsBlock(BlockPos target, double speed) { double range = getNavigator().getPathSearchRange() - 6.0D; if (getDistanceSq(target) > Math.pow(range, 2.0)) { Vec3d vec3d = RandomPositionGenerator.findRandomTargetBlockTowards(this, (int) range, 8, new Vec3d(target.getX(), target.getY(), target.getZ())); if (vec3d != null && !getNavigator().setPath(getNavigator().getPathToXYZ(vec3d.x, vec3d.y, vec3d.z), speed)) { attemptTeleport(vec3d.x, vec3d.y, vec3d.z); } } else { if (!getNavigator().setPath(getNavigator().getPathToPos(target), speed)) { attemptTeleport(target.getX(), target.getY(), target.getZ()); } } } //searches for the nearest bed public BlockPos searchBed() { List nearbyBeds = Util.getNearbyBlocks(getPos(), world, BlockBed.class, 8, 8); List valid = new ArrayList<>(); for (BlockPos pos : nearbyBeds) { IBlockState state = world.getBlockState(pos); if (!(state.getValue(OCCUPIED)) && state.getValue(PART) != BlockBed.EnumPartType.HEAD) { valid.add(pos); } } return Util.getNearestPoint(getPos(), valid); } /** * Returns the orientation of the bed in degrees. */ @SideOnly(Side.CLIENT) public float getBedOrientationInDegrees() { BlockPos bedLocation = get(EntityVillagerMCA.BED_POS); IBlockState state = bedLocation == BlockPos.ORIGIN ? null : this.world.getBlockState(bedLocation); if (state != null && state.getBlock().isBed(state, world, bedLocation, this)) { EnumFacing enumfacing = state.getBlock().getBedDirection(state, world, bedLocation); switch (enumfacing) { case SOUTH: return 90.0F; case WEST: return 0.0F; case NORTH: return 270.0F; case EAST: return 180.0F; } } return 0.0F; } public boolean isSleeping() { return get(SLEEPING); } private void updateSleeping() { if (isSleeping()) { BlockPos bedLocation = get(EntityVillagerMCA.BED_POS); final IBlockState state = this.world.isBlockLoaded(bedLocation) ? this.world.getBlockState(bedLocation) : null; final boolean isBed = state != null && state.getBlock().isBed(state, this.world, bedLocation, this); if (isBed) { final EnumFacing enumfacing = state.getBlock() instanceof BlockHorizontal ? state.getValue(BlockHorizontal.FACING) : null; if (enumfacing != null) { float f1 = 0.5F + (float) enumfacing.getFrontOffsetX() * 0.4F; float f = 0.5F + (float) enumfacing.getFrontOffsetZ() * 0.4F; this.setRenderOffsetForSleep(enumfacing); this.setPosition((double) ((float) bedLocation.getX() + f1), (double) ((float) bedLocation.getY() + 0.6875F), (double) ((float) bedLocation.getZ() + f)); } else { this.setPosition((double) ((float) bedLocation.getX() + 0.5F), (double) ((float) bedLocation.getY() + 0.6875F), (double) ((float) bedLocation.getZ() + 0.5F)); } this.setSize(0.2F, 0.2F); this.motionX = 0.0D; this.motionY = 0.0D; this.motionZ = 0.0D; } else { set(EntityVillagerMCA.BED_POS, BlockPos.ORIGIN); stopSleeping(); } } else { this.setSize(0.6F, 1.8F); } } private void setRenderOffsetForSleep(EnumFacing bedDirection) { this.renderOffsetX = -1.0F * (float) bedDirection.getFrontOffsetX(); this.renderOffsetZ = -1.0F * (float) bedDirection.getFrontOffsetZ(); } public void startSleeping() { if (this.isRiding()) { this.dismountRidingEntity(); } set(SLEEPING, true); BlockPos bedLocation = get(EntityVillagerMCA.BED_POS); IBlockState blockstate = this.world.getBlockState(bedLocation); if (blockstate.getBlock() == Blocks.BED) { blockstate.getBlock().setBedOccupied(world, bedLocation, null, true); } } public void stopSleeping() { BlockPos bedLocation = get(EntityVillagerMCA.BED_POS); if (bedLocation != BlockPos.ORIGIN) { IBlockState blockstate = this.world.getBlockState(bedLocation); if (blockstate.getBlock().isBed(blockstate, world, bedLocation, this)) { blockstate.getBlock().setBedOccupied(world, bedLocation, null, false); BlockPos blockpos = blockstate.getBlock().getBedSpawnPosition(blockstate, world, bedLocation, null); if (blockpos == null) { blockpos = bedLocation.up(); } this.setPosition((double) ((float) blockpos.getX() + 0.5F), (double) ((float) blockpos.getY() + 0.1F), (double) ((float) blockpos.getZ() + 0.5F)); } } set(SLEEPING, false); } } ================================================ FILE: src/main/java/mca/entity/ai/AbstractEntityAIChore.java ================================================ package mca.entity.ai; import com.google.common.base.Optional; import mca.core.Constants; import mca.core.MCA; import mca.entity.EntityVillagerMCA; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.entity.player.EntityPlayer; public abstract class AbstractEntityAIChore extends EntityAIBase { protected final EntityVillagerMCA villager; public AbstractEntityAIChore(EntityVillagerMCA entityIn) { this.villager = entityIn; this.setMutexBits(4); } @Override public void updateTask() { super.updateTask(); if (!getAssigningPlayer().isPresent()) { MCA.getLog().warn("Force-stopped chore because assigning player was not present."); villager.stopChore(); } } Optional getAssigningPlayer() { EntityPlayer player = villager.world.getPlayerEntityByUUID(villager.get(EntityVillagerMCA.CHORE_ASSIGNING_PLAYER).or(Constants.ZERO_UUID)); return Optional.fromNullable(player); } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIAgeBaby.java ================================================ package mca.entity.ai; import com.google.common.base.Optional; import mca.core.MCA; import mca.entity.EntityVillagerMCA; import mca.entity.data.ParentData; import mca.enums.EnumGender; import net.minecraft.entity.ai.EntityAIBase; public class EntityAIAgeBaby extends EntityAIBase { private final EntityVillagerMCA villager; public EntityAIAgeBaby(EntityVillagerMCA entityIn) { this.villager = entityIn; this.setMutexBits(4); } public boolean shouldExecute() { return villager.get(EntityVillagerMCA.HAS_BABY); } public void updateTask() { if (villager.ticksExisted % 1200 != 0) return; villager.babyAge += 1; if (villager.babyAge < MCA.getConfig().babyGrowUpTime) return; EntityVillagerMCA child = new EntityVillagerMCA(villager.world, Optional.absent(), Optional.of(villager.get(EntityVillagerMCA.BABY_IS_MALE) ? EnumGender.MALE : EnumGender.FEMALE)); child.set(EntityVillagerMCA.PARENTS, ParentData.fromVillager(villager).toNBT()); child.setPosition(villager.posX, villager.posY, villager.posZ); villager.world.spawnEntity(child); villager.set(EntityVillagerMCA.HAS_BABY, false); } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIChopping.java ================================================ package mca.entity.ai; import mca.entity.EntityVillagerMCA; import mca.enums.EnumChore; import mca.util.Util; import net.minecraft.block.BlockLeaves; import net.minecraft.block.BlockLog; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.item.ItemAxe; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import java.util.ArrayList; import java.util.List; public class EntityAIChopping extends AbstractEntityAIChore { private int chopTicks; private BlockPos targetTree; public EntityAIChopping(EntityVillagerMCA entityIn) { super(entityIn); this.setMutexBits(1); } public boolean shouldExecute() { if (villager.getHealth() < villager.getMaxHealth()) { villager.stopChore(); } return EnumChore.byId(villager.get(EntityVillagerMCA.ACTIVE_CHORE)) == EnumChore.CHOP; } public void updateTask() { if (!villager.inventory.contains(ItemAxe.class)) { villager.say(getAssigningPlayer(), "chore.chopping.noaxe"); villager.stopChore(); } if (targetTree == null) { List nearbyLogs = Util.getNearbyBlocks(villager.getPos(), villager.world, BlockLog.class, 10, 5); List nearbyTrees = new ArrayList<>(); // valid "trees" are logs on the ground with leaves around them nearbyLogs.stream() .filter(log -> { IBlockState down = villager.world.getBlockState(log.down()); List leaves = Util.getNearbyBlocks(log, villager.world, BlockLeaves.class, 1, 5); return leaves.size() > 0 && (down.getBlock() == Blocks.GRASS || down.getBlock() == Blocks.DIRT); }) .forEach(nearbyTrees::add); targetTree = Util.getNearestPoint(villager.getPos(), nearbyTrees); return; } double distance = Math.sqrt(villager.getDistanceSq(targetTree)); if (distance >= 4.0D) villager.getNavigator().setPath(villager.getNavigator().getPathToPos(targetTree), 0.5D); else { IBlockState state = villager.world.getBlockState(targetTree); if (state.getBlock() instanceof BlockLog) { BlockLog log = (BlockLog) state.getBlock(); villager.swingArm(EnumHand.MAIN_HAND); chopTicks++; if (chopTicks >= 80) { chopTicks = 0; villager.inventory.addItem(new ItemStack(log, 1)); villager.getHeldItem(EnumHand.MAIN_HAND).damageItem(2, villager); if (villager.world.rand.nextFloat() >= 0.90) destroyTree(targetTree); } } else targetTree = null; } } private void destroyTree(BlockPos origin) { BlockPos pos = origin; while (villager.world.getBlockState(pos).getBlock() instanceof BlockLog) { villager.world.setBlockToAir(pos); pos = pos.add(0, 1, 0); } } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIDefendFromTarget.java ================================================ package mca.entity.ai; import net.minecraft.entity.EntityCreature; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.util.EnumHand; public class EntityAIDefendFromTarget extends EntityAIBase { private EntityCreature attacker; private int attackTick; public EntityAIDefendFromTarget(EntityCreature creature) { this.attacker = creature; this.setMutexBits(0); } public boolean shouldExecute() { this.attackTick--; EntityLivingBase entitylivingbase = this.attacker.getAttackTarget(); if (entitylivingbase == null) { return false; } else if (!entitylivingbase.isEntityAlive()) { return false; } else if (this.attackTick > 0) { return false; } else { return 4.0D >= this.attacker.getDistanceSq(entitylivingbase.posX, entitylivingbase.getEntityBoundingBox().minY, entitylivingbase.posZ); } } public boolean shouldContinueExecuting() { return false; } public void startExecuting() { this.attackTick = 10; EntityLivingBase entitylivingbase = this.attacker.getAttackTarget(); if (entitylivingbase != null) { this.attacker.getLookHelper().setLookPositionWithEntity(entitylivingbase, 30.0F, 30.0F); this.attacker.swingArm(EnumHand.MAIN_HAND); this.attacker.attackEntityAsMob(entitylivingbase); } } public void resetTask() { } public void updateTask() { } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIFishing.java ================================================ package mca.entity.ai; import mca.entity.EntityVillagerMCA; import mca.enums.EnumChore; import mca.util.Util; import net.minecraft.block.BlockStaticLiquid; import net.minecraft.init.Blocks; import net.minecraft.init.Items; import net.minecraft.item.ItemFishFood; import net.minecraft.item.ItemFishingRod; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import java.util.Comparator; import java.util.List; public class EntityAIFishing extends AbstractEntityAIChore { private BlockPos targetWater; private boolean hasCastRod; private int ticks; public EntityAIFishing(EntityVillagerMCA entityIn) { super(entityIn); this.setMutexBits(1); } public boolean shouldExecute() { if (villager.getHealth() < villager.getMaxHealth()) { villager.stopChore(); } return EnumChore.byId(villager.get(EntityVillagerMCA.ACTIVE_CHORE)) == EnumChore.FISH; } public void updateTask() { super.updateTask(); if (!villager.inventory.contains(ItemFishingRod.class)) { villager.say(getAssigningPlayer(), "chore.fishing.norod"); villager.stopChore(); return; } if (targetWater == null) { List nearbyStaticLiquid = Util.getNearbyBlocks(villager.getPos(), villager.world, BlockStaticLiquid.class, 12, 3); targetWater = nearbyStaticLiquid.stream() .filter((p) -> villager.world.getBlockState(p).getBlock() == Blocks.WATER) .min(Comparator.comparingDouble(villager::getDistanceSq)).orElse(null); } else if (villager.getDistanceSq(targetWater) > 5.0D) villager.getNavigator().setPath(villager.getNavigator().getPathToPos(targetWater), 0.8D); else if (villager.getDistanceSq(targetWater) < 5.0D) { villager.getNavigator().clearPath(); if (!hasCastRod) { villager.swingArm(EnumHand.MAIN_HAND); hasCastRod = true; } ticks++; if (ticks >= villager.world.rand.nextInt(200) + 200) { if (villager.world.rand.nextFloat() >= 0.35F) { int typesSize = ItemFishFood.FishType.values().length; ItemFishFood.FishType type = ItemFishFood.FishType.values()[villager.world.rand.nextInt(typesSize)]; ItemStack stack = new ItemStack(Items.FISH, 1, type.getMetadata()); villager.swingArm(EnumHand.MAIN_HAND); villager.inventory.addItem(stack); villager.getHeldItem(EnumHand.MAIN_HAND).damageItem(2, villager); } ticks = 0; } } } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIGoHangout.java ================================================ package mca.entity.ai; import mca.entity.EntityVillagerMCA; import mca.enums.EnumChore; public class EntityAIGoHangout extends AbstractEntityAIChore { private boolean atHangout = false; public EntityAIGoHangout(EntityVillagerMCA villagerIn) { super(villagerIn); this.setMutexBits(1); } public boolean shouldExecute() { if (villager.getHangout().getY() == 0) { return false; //no workplace } //no time, has to work if (EnumChore.byId(villager.get(EntityVillagerMCA.ACTIVE_CHORE)) != EnumChore.NONE) { return false; } long time = villager.world.getWorldTime() % 24000L; if (time < 9000 || time > 11000) { //spare time is over, villager will start going home atHangout = false; return false; } double validArea = 64.0D; //allows 8 blocks radius to stay double distance = villager.getDistanceSq(villager.getHangout()); if (!atHangout) { if (distance < 9.0) { //arrived at hangout atHangout = true; } else { //did not reach workplace for today -> shrink valid area so the villager gathers clearly at his workplace validArea = 4.0D; } } return distance > validArea; } public boolean shouldContinueExecuting() { return !villager.getNavigator().noPath(); } public void startExecuting() { villager.moveTowardsBlock(villager.getHangout()); } public void updateTask() { } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIGoWorkplace.java ================================================ package mca.entity.ai; import mca.entity.EntityVillagerMCA; public class EntityAIGoWorkplace extends AbstractEntityAIChore { private boolean atWork = false; public EntityAIGoWorkplace(EntityVillagerMCA villagerIn) { super(villagerIn); this.setMutexBits(1); } public boolean shouldExecute() { if (villager.getWorkplace().getY() == 0 || villager.world.isRaining()) { return false; //no workplace or it is raining } long time = villager.world.getWorldTime() % 24000L; if (time < 4000 || time > 7000) { //work is over, villager will start spreading atWork = false; return false; } double validArea = 576.0D; //allows 24 blocks radius to work double distance = villager.getDistanceSq(villager.getWorkplace()); if (!atWork) { if (distance < 9.0) { //arrived at workplace atWork = true; } else { //did not reach workplace for today -> shrink valid area so the villager gathers clearly at his workplace validArea = 4.0D; } } return distance > validArea; } public boolean shouldContinueExecuting() { return !villager.getNavigator().noPath(); } public void startExecuting() { //MCA.getLog().info(villager.getName() + " goes to work"); villager.moveTowardsBlock(villager.getWorkplace()); } public void updateTask() { } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIHarvesting.java ================================================ package mca.entity.ai; import mca.core.MCA; import mca.entity.EntityVillagerMCA; import mca.enums.EnumChore; import mca.util.Util; import net.minecraft.block.BlockCrops; import net.minecraft.block.properties.IProperty; import net.minecraft.block.state.IBlockState; import net.minecraft.item.*; import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import java.util.ArrayList; import java.util.List; public class EntityAIHarvesting extends AbstractEntityAIChore { private int blockWork = 0; private int lastCropScan = 0; public EntityAIHarvesting(EntityVillagerMCA villagerIn) { super(villagerIn); this.setMutexBits(1); } public boolean shouldExecute() { if (villager.getHealth() < villager.getMaxHealth()) { villager.stopChore(); } return EnumChore.byId(villager.get(EntityVillagerMCA.ACTIVE_CHORE)) == EnumChore.HARVEST && (blockWork - villager.ticksExisted) < 0; } public boolean shouldContinueExecuting() { return !villager.getNavigator().noPath(); } private BlockPos searchCrop(int rangeX, int rangeY) { List nearbyCrops = Util.getNearbyBlocks(villager.getPos(), villager.world, BlockCrops.class, rangeX, rangeY); List harvestable = new ArrayList<>(); for (BlockPos pos : nearbyCrops) { IBlockState state = villager.world.getBlockState(pos); BlockCrops crop = (BlockCrops) state.getBlock(); if (crop.isMaxAge(state)) { harvestable.add(pos); } } return Util.getNearestPoint(villager.getPos(), harvestable); } public void startExecuting() { if (!villager.inventory.contains(ItemHoe.class)) { villager.say(getAssigningPlayer(), "chore.harvesting.nohoe"); villager.stopChore(); } //search crop BlockPos target = searchCrop(16, 3); //no crop next to villager -> long range scan //limited to once a minute to reduce CPU usage if (target == null && villager.ticksExisted - lastCropScan > 1200) { //MCA.getLog().info(villager.getName() + " scans for crops"); lastCropScan = villager.ticksExisted; target = searchCrop(32, 16); } if (target == null) { if (villager.getWorkplace().getY() > 0 && villager.getDistanceSq(villager.getWorkplace()) > 256.0D) { //go to their workplace (if set and more than 16 blocks away) //MCA.getLog().info(villager.getName() + " goes to workplace"); villager.moveTowardsBlock(villager.getWorkplace()); } else { //failed (no crop on range), allows now other, lower priority tasks to interrupt //MCA.getLog().info(villager.getName() + " idles"); blockWork = villager.ticksExisted + 100 + villager.getRNG().nextInt(100); } } else { //harvest if next to it, else try to reach it double distanceTo = Math.sqrt(villager.getDistanceSq(target)); if (distanceTo >= 2.0D) { if (!villager.getNavigator().setPath(villager.getNavigator().getPathToPos(target), 0.5D)) { villager.attemptTeleport(target.getX(), target.getY(), target.getZ()); } } else { //harvest IBlockState state = villager.world.getBlockState(target); if (state.getBlock() instanceof BlockCrops) { BlockCrops crop = (BlockCrops) state.getBlock(); NonNullList drops = NonNullList.create(); crop.getDrops(drops, villager.world, target, state, 0); for (ItemStack stack : drops) { villager.inventory.addItem(stack); } villager.swingArm(EnumHand.MAIN_HAND); villager.getHeldItem(EnumHand.MAIN_HAND).damageItem(2, villager); try { IProperty property = (IProperty) crop.getBlockState().getProperty("age"); villager.world.setBlockState(target, state.withProperty(property, 0)); } catch (Exception e) { // age property may have some issues on certain mods, if it errors just set to air MCA.getLog().warn("Error resetting crop age at " + target.toString() + "! Setting to air."); villager.world.setBlockToAir(target); } } //wait before harvesting next crop ItemStack hoeStack = villager.inventory.getBestItemOfType(ItemHoe.class); float efficiency = hoeStack == ItemStack.EMPTY ? 0.0f : Item.ToolMaterial.valueOf(((ItemHoe) hoeStack.getItem()).getMaterialName()).getEfficiency(); blockWork = villager.ticksExisted + (int) Math.max(2.0f, 60.0f - efficiency * 5.0f); } } } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIHunting.java ================================================ package mca.entity.ai; import mca.entity.EntityVillagerMCA; import mca.enums.EnumChore; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.passive.EntityAnimal; import net.minecraft.entity.passive.EntityTameable; import net.minecraft.item.ItemSword; import net.minecraft.util.DamageSource; import net.minecraft.util.EnumHand; import java.util.Comparator; import java.util.Optional; public class EntityAIHunting extends AbstractEntityAIChore { private int ticks = 0; private int nextAction = 0; private EntityAnimal target = null; public EntityAIHunting(EntityVillagerMCA entityIn) { super(entityIn); this.setMutexBits(1); } public boolean shouldExecute() { if (villager.getHealth() < villager.getMaxHealth()) { villager.stopChore(); } return EnumChore.byId(villager.get(EntityVillagerMCA.ACTIVE_CHORE)) == EnumChore.HUNT; } public void updateTask() { super.updateTask(); if (!villager.inventory.contains(ItemSword.class)) { villager.say(getAssigningPlayer(), "chore.hunting.nosword"); villager.stopChore(); } if (target == null) { ticks++; if (ticks >= nextAction) { ticks = 0; if (villager.world.rand.nextFloat() >= 0.0D) { Optional animal = villager.world.getEntitiesWithinAABB(EntityAnimal.class, villager.getEntityBoundingBox().grow(15.0D, 3.0D, 15.0D)).stream() .filter((a) -> !(a instanceof EntityTameable)) .min(Comparator.comparingDouble(villager::getDistance)); if (animal.isPresent()) { target = animal.get(); target.getNavigator().setPath(target.getNavigator().getPathToEntityLiving(villager), 1.0F); } } nextAction = 300; } } else { boolean pathSuccess = villager.getNavigator().setPath(villager.getNavigator().getPathToEntityLiving(target), 0.6F); if (!pathSuccess || target.isDead) { // search for EntityItems around the target and grab them villager.world.loadedEntityList.stream() .filter((e) -> e instanceof EntityItem && e.getDistance(target) <= 5.0D) .forEach((item) -> { villager.inventory.addItem(((EntityItem) item).getItem()); item.setDead(); }); target = null; } else if (villager.getDistance(target) <= 3.5F) { villager.getNavigator().setPath(villager.getNavigator().getPathToEntityLiving(target), 1.0F); villager.swingArm(EnumHand.MAIN_HAND); target.attackEntityFrom(DamageSource.causeMobDamage(villager), 6.0F); villager.getHeldItem(EnumHand.MAIN_HAND).damageItem(2, villager); } } } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIMoveState.java ================================================ package mca.entity.ai; import mca.core.Constants; import mca.entity.EntityVillagerMCA; import mca.enums.EnumMoveState; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.pathfinding.PathNavigate; public class EntityAIMoveState extends EntityAIBase { private final EntityVillagerMCA villager; public EntityAIMoveState(EntityVillagerMCA entityIn) { this.villager = entityIn; this.setMutexBits(1); } public boolean shouldExecute() { return !villager.playerToFollowUUID.equals(Constants.ZERO_UUID) || EnumMoveState.byId(villager.get(EntityVillagerMCA.MOVE_STATE)) == EnumMoveState.STAY; } public void updateTask() { PathNavigate nav = villager.getNavigator(); EntityPlayer playerToFollow = villager.world.getPlayerEntityByUUID(villager.playerToFollowUUID); switch (EnumMoveState.byId(villager.get(EntityVillagerMCA.MOVE_STATE))) { case FOLLOW: double distance = playerToFollow != null ? villager.getDistance(playerToFollow) : -1.0D; if (playerToFollow == null) { villager.set(EntityVillagerMCA.MOVE_STATE, EnumMoveState.MOVE.getId()); break; } else if (distance >= 3.0D && distance <= 10.0D) { nav.setPath(nav.getPathToEntityLiving(playerToFollow), villager.isRiding() ? 1.7D : 0.8D); } else if (distance > 10.0D) { villager.attemptTeleport(playerToFollow.posX, playerToFollow.posY, playerToFollow.posZ); } else { // close enough to avoid crowding the player nav.clearPath(); } break; case STAY: nav.clearPath(); break; } } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIProcreate.java ================================================ package mca.entity.ai; import lombok.RequiredArgsConstructor; import mca.core.Constants; import mca.core.MCA; import mca.core.minecraft.ItemsMCA; import mca.entity.EntityVillagerMCA; import mca.entity.data.PlayerSaveData; import net.minecraft.entity.ai.EntityAIBase; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.init.SoundEvents; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumParticleTypes; import net.minecraft.util.SoundCategory; @RequiredArgsConstructor public class EntityAIProcreate extends EntityAIBase { private final EntityVillagerMCA villager; public int procreateTimer; @Override public boolean shouldExecute() { return villager.get(EntityVillagerMCA.IS_PROCREATING); } @Override public void updateTask() { if (procreateTimer % 5 == 0) villager.spawnParticles(EnumParticleTypes.HEART); if (--procreateTimer <= 0) { villager.set(EntityVillagerMCA.IS_PROCREATING, false); EntityPlayer spousePlayer = villager.world.getPlayerEntityByUUID(villager.get(EntityVillagerMCA.SPOUSE_UUID).or(Constants.ZERO_UUID)); if (spousePlayer != null) { villager.world.playSound(null, villager.posX, villager.posY, villager.posZ, SoundEvents.ENTITY_CHICKEN_EGG, SoundCategory.NEUTRAL, 1.0F, 1.0F); spousePlayer.inventory.addItemStackToInventory(new ItemStack(villager.getRNG().nextBoolean() ? ItemsMCA.BABY_BOY : ItemsMCA.BABY_GIRL)); PlayerSaveData.get(spousePlayer).setBabyPresent(true); if (villager.getRNG().nextFloat() < MCA.getConfig().chanceToHaveTwins / 100) spousePlayer.inventory.addItemStackToInventory(new ItemStack(villager.getRNG().nextBoolean() ? ItemsMCA.BABY_BOY : ItemsMCA.BABY_GIRL)); } } } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAIProspecting.java ================================================ package mca.entity.ai; import mca.entity.EntityVillagerMCA; import mca.enums.EnumChore; import mca.util.Util; import net.minecraft.block.Block; import net.minecraft.block.BlockOre; import net.minecraft.item.Item; import net.minecraft.item.ItemPickaxe; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; public class EntityAIProspecting extends AbstractEntityAIChore { private int ticks; public EntityAIProspecting(EntityVillagerMCA entityIn) { super(entityIn); this.setMutexBits(4); } public boolean shouldExecute() { if (villager.getHealth() < villager.getMaxHealth()) { villager.stopChore(); } return EnumChore.byId(villager.get(EntityVillagerMCA.ACTIVE_CHORE)) == EnumChore.PROSPECT; } public void updateTask() { super.updateTask(); ItemStack pickStack = villager.inventory.getBestItemOfType(ItemPickaxe.class); if (pickStack == ItemStack.EMPTY) { villager.say(getAssigningPlayer(), "chore.mining.nopick"); villager.stopChore(); return; } float efficiency = Item.ToolMaterial.valueOf(((ItemPickaxe) pickStack.getItem()).getToolMaterialName()).getEfficiency(); float notifyRate = Math.max(600 - efficiency * 50, 100); if (ticks >= notifyRate) { BlockPos closestOre = Util.getNearestPoint(villager.getPos(), Util.getNearbyBlocks(villager.getPos(), villager.world, BlockOre.class, 4, 3)); if (closestOre != null) { Block block = villager.world.getBlockState(closestOre).getBlock(); villager.say(getAssigningPlayer(), "chore.mining.orenotify", block.getLocalizedName()); pickStack.damageItem(2, villager); } ticks = 0; return; } ticks++; } } ================================================ FILE: src/main/java/mca/entity/ai/EntityAISleeping.java ================================================ package mca.entity.ai; import mca.core.minecraft.ProfessionsMCA; import mca.entity.EntityVillagerMCA; import net.minecraft.util.math.BlockPos; public class EntityAISleeping extends AbstractEntityAIChore { private int failed = 0; public EntityAISleeping(EntityVillagerMCA villagerIn) { super(villagerIn); this.setMutexBits(1); } public boolean shouldExecute() { //let the avoid tasks work if (villager.getHealth() < villager.getMaxHealth()) { return false; } if (villager.ticksExisted - failed < 1200) { //wake up if still sleeping if (villager.isSleeping()) { villager.stopSleeping(); } return false; } long time = villager.world.getWorldTime() % 24000L; if (villager.get(EntityVillagerMCA.BED_POS) == BlockPos.ORIGIN && time < 16000) { //at tick 18000 villager without bed are allowed to automatically choose one //wake up if still sleeping if (villager.isSleeping()) { villager.stopSleeping(); } return false; } //if guards detect enemies they won't sleep if (villager.getProfessionForge() == ProfessionsMCA.guard && villager.getAttackTarget() != null) { //wake up, this is a emergency! if (villager.isSleeping()) { villager.stopSleeping(); } return false; } if (time > (villager.getProfessionForge() == ProfessionsMCA.guard ? 14000 : 12000) && time < 23000) { return true; } else { //wake up if still sleeping if (villager.isSleeping()) { villager.stopSleeping(); } return false; } } public boolean shouldContinueExecuting() { return shouldExecute() && (!villager.getNavigator().noPath() || villager.isSleeping()); } public void startExecuting() { if (villager.get(EntityVillagerMCA.BED_POS) == BlockPos.ORIGIN || villager.getDistanceSq(villager.get(EntityVillagerMCA.BED_POS)) < 4.0) { //search for the nearest bed, might be a different than before BlockPos pos = villager.searchBed(); if (pos == null) { //no bed found, let's forget about the remembered bed if (villager.get(EntityVillagerMCA.BED_POS) != BlockPos.ORIGIN) { //TODO: notify the player? //MCA.getLog().info(villager.getName() + " lost the bed"); villager.set(EntityVillagerMCA.BED_POS, BlockPos.ORIGIN); } else { //MCA.getLog().info(villager.getName() + " has no bed"); } failed = villager.ticksExisted; } else { //MCA.getLog().info(villager.getName() + " sleeps now"); villager.set(EntityVillagerMCA.BED_POS, pos); villager.startSleeping(); } } else { //MCA.getLog().info(villager.getName() + " is going to bed"); villager.moveTowardsBlock(villager.get(EntityVillagerMCA.BED_POS), 0.75); } } public void resetTask() { if (villager.isSleeping()) { //MCA.getLog().info(villager.getName() + " wakes up"); villager.stopSleeping(); } } public void updateTask() { if (villager.isSleeping()) { villager.setRotationYawHead(0.0f); villager.rotationYaw = 0.0f; } } } ================================================ FILE: src/main/java/mca/entity/data/ParentData.java ================================================ package mca.entity.data; import lombok.Getter; import mca.core.Constants; import mca.entity.EntityVillagerMCA; import net.minecraft.entity.Entity; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import java.util.UUID; import static mca.entity.EntityVillagerMCA.*; @Getter public class ParentData { private UUID parent1UUID = Constants.ZERO_UUID; private UUID parent2UUID = Constants.ZERO_UUID; private String parent1Name = ""; private String parent2Name = ""; public static ParentData fromNBT(NBTTagCompound nbt) { ParentData data = new ParentData(); data.parent1UUID = nbt.getUniqueId("parent1UUID"); data.parent2UUID = nbt.getUniqueId("parent2UUID"); data.parent1Name = nbt.getString("parent1Name"); data.parent2Name = nbt.getString("parent2Name"); return data; } public static ParentData create(UUID parent1UUID, UUID parent2UUID, String parent1Name, String parent2Name) { ParentData data = new ParentData(); data.parent1UUID = parent1UUID; data.parent2UUID = parent2UUID; data.parent1Name = parent1Name; data.parent2Name = parent2Name; return data; } public static ParentData fromVillager(EntityVillagerMCA villager) { ParentData data = new ParentData(); data.parent1Name = villager.get(VILLAGER_NAME); data.parent1UUID = villager.getUniqueID(); data.parent2Name = villager.get(SPOUSE_NAME); data.parent2UUID = villager.get(SPOUSE_UUID).or(Constants.ZERO_UUID); return data; } public NBTTagCompound toNBT() { NBTTagCompound nbt = new NBTTagCompound(); nbt.setUniqueId("parent1UUID", parent1UUID); nbt.setUniqueId("parent2UUID", parent2UUID); nbt.setString("parent1Name", parent1Name); nbt.setString("parent2Name", parent2Name); return nbt; } public ParentData setParents(UUID parent1UUID, String parent1Name, UUID parent2UUID, String parent2Name) { this.parent1UUID = parent1UUID; this.parent2UUID = parent2UUID; this.parent1Name = parent1Name; this.parent2Name = parent2Name; return this; } public Entity getParentEntity(World world, UUID uuid) { return world.loadedEntityList.stream().filter(e -> e.getUniqueID().equals(uuid)).findFirst().orElse(null); // TODO: This should definitely be changed to an optional } public Entity[] getParentEntities(World world) { return new Entity[]{ getParentEntity(world, getParent1UUID()), getParentEntity(world, getParent2UUID()) }; } } ================================================ FILE: src/main/java/mca/entity/data/PlayerHistory.java ================================================ package mca.entity.data; import lombok.Getter; import mca.core.Constants; import mca.entity.EntityVillagerMCA; import mca.enums.EnumDialogueType; import net.minecraft.nbt.NBTTagCompound; import java.util.UUID; public class PlayerHistory { @Getter private int hearts; @Getter private int interactionFatigue; @Getter private boolean giftPresent; @Getter private int greetTimer; @Getter private EnumDialogueType dialogueType; @Getter private UUID playerUUID; private EntityVillagerMCA villager; private PlayerHistory() { hearts = 0; interactionFatigue = 0; giftPresent = false; greetTimer = 0; playerUUID = Constants.ZERO_UUID; dialogueType = EnumDialogueType.ADULT; } public static PlayerHistory getNew(EntityVillagerMCA villager, UUID uuid) { PlayerHistory history = new PlayerHistory(); history.villager = villager; history.playerUUID = uuid; if (villager.isChild()) { history.setDialogueType(EnumDialogueType.CHILD); } else { history.setDialogueType(EnumDialogueType.ADULT); } return history; } public static PlayerHistory fromNBT(EntityVillagerMCA villager, UUID uuid, NBTTagCompound nbt) { PlayerHistory history = new PlayerHistory(); history.villager = villager; history.playerUUID = uuid; history.hearts = nbt.getInteger("hearts"); history.interactionFatigue = nbt.getInteger("interactionFatigue"); history.giftPresent = nbt.getBoolean("giftPresent"); history.greetTimer = nbt.getInteger("greetTimer"); history.dialogueType = EnumDialogueType.byValue(nbt.getString("dialogueType")); return history; } public NBTTagCompound toNBT() { NBTTagCompound nbt = new NBTTagCompound(); nbt.setInteger("hearts", hearts); nbt.setInteger("interactionFatigue", interactionFatigue); nbt.setBoolean("giftPresent", giftPresent); nbt.setInteger("greetTimer", greetTimer); nbt.setString("dialogueType", dialogueType.getId()); return nbt; } public void setHearts(int value) { hearts = value; villager.updatePlayerHistoryMap(this); } public void changeHearts(int value) { hearts += value; villager.updatePlayerHistoryMap(this); } public void changeInteractionFatigue(int value) { interactionFatigue += value; villager.updatePlayerHistoryMap(this); } public void update() { // every 5 minutes reduce interaction fatigues if (villager.ticksExisted % 6000 == 0) changeInteractionFatigue(-1); } public void setDialogueType(EnumDialogueType type) { this.dialogueType = type; villager.updatePlayerHistoryMap(this); } } ================================================ FILE: src/main/java/mca/entity/data/PlayerSaveData.java ================================================ package mca.entity.data; import lombok.Getter; import mca.core.Constants; import mca.core.MCA; import mca.enums.EnumMarriageState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.text.TextComponentString; import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.Arrays; import java.util.List; import java.util.UUID; import java.util.stream.Collectors; @Getter public class PlayerSaveData extends WorldSavedData { private static final String PREFIX = "MCA-Player-V1-"; private UUID spouseUUID = Constants.ZERO_UUID; private EnumMarriageState marriageState = EnumMarriageState.NOT_MARRIED; private String spouseName = ""; private boolean babyPresent = false; public PlayerSaveData(String id) { super(id); } public static PlayerSaveData get(EntityPlayer player) { String dataId = PREFIX + player.getUniqueID().toString(); PlayerSaveData data = (PlayerSaveData) player.world.loadData(PlayerSaveData.class, dataId); if (data == null) { data = new PlayerSaveData(dataId); player.world.setData(dataId, data); } return data; } public static PlayerSaveData getExisting(World world, UUID uuid) { return (PlayerSaveData) world.loadData(PlayerSaveData.class, PREFIX + uuid.toString()); } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { nbt.setUniqueId("spouseUUID", spouseUUID); nbt.setInteger("marriageState", marriageState.getId()); nbt.setString("spouseName", spouseName); nbt.setBoolean("babyPresent", babyPresent); return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { spouseUUID = nbt.getUniqueId("spouseUUID"); marriageState = EnumMarriageState.byId(nbt.getInteger("marriageState")); spouseName = nbt.getString("spouseName"); babyPresent = nbt.getBoolean("babyPresent"); } public boolean isMarriedOrEngaged() { return marriageState != EnumMarriageState.NOT_MARRIED; } public void marry(UUID uuid, String name) { spouseUUID = uuid; marriageState = EnumMarriageState.MARRIED; spouseName = name; markDirty(); } public void endMarriage() { spouseUUID = Constants.ZERO_UUID; spouseName = ""; marriageState = EnumMarriageState.NOT_MARRIED; markDirty(); } public void setBabyPresent(boolean value) { this.babyPresent = value; markDirty(); } public void reset() { endMarriage(); setBabyPresent(false); markDirty(); } public List getDataFields() { return Arrays.stream(this.getClass().getDeclaredFields()).filter(f -> !Modifier.isFinal(f.getModifiers())).collect(Collectors.toList()); } public void dump(EntityPlayer player) { for (Field f : getDataFields()) { try { player.sendMessage(new TextComponentString(f.getName() + " = " + f.get(this).toString())); } catch (Exception e) { MCA.getLog().error("Error dumping player data!"); MCA.getLog().error(e); } } } } ================================================ FILE: src/main/java/mca/entity/data/SavedVillagers.java ================================================ package mca.entity.data; import mca.entity.EntityVillagerMCA; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.world.World; import net.minecraft.world.storage.WorldSavedData; import java.util.HashMap; import java.util.Map; import java.util.UUID; /** * SavedVillagers handles saving dead villagers to the world which allows them to be restored later. */ public class SavedVillagers extends WorldSavedData { private static final String DATA_ID = "MCA-Villagers-V1"; private Map villagerData = new HashMap<>(); public SavedVillagers(String id) { super(id); } public static SavedVillagers get(World world) { SavedVillagers data = (SavedVillagers) world.loadData(SavedVillagers.class, DATA_ID); if (data == null) { data = new SavedVillagers(DATA_ID); world.setData(DATA_ID, data); } return data; } public void save(EntityVillagerMCA villager) { villagerData.put(villager.getUniqueID().toString(), villager.writeToNBT(new NBTTagCompound())); markDirty(); } public void remove(UUID uuid) { villagerData.remove(uuid.toString()); markDirty(); } public Map getMap() { return villagerData; } public NBTTagCompound loadByUUID(UUID uuid) { return villagerData.get(uuid.toString()); } @Override public NBTTagCompound writeToNBT(NBTTagCompound nbt) { villagerData.forEach(nbt::setTag); return nbt; } @Override public void readFromNBT(NBTTagCompound nbt) { nbt.getKeySet().forEach((k) -> villagerData.put(k, nbt.getCompoundTag(k))); } } ================================================ FILE: src/main/java/mca/entity/inventory/InventoryMCA.java ================================================ package mca.entity.inventory; import mca.entity.EntityVillagerMCA; import net.minecraft.inventory.EntityEquipmentSlot; import net.minecraft.inventory.InventoryBasic; import net.minecraft.item.Item; import net.minecraft.item.ItemArmor; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import javax.annotation.Nullable; import java.util.ArrayList; import java.util.List; public class InventoryMCA extends InventoryBasic { private EntityVillagerMCA villager; public InventoryMCA(EntityVillagerMCA villager) { super("Villager Inventory", true, 27); this.villager = villager; } public int getFirstSlotContainingItem(Item item) { for (int i = 0; i < this.getSizeInventory(); i++) { ItemStack stack = this.getStackInSlot(i); if (stack.getItem() != item) continue; return i; } return -1; } public boolean contains(Class clazz) { for (int i = 0; i < this.getSizeInventory(); ++i) { final ItemStack stack = this.getStackInSlot(i); final Item item = stack.getItem(); if (item.getClass() == clazz) return true; } return false; } /** * Gets the best quality (max damage) item of the specified type that is in the inventory. * * @param type The class of item that will be returned. * @return The item stack containing the item of the specified type with the highest max damage. */ public ItemStack getBestItemOfType(@Nullable Class type) { if (type == null) return ItemStack.EMPTY; else return getStackInSlot(getBestItemOfTypeSlot(type)); } public ItemStack getBestArmorOfType(EntityEquipmentSlot slot) { ItemStack returnStack = ItemStack.EMPTY; List armors = new ArrayList(); for (int i = 0; i < this.getSizeInventory(); ++i) { ItemStack stack = this.getStackInSlot(i); if (stack.getItem() instanceof ItemArmor) { ItemArmor armor = (ItemArmor) stack.getItem(); if (armor.armorType == slot) armors.add(stack); } } int highestMaxDamage = 0; for (ItemStack stack : armors) { if (stack.getMaxDamage() > highestMaxDamage) { returnStack = stack; highestMaxDamage = stack.getMaxDamage(); } } return returnStack; } public int getBestItemOfTypeSlot(Class type) { int highestMaxDamage = 0; int best = -1; for (int i = 0; i < this.getSizeInventory(); ++i) { ItemStack stackInInventory = this.getStackInSlot(i); final String itemClassName = stackInInventory.getItem().getClass().getName(); if (itemClassName.equals(type.getName()) && highestMaxDamage < stackInInventory.getMaxDamage()) { highestMaxDamage = stackInInventory.getMaxDamage(); best = i; } } return best; } public void dropAllItems() { for (int i = 0; i < this.getSizeInventory(); i++) { ItemStack stack = this.getStackInSlot(i); villager.entityDropItem(stack, 1.0F); } } public void readInventoryFromNBT(NBTTagList tagList) { for (int i = 0; i < this.getSizeInventory(); ++i) { this.setInventorySlotContents(i, ItemStack.EMPTY); } for (int i = 0; i < tagList.tagCount(); ++i) { NBTTagCompound nbt = tagList.getCompoundTagAt(i); int slot = nbt.getByte("Slot") & 255; if (slot < this.getSizeInventory()) { this.setInventorySlotContents(slot, new ItemStack(nbt)); } } } public NBTTagList writeInventoryToNBT() { NBTTagList tagList = new NBTTagList(); for (int i = 0; i < this.getSizeInventory(); ++i) { ItemStack itemstack = this.getStackInSlot(i); if (itemstack != ItemStack.EMPTY) { NBTTagCompound nbt = new NBTTagCompound(); nbt.setByte("Slot", (byte) i); itemstack.writeToNBT(nbt); tagList.appendTag(nbt); } } return tagList; } } ================================================ FILE: src/main/java/mca/enums/EnumAgeState.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import mca.core.MCA; import java.util.Arrays; import java.util.Optional; @AllArgsConstructor @Getter public enum EnumAgeState { UNASSIGNED(-1, 0.8f, 2.0f, 1.5f), BABY(0, 0.3f, 0.5f, 0.4f), TODDLER(1, 0.3f, 0.6f, 0.5f), CHILD(2, 0.5f, 1.1f, 1f), TEEN(3, 0.6f, 1.6f, 1.35f), ADULT(4, 0.8f, 2f, 1.5f); int id; float width; float height; float scaleForAge; public static EnumAgeState byId(int id) { Optional state = Arrays.stream(values()).filter((e) -> e.id == id).findFirst(); return state.orElse(UNASSIGNED); } public static EnumAgeState byCurrentAge(int startingAge, int growingAge) { int step = startingAge / 4; if (growingAge >= step) return EnumAgeState.TEEN; else if (growingAge >= step * 2) return EnumAgeState.CHILD; else if (growingAge >= step * 3 && growingAge < step * 2) return EnumAgeState.TODDLER; else if (growingAge >= step * 4 && growingAge < step * 3) return EnumAgeState.BABY; return EnumAgeState.ADULT; } public String localizedName() { return MCA.getLocalizer().localize("enum.agestate." + name().toLowerCase()); } } ================================================ FILE: src/main/java/mca/enums/EnumChore.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import mca.core.MCA; import net.minecraft.item.*; import java.util.Arrays; import java.util.Optional; @AllArgsConstructor public enum EnumChore { NONE(0, "none", null), PROSPECT(1, "gui.label.prospecting", ItemPickaxe.class), HARVEST(2, "gui.label.harvesting", ItemHoe.class), CHOP(3, "gui.label.chopping", ItemAxe.class), HUNT(4, "gui.label.hunting", ItemSword.class), FISH(5, "gui.label.fishing", ItemFishingRod.class); @Getter int id; String friendlyName; @Getter Class toolType; public static EnumChore byId(int id) { Optional state = Arrays.stream(values()).filter((e) -> e.id == id).findFirst(); return state.orElse(NONE); } public String getFriendlyName() { return MCA.getLocalizer().localize(this.friendlyName); } } ================================================ FILE: src/main/java/mca/enums/EnumConstraint.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Optional; @AllArgsConstructor @Getter public enum EnumConstraint { FAMILY("family"), NOT_FAMILY("notfamily"), ADULTS("adults"), SPOUSE("spouse"), NOT_SPOUSE("notspouse"), HIDE_ON_FAIL("hideonfail"); String id; public static List fromStringList(String constraints) { List list = new ArrayList<>(); if (constraints != null && !constraints.isEmpty()) { String[] splitConstraints = constraints.split("\\|"); for (String s : splitConstraints) { EnumConstraint constraint = byValue(s); if (s != null) { list.add(constraint); } } } return list; } public static EnumConstraint byValue(String value) { Optional state = Arrays.stream(values()).filter((e) -> e.id.equals(value)).findFirst(); return state.orElse(null); } } ================================================ FILE: src/main/java/mca/enums/EnumDialogueType.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import java.util.Arrays; @AllArgsConstructor @Getter public enum EnumDialogueType { CHILDP("childp"), CHILD("child"), ADULT("adult"), SPOUSE("spouse"); String id; public static EnumDialogueType byValue(String value) { return Arrays.stream(values()).filter(c -> c.getId().equals(value)).findFirst().orElse(null); } } ================================================ FILE: src/main/java/mca/enums/EnumGender.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import java.util.Arrays; import java.util.Optional; import java.util.Random; @AllArgsConstructor @Getter public enum EnumGender { UNASSIGNED(0, "unassigned"), MALE(1, "male"), FEMALE(2, "female"); int id; String strName; public static EnumGender byId(int id) { Optional gender = Arrays.stream(values()).filter((e) -> e.id == id).findFirst(); return gender.orElse(UNASSIGNED); } public static EnumGender getRandom() { return new Random().nextBoolean() ? MALE : FEMALE; } public static EnumGender byName(String name) { Optional gender = Arrays.stream(values()).filter((e) -> e.getStrName().equals(name)).findFirst(); return gender.orElse(UNASSIGNED); } } ================================================ FILE: src/main/java/mca/enums/EnumMarriageState.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import java.util.Arrays; import java.util.Optional; @AllArgsConstructor @Getter public enum EnumMarriageState { NOT_MARRIED(0), ENGAGED(1), MARRIED(2); int id; public static EnumMarriageState byId(int id) { Optional state = Arrays.stream(values()).filter((e) -> e.id == id).findFirst(); return state.orElse(NOT_MARRIED); } } ================================================ FILE: src/main/java/mca/enums/EnumMoveState.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import mca.core.MCA; import java.util.Arrays; @AllArgsConstructor public enum EnumMoveState { MOVE(0, ""), STAY(1, "gui.label.staying"), FOLLOW(2, "gui.label.following"); @Getter int id; String friendlyName; public static EnumMoveState byId(int id) { return Arrays.stream(values()).filter(s -> s.id == id).findFirst().orElse(MOVE); } public String getFriendlyName() { return MCA.getLocalizer().localize(friendlyName); } } ================================================ FILE: src/main/java/mca/enums/EnumReaperAttackState.java ================================================ package mca.enums; import lombok.AllArgsConstructor; import lombok.Getter; import java.util.Arrays; @AllArgsConstructor @Getter public enum EnumReaperAttackState { IDLE(0), PRE(1), POST(2), REST(3), BLOCK(4); int id; public static EnumReaperAttackState fromId(int id) { return Arrays.stream(values()).filter(s -> s.id == id).findFirst().orElse(IDLE); } } ================================================ FILE: src/main/java/mca/items/ItemBaby.java ================================================ package mca.items; import com.google.common.base.Optional; import mca.api.API; import mca.core.Constants; import mca.core.Localizer; import mca.core.MCA; import mca.core.minecraft.ProfessionsMCA; import mca.entity.EntityVillagerMCA; import mca.entity.data.ParentData; import mca.entity.data.PlayerSaveData; import mca.enums.EnumAgeState; import mca.enums.EnumDialogueType; import mca.enums.EnumGender; import net.minecraft.client.Minecraft; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.Entity; import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraftforge.fml.common.FMLCommonHandler; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import java.util.List; public class ItemBaby extends Item { private boolean isMale; public ItemBaby(boolean isMale) { this.isMale = isMale; this.setMaxStackSize(1); } @Override public void onUpdate(ItemStack itemStack, World world, Entity entity, int unknownInt, boolean unknownBoolean) { super.onUpdate(itemStack, world, entity, unknownInt, unknownBoolean); if (!world.isRemote) { if (!itemStack.hasTagCompound()) { NBTTagCompound compound = new NBTTagCompound(); compound.setString("name", ""); compound.setInteger("age", 0); compound.setUniqueId("ownerUUID", entity.getUniqueID()); compound.setString("ownerName", entity.getName()); compound.setBoolean("isInfected", false); itemStack.setTagCompound(compound); } else { updateBabyGrowth(itemStack); } } } @Override public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { BlockPos pos = player.getPosition(); ItemStack stack = player.getHeldItem(hand); int posX = pos.getX(); int posY = pos.getY() + 1; int posZ = pos.getZ(); // Right-clicking an unnamed baby allows you to name it if (world.isRemote && getBabyName(stack).equals("")) player.openGui(MCA.getInstance(), Constants.GUI_ID_NAMEBABY, player.world, player.getEntityId(), 0, 0); if (!world.isRemote) { if (isReadyToGrowUp(stack) && !getBabyName(stack).equals("")) { // Name is good and we're ready to grow EntityVillagerMCA child = new EntityVillagerMCA(world, Optional.of(ProfessionsMCA.child), Optional.of(this.isMale ? EnumGender.MALE : EnumGender.FEMALE)); child.set(EntityVillagerMCA.VILLAGER_NAME, getBabyName(stack)); child.set(EntityVillagerMCA.TEXTURE, API.getRandomSkin(child)); // allow for special-case skins to be applied with the proper name attached to the child at this point child.set(EntityVillagerMCA.AGE_STATE, EnumAgeState.BABY.getId()); child.setStartingAge(MCA.getConfig().childGrowUpTime * 60 * 20 * -1); child.setScaleForAge(true); child.setPosition(posX, posY, posZ); world.spawnEntity(child); PlayerSaveData playerData = PlayerSaveData.get(player); child.set(EntityVillagerMCA.PARENTS, ParentData.create(player.getUniqueID(), playerData.getSpouseUUID(), player.getName(), playerData.getSpouseName()).toNBT()); player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); playerData.setBabyPresent(false); // set proper dialogue type child.getPlayerHistoryFor(player.getUniqueID()).setDialogueType(EnumDialogueType.CHILDP); } } return super.onItemRightClick(world, player, hand); } private String getBabyName(ItemStack stack) { return stack.getTagCompound().getString("name"); } @Override public boolean onEntityItemUpdate(EntityItem entityItem) { if (!entityItem.world.isRemote) { updateBabyGrowth(entityItem.getItem()); } return super.onEntityItemUpdate(entityItem); } @SideOnly(Side.CLIENT) @Override public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { super.addInformation(stack, worldIn, tooltip, flagIn); Localizer loc = MCA.getLocalizer(); if (stack.hasTagCompound()) { EntityPlayer player = Minecraft.getMinecraft().player; NBTTagCompound nbt = stack.getTagCompound(); String textColor = ((ItemBaby) stack.getItem()).isMale ? Constants.Color.AQUA : Constants.Color.LIGHTPURPLE; int ageInMinutes = nbt.getInteger("age"); String ownerName = nbt.getUniqueId("ownerUUID").equals(player.getUniqueID()) ? MCA.getLocalizer().localize("label.you") : nbt.getString("ownerName"); if (getBabyName(stack).equals("")) tooltip.add(textColor + loc.localize("gui.label.name") + " " + Constants.Format.RESET + MCA.getLocalizer().localize("label.unnamed")); else tooltip.add(textColor + loc.localize("gui.label.name") + " " + Constants.Format.RESET + nbt.getString("name")); tooltip.add(textColor + loc.localize("gui.label.age") + " " + Constants.Format.RESET + ageInMinutes + " " + (ageInMinutes == 1 ? loc.localize("gui.label.minute") : loc.localize("gui.label.minutes"))); tooltip.add(textColor + loc.localize("gui.label.parent") + " " + Constants.Format.RESET + ownerName); if (nbt.getBoolean("isInfected")) tooltip.add(Constants.Color.GREEN + loc.localize("gui.label.infected")); if (isReadyToGrowUp(stack)) tooltip.add(Constants.Color.GREEN + loc.localize("gui.label.readytogrow")); if (nbt.getString("name").equals(loc.localize("gui.label.unnamed"))) tooltip.add(Constants.Color.YELLOW + loc.localize("gui.label.rightclicktoname")); } } private void updateBabyGrowth(ItemStack itemStack) { if (itemStack.hasTagCompound() && FMLCommonHandler.instance().getMinecraftServerInstance().getTickCounter() % 1200 == 0) { int age = itemStack.getTagCompound().getInteger("age"); age++; itemStack.getTagCompound().setInteger("age", age); } } private boolean isReadyToGrowUp(ItemStack itemStack) { return itemStack.getTagCompound().getInteger("age") >= MCA.getConfig().babyGrowUpTime; } public EnumGender getGender() { return isMale ? EnumGender.MALE : EnumGender.FEMALE; } } ================================================ FILE: src/main/java/mca/items/ItemEngagementRing.java ================================================ package mca.items; import mca.entity.EntityVillagerMCA; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import javax.annotation.Nullable; import java.util.List; public class ItemEngagementRing extends ItemWeddingRing { public boolean handle(EntityPlayer player, EntityVillagerMCA villager) { return super.handle(player, villager); } @SideOnly(Side.CLIENT) public void addInformation(ItemStack stack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { tooltip.add("Halves the hearts required to marry someone."); } } ================================================ FILE: src/main/java/mca/items/ItemGuideBook.java ================================================ package mca.items; import mca.core.Constants; import mca.core.MCA; import mca.core.minecraft.ItemsMCA; import net.minecraft.entity.Entity; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.inventory.Slot; import net.minecraft.item.ItemStack; import net.minecraft.item.ItemWrittenBook; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; import net.minecraft.nbt.NBTTagString; import net.minecraft.network.play.server.SPacketSetSlot; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumHand; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentUtils; import net.minecraft.world.World; public class ItemGuideBook extends ItemWrittenBook { public ItemGuideBook() { super(); } @Override public void onUpdate(ItemStack itemStack, World world, Entity entity, int unknownInt, boolean unknownBoolean) { super.onUpdate(itemStack, world, entity, unknownInt, unknownBoolean); if (!world.isRemote && !itemStack.hasTagCompound()) ItemsMCA.setBookNBT(itemStack); } @Override public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { ItemStack itemstack = playerIn.getHeldItem(handIn); if (worldIn.isRemote) { playerIn.openGui(MCA.getInstance(), Constants.GUI_ID_GUIDEBOOK, worldIn, (int)playerIn.posX, (int)playerIn.posY, (int)playerIn.posZ); } return new ActionResult(EnumActionResult.SUCCESS, itemstack); } private void resolveContents(ItemStack stack, EntityPlayer player) { if (stack.getTagCompound() != null) { NBTTagCompound nbttagcompound = stack.getTagCompound(); if (!nbttagcompound.getBoolean("resolved")) { nbttagcompound.setBoolean("resolved", true); if (validBookTagContents(nbttagcompound)) { NBTTagList nbttaglist = nbttagcompound.getTagList("pages", 8); for (int i = 0; i < nbttaglist.tagCount(); ++i) { String s = nbttaglist.getStringTagAt(i); ITextComponent itextcomponent; try { itextcomponent = ITextComponent.Serializer.fromJsonLenient(s); itextcomponent = TextComponentUtils.processComponent(player, itextcomponent, player); } catch (Exception var9) { itextcomponent = new TextComponentString(s); } nbttaglist.set(i, new NBTTagString(ITextComponent.Serializer.componentToJson(itextcomponent))); } nbttagcompound.setTag("pages", nbttaglist); if (player instanceof EntityPlayerMP && player.getHeldItemMainhand() == stack) { Slot slot = player.openContainer.getSlotFromInventory(player.inventory, player.inventory.currentItem); ((EntityPlayerMP)player).connection.sendPacket(new SPacketSetSlot(0, slot.slotNumber, stack)); } } } } } } ================================================ FILE: src/main/java/mca/items/ItemMatchmakersRing.java ================================================ package mca.items; import com.google.common.base.Optional; import mca.entity.EntityVillagerMCA; import mca.enums.EnumMarriageState; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumParticleTypes; import java.util.Comparator; import java.util.List; public class ItemMatchmakersRing extends ItemSpecialCaseGift { public boolean handle(EntityPlayer player, EntityVillagerMCA villager) { // ensure two rings are in the inventory if (player.inventory.getStackInSlot(player.inventory.currentItem).getCount() < 2) { villager.say(Optional.of(player), "interaction.matchmaker.fail.needtwo"); return false; } // ensure our target isn't married already if (villager.isMarried()) { villager.say(Optional.of(player), "interaction.matchmaker.fail.married"); return false; } List villagers = villager.world.getEntities(EntityVillagerMCA.class, v -> v != null && !v.isMarried() && !v.isChild() && v.getDistance(villager) < 3.0D && v != villager); java.util.Optional target = villagers.stream().min(Comparator.comparingDouble(villager::getDistance)); // ensure we found a nearby villager if (!target.isPresent()) { villager.say(Optional.of(player), "interaction.matchmaker.fail.novillagers"); return false; } // setup the marriage by assigning spouse UUIDs EntityVillagerMCA spouse = target.get(); villager.set(EntityVillagerMCA.SPOUSE_UUID, Optional.of(target.get().getUniqueID())); villager.set(EntityVillagerMCA.MARRIAGE_STATE, EnumMarriageState.MARRIED.getId()); villager.set(EntityVillagerMCA.SPOUSE_NAME, spouse.get(EntityVillagerMCA.VILLAGER_NAME)); spouse.set(EntityVillagerMCA.SPOUSE_UUID, Optional.of(villager.getUniqueID())); spouse.set(EntityVillagerMCA.MARRIAGE_STATE, EnumMarriageState.MARRIED.getId()); spouse.set(EntityVillagerMCA.SPOUSE_NAME, villager.get(EntityVillagerMCA.VILLAGER_NAME)); // spawn hearts to show something happened villager.spawnParticles(EnumParticleTypes.HEART); target.get().spawnParticles(EnumParticleTypes.HEART); // remove the rings for survival mode if (!player.isCreative()) player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); return true; } } ================================================ FILE: src/main/java/mca/items/ItemSpawnEgg.java ================================================ package mca.items; import com.google.common.base.Optional; import mca.entity.EntityVillagerMCA; import mca.enums.EnumGender; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.EnumActionResult; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; public class ItemSpawnEgg extends Item { private boolean isMale; public ItemSpawnEgg(boolean isMale) { this.isMale = isMale; this.setMaxStackSize(1); } @Override public EnumActionResult onItemUse(EntityPlayer player, World world, BlockPos pos, EnumHand hand, EnumFacing side, float hitX, float hitY, float hitZ) { int posX = pos.getX(); int posY = pos.getY() + 1; int posZ = pos.getZ(); if (!world.isRemote) { EntityVillagerMCA villager = new EntityVillagerMCA(world, Optional.absent(), Optional.of(isMale ? EnumGender.MALE : EnumGender.FEMALE)); villager.setPosition(posX + 0.5D, posY, posZ + 0.5D); villager.finalizeMobSpawn(world.getDifficultyForLocation(villager.getPos()), null, false); world.spawnEntity(villager); if (!player.capabilities.isCreativeMode) player.inventory.setInventorySlotContents(player.inventory.currentItem, ItemStack.EMPTY); } return EnumActionResult.PASS; } } ================================================ FILE: src/main/java/mca/items/ItemSpecialCaseGift.java ================================================ package mca.items; import mca.entity.EntityVillagerMCA; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; public abstract class ItemSpecialCaseGift extends Item { public abstract boolean handle(EntityPlayer player, EntityVillagerMCA villager); } ================================================ FILE: src/main/java/mca/items/ItemStaffOfLife.java ================================================ package mca.items; import mca.core.Constants; import mca.core.MCA; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumHand; import net.minecraft.util.text.TextComponentString; import net.minecraft.world.World; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; import org.lwjgl.input.Keyboard; import javax.annotation.Nullable; import java.util.List; public class ItemStaffOfLife extends Item { public ItemStaffOfLife() { super(); maxStackSize = 1; setUnlocalizedName("staff_of_life"); setMaxDamage(4); } @Override public ActionResult onItemRightClick(World worldIn, EntityPlayer playerIn, EnumHand handIn) { if (!MCA.getConfig().enableRevivals) playerIn.sendMessage(new TextComponentString(MCA.getLocalizer().localize("notify.revival.disabled"))); playerIn.openGui(MCA.getInstance(), Constants.GUI_ID_STAFFOFLIFE, playerIn.world, 0, 0, 0); return super.onItemRightClick(worldIn, playerIn, handIn); } @Override public void addInformation(ItemStack itemStack, @Nullable World worldIn, List tooltip, ITooltipFlag flagIn) { tooltip.add("Uses left: " + (itemStack.getMaxDamage() - itemStack.getItemDamage() + 1)); if (Keyboard.isKeyDown(Keyboard.KEY_LSHIFT) || Keyboard.isKeyDown(Keyboard.KEY_RSHIFT)) { tooltip.add("Use to revive a previously dead"); tooltip.add("villager, but all of their memories"); tooltip.add("will be forgotten."); } else tooltip.add("Hold " + Constants.Color.YELLOW + "SHIFT" + Constants.Color.GRAY + " for info."); } @SideOnly(Side.CLIENT) @Override public boolean hasEffect(ItemStack itemStack) { return true; } } ================================================ FILE: src/main/java/mca/items/ItemVillagerEditor.java ================================================ package mca.items; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraftforge.fml.relauncher.Side; import net.minecraftforge.fml.relauncher.SideOnly; public class ItemVillagerEditor extends Item { public ItemVillagerEditor() { super(); maxStackSize = 1; setUnlocalizedName("villager_editor"); } @SideOnly(Side.CLIENT) @Override public boolean hasEffect(ItemStack itemStack) { return true; } } ================================================ FILE: src/main/java/mca/items/ItemWeddingRing.java ================================================ package mca.items; import com.google.common.base.Optional; import mca.core.MCA; import mca.entity.EntityVillagerMCA; import mca.entity.data.PlayerHistory; import mca.entity.data.PlayerSaveData; import mca.enums.EnumDialogueType; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.EnumParticleTypes; public class ItemWeddingRing extends ItemSpecialCaseGift { public boolean handle(EntityPlayer player, EntityVillagerMCA villager) { PlayerSaveData playerData = PlayerSaveData.get(player); PlayerHistory history = villager.getPlayerHistoryFor(player.getUniqueID()); String response; if (villager.isMarriedTo(player.getUniqueID())) response = "interaction.marry.fail.marriedtogiver"; else if (villager.isMarried()) response = "interaction.marry.fail.marriedtoother"; else if (playerData.isMarriedOrEngaged()) response = "interaction.marry.fail.marriedtoother"; else if (this instanceof ItemEngagementRing && history.getHearts() < MCA.getConfig().marriageHeartsRequirement / 2) response = "interaction.marry.fail.lowhearts"; else if (!(this instanceof ItemEngagementRing) && history.getHearts() < MCA.getConfig().marriageHeartsRequirement) response = "interaction.marry.fail.lowhearts"; else { response = "interaction.marry.success"; playerData.marry(villager.getUniqueID(), villager.get(EntityVillagerMCA.VILLAGER_NAME)); villager.getPlayerHistoryFor(player.getUniqueID()).setDialogueType(EnumDialogueType.SPOUSE); villager.spawnParticles(EnumParticleTypes.HEART); villager.marry(player); } villager.say(Optional.of(player), response); return false; } } ================================================ FILE: src/main/java/mca/items/ItemWhistle.java ================================================ package mca.items; import java.util.List; import mca.core.Constants; import mca.core.MCA; import net.minecraft.client.util.ITooltipFlag; import net.minecraft.entity.player.EntityPlayer; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.ActionResult; import net.minecraft.util.EnumHand; import net.minecraft.world.World; public class ItemWhistle extends Item { public ItemWhistle() { super(); maxStackSize = 1; } @Override public ActionResult onItemRightClick(World world, EntityPlayer player, EnumHand hand) { player.openGui(MCA.getInstance(), Constants.GUI_ID_WHISTLE, world, (int)player.posX, (int)player.posY, (int)player.posZ); return super.onItemRightClick(world, player, hand); } @Override public void addInformation(ItemStack stack, World worldIn, List tooltip, ITooltipFlag flagIn) { super.addInformation(stack, worldIn, tooltip, flagIn); tooltip.add("Allows you to call your family to your current location."); } } ================================================ FILE: src/main/java/mca/server/ServerMessageHandler.java ================================================ package mca.server; import mca.core.forge.NetMCA; import mca.core.minecraft.VillageHelper; import net.minecraft.entity.player.EntityPlayerMP; import net.minecraft.util.text.TextComponentString; public class ServerMessageHandler { public static void handleMessage(EntityPlayerMP player, NetMCA.ButtonAction message) { switch (message.getButtonId()) { case "gui.button.debug.startraid": startRaid(player); break; case "gui.button.debug.spawnguards": spawnGuards(player); break; case "gui.button.debug.rebuildvillage": rebuildVillage(player); break; } } private static void startRaid(EntityPlayerMP player) { player.sendMessage(new TextComponentString("Starting raid on village...")); VillageHelper.forceRaid(player); } private static void spawnGuards(EntityPlayerMP player) { player.sendMessage(new TextComponentString("Spawning village guards...")); VillageHelper.tick(player.world); } private static void rebuildVillage(EntityPlayerMP player) { player.sendMessage(new TextComponentString("Rebuilding annihilated village...")); } } ================================================ FILE: src/main/java/mca/util/ItemStackCache.java ================================================ package mca.util; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import java.util.HashMap; import java.util.Map; public class ItemStackCache { private static Map cache = new HashMap<>(); public static ItemStack get(Item item) { if (!cache.containsKey(item)) cache.put(item, new ItemStack(item, 1)); return cache.get(item); } } ================================================ FILE: src/main/java/mca/util/ResourceLocationCache.java ================================================ package mca.util; import net.minecraft.util.ResourceLocation; import java.util.HashMap; import java.util.Map; public class ResourceLocationCache { private static Map cache = new HashMap<>(); public static ResourceLocation getResourceLocationFor(String location) { if (cache.containsKey(location)) { return cache.get(location); } else { ResourceLocation rLoc = new ResourceLocation(location); cache.put(location, rLoc); return rLoc; } } } ================================================ FILE: src/main/java/mca/util/Util.java ================================================ package mca.util; import com.google.common.base.Optional; import com.google.gson.Gson; import mca.core.MCA; import net.minecraft.block.Block; import net.minecraft.entity.Entity; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import org.apache.commons.io.IOUtils; import javax.annotation.Nullable; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.UUID; import static org.apache.http.protocol.HTTP.USER_AGENT; public class Util { private static final String RESOURCE_PREFIX = "assets/mca/"; /** * Finds a y position given an x,y,z coordinate triple that is assumed to be the world's "ground". * * @param world The world in which blocks will be tested * @param x X coordinate * @param y Y coordinate, used as the starting height for finding ground. * @param z Z coordinate * @return Integer representing the air block above the first non-air block given the provided ordered triples. */ public static int getSpawnSafeTopLevel(World world, int x, int y, int z) { Block block = Blocks.AIR; while (block == Blocks.AIR && y > 0) { y--; block = world.getBlockState(new BlockPos(x, y, z)).getBlock(); } return y + 1; } public static String readResource(String path) { String data; String location = RESOURCE_PREFIX + path; try { data = IOUtils.toString(new InputStreamReader(MCA.class.getClassLoader().getResourceAsStream(location))); } catch (IOException e) { throw new RuntimeException("Failed to read resource from JAR: " + location); } return data; } public static T readResourceAsJSON(String path, Class type) { Gson gson = new Gson(); T data = gson.fromJson(Util.readResource(path), type); return data; } public static Optional getEntityByUUID(World world, UUID uuid) { for (Entity entity : world.loadedEntityList) { if (entity.getUniqueID().equals(uuid)) { return Optional.of(entity); } } return Optional.absent(); } public static Optional getEntityByUUID(World world, UUID uuid, Class clazz) { for (Entity entity : world.loadedEntityList) { if (entity.getClass().isAssignableFrom(clazz) && entity.getUniqueID().equals(uuid)) { return Optional.of((T) entity); } } return Optional.absent(); } public static List getNearbyBlocks(BlockPos origin, World world, @Nullable Class filter, int xzDist, int yDist) { final List pointsList = new ArrayList<>(); for (int x = -xzDist; x <= xzDist; x++) { for (int y = -yDist; y <= yDist; y++) { for (int z = -xzDist; z <= xzDist; z++) { if (x != 0 || y != 0 || z != 0) { BlockPos pos = new BlockPos(origin.getX() + x, origin.getY() + y, origin.getZ() + z); if (filter != null && filter.isAssignableFrom(world.getBlockState(pos).getBlock().getClass())) { pointsList.add(pos); } else if (filter == null) { pointsList.add(pos); } } } } } return pointsList; } public static BlockPos getNearestPoint(BlockPos origin, List blocks) { double closest = 100.0D; BlockPos returnPoint = null; for (BlockPos point : blocks) { double distance = origin.getDistance(point.getX(), point.getY(), point.getZ()); if (distance < closest) { closest = distance; returnPoint = point; } } return returnPoint; } public static String httpGet(String url) { try { URL obj = new URL(url); HttpURLConnection con = (HttpURLConnection) obj.openConnection(); con.setRequestMethod("GET"); con.setRequestProperty("User-Agent", USER_AGENT); BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); String inputLine; StringBuffer response = new StringBuffer(); while ((inputLine = in.readLine()) != null) { response.append(inputLine); } in.close(); return response.toString(); } catch (IOException ignored) { MCA.getLog().error("Failed to GET from: " + url); } return ""; } } ================================================ FILE: src/main/resources/assets/mca/api/gifts.json ================================================ [ {"type":"item", "name":"minecraft:wooden_sword", "value":3}, {"type":"item", "name":"minecraft:wooden_axe", "value":3}, {"type":"item", "name":"minecraft:wooden_hoe", "value":3}, {"type":"item", "name":"minecraft:wooden_shovel", "value":3}, {"type":"item", "name":"minecraft:stone_sword", "value":6}, {"type":"item", "name":"minecraft:stone_axe", "value":6}, {"type":"item", "name":"minecraft:stone_hoe", "value":6}, {"type":"item", "name":"minecraft:stone_shovel", "value":6}, {"type":"item", "name":"minecraft:wooden_pickaxe", "value":3}, {"type":"item", "name":"minecraft:beef", "value":5}, {"type":"item", "name":"minecraft:chicken", "value":5}, {"type":"item", "name":"minecraft:porkchop", "value":5}, {"type":"item", "name":"minecraft:leather", "value":3}, {"type":"item", "name":"minecraft:leather_chestplate", "value":3}, {"type":"item", "name":"minecraft:leather_helmet", "value":3}, {"type":"item", "name":"minecraft:leather_leggings", "value":3}, {"type":"item", "name":"minecraft:leather_boots", "value":3}, {"type":"item", "name":"minecraft:reeds", "value":2}, {"type":"item", "name":"minecraft:wheat_seeds", "value":1}, {"type":"item", "name":"minecraft:wheat", "value":1}, {"type":"item", "name":"minecraft:bread", "value":3}, {"type":"item", "name":"minecraft:coal", "value":5}, {"type":"item", "name":"minecraft:sugar", "value":5}, {"type":"item", "name":"minecraft:clay_ball", "value":0}, {"type":"item", "name":"minecraft:dye", "value":1}, {"type":"item", "name":"minecraft:cooked_beef", "value":5}, {"type":"item", "name":"minecraft:cooked_chicken", "value":5}, {"type":"item", "name":"minecraft:cooked_porkchop", "value":5}, {"type":"item", "name":"minecraft:cookie", "value":10}, {"type":"item", "name":"minecraft:melon", "value":5}, {"type":"item", "name":"minecraft:melon_seeds", "value":1}, {"type":"item", "name":"minecraft:iron_helmet", "value":5}, {"type":"item", "name":"minecraft:iron_chestplate", "value":5}, {"type":"item", "name":"minecraft:iron_leggings", "value":5}, {"type":"item", "name":"minecraft:iron_boots", "value":5}, {"type":"item", "name":"minecraft:cake", "value":15}, {"type":"item", "name":"minecraft:iron_sword", "value":5}, {"type":"item", "name":"minecraft:iron_axe", "value":5}, {"type":"item", "name":"minecraft:iron_hoe", "value":5}, {"type":"item", "name":"minecraft:iron_pickaxe", "value":5}, {"type":"item", "name":"minecraft:iron_shovel", "value":5}, {"type":"item", "name":"minecraft:fishing_rod", "value":1}, {"type":"item", "name":"minecraft:bow", "value":3}, {"type":"item", "name":"minecraft:book", "value":5}, {"type":"item", "name":"minecraft:bucket", "value":0}, {"type":"item", "name":"minecraft:milk_bucket", "value":3}, {"type":"item", "name":"minecraft:water_bucket", "value":0}, {"type":"item", "name":"minecraft:lava_bucket", "value":0}, {"type":"item", "name":"minecraft:mushroom_stew", "value":10}, {"type":"item", "name":"minecraft:pumpkin_seeds", "value":2}, {"type":"item", "name":"minecraft:flint_and_steel", "value":3}, {"type":"item", "name":"minecraft:redstone", "value":2}, {"type":"item", "name":"minecraft:boat", "value":3}, {"type":"item", "name":"minecraft:iron_door", "value":0}, {"type":"item", "name":"minecraft:minecart", "value":0}, {"type":"item", "name":"minecraft:flint", "value":0}, {"type":"item", "name":"minecraft:gold_nugget", "value":5}, {"type":"item", "name":"minecraft:gold_ingot", "value":8}, {"type":"item", "name":"minecraft:iron_ingot", "value":4}, {"type":"item", "name":"minecraft:diamond", "value":15}, {"type":"item", "name":"minecraft:map", "value":0}, {"type":"item", "name":"minecraft:clock", "value":3}, {"type":"item", "name":"minecraft:compass", "value":3}, {"type":"item", "name":"minecraft:blaze_rod", "value":10}, {"type":"item", "name":"minecraft:blaze_powder", "value":6}, {"type":"item", "name":"minecraft:diamond_sword", "value":10}, {"type":"item", "name":"minecraft:diamond_axe", "value":10}, {"type":"item", "name":"minecraft:diamond_shovel", "value":10}, {"type":"item", "name":"minecraft:diamond_hoe", "value":10}, {"type":"item", "name":"minecraft:diamond_helmet", "value":10}, {"type":"item", "name":"minecraft:diamond_chestplate", "value":10}, {"type":"item", "name":"minecraft:diamond_leggings", "value":10}, {"type":"item", "name":"minecraft:diamond_boots", "value":10}, {"type":"item", "name":"minecraft:painting", "value":10}, {"type":"item", "name":"minecraft:ender_pearl", "value":15}, {"type":"item", "name":"minecraft:ender_eye", "value":25}, {"type":"item", "name":"minecraft:slime_ball", "value":0}, {"type":"item", "name":"minecraft:saddle", "value":3}, {"type":"item", "name":"minecraft:gunpowder", "value":5}, {"type":"item", "name":"minecraft:golden_apple", "value":25}, {"type":"item", "name":"minecraft:record_11", "value":15}, {"type":"item", "name":"minecraft:record_13", "value":15}, {"type":"item", "name":"minecraft:record_wait", "value":15}, {"type":"item", "name":"minecraft:record_cat", "value":15}, {"type":"item", "name":"minecraft:record_chirp", "value":15}, {"type":"item", "name":"minecraft:record_far", "value":15}, {"type":"item", "name":"minecraft:record_mall", "value":15}, {"type":"item", "name":"minecraft:record_mellohi", "value":15}, {"type":"item", "name":"minecraft:record_stal", "value":15}, {"type":"item", "name":"minecraft:record_strad", "value":15}, {"type":"item", "name":"minecraft:record_ward", "value":15}, {"type":"item", "name":"minecraft:emerald", "value":25}, {"type":"block","name":"minecraft:red_flower","value":2}, {"type":"block","name":"minecraft:yellow_flower","value":2}, {"type":"block","name":"minecraft:planks","value":1}, {"type":"block","name":"minecraft:log","value":1}, {"type":"block","name":"minecraft:pumpkin","value":3}, {"type":"block","name":"minecraft:chest","value":6}, {"type":"block","name":"minecraft:wool","value":3}, {"type":"block","name":"minecraft:iron_ore","value":3}, {"type":"block","name":"minecraft:gold_ore","value":5}, {"type":"block","name":"minecraft:redstone_ore","value":3}, {"type":"block","name":"minecraft:rail","value":5}, {"type":"block","name":"minecraft:detector_rail","value":7}, {"type":"block","name":"minecraft:activator_rail","value":7}, {"type":"block","name":"minecraft:furnace","value":5}, {"type":"block","name":"minecraft:crafting_table","value":3}, {"type":"block","name":"minecraft:lapis_block","value":15}, {"type":"block","name":"minecraft:bookshelf","value":5}, {"type":"block","name":"minecraft:gold_block","value":15}, {"type":"block","name":"minecraft:iron_block","value":10}, {"type":"block","name":"minecraft:diamond_block","value":25}, {"type":"block","name":"minecraft:brewing_stand","value":5}, {"type":"block","name":"minecraft:enchanting_table","value":5}, {"type":"block","name":"minecraft:brick_block","value":3}, {"type":"block","name":"minecraft:obsidian","value":9}, {"type":"block","name":"minecraft:piston","value":6}, {"type":"block","name":"minecraft:glowstone","value":5}, {"type":"block","name":"minecraft:emerald_block","value":25}, {"type":"block","name":"minecraft:redstone_block","value":15}, {"type":"block","name":"mca:rose_gold_block","value":10}, {"type":"block","name":"mca:rose_gold_ore","value":10} ] ================================================ FILE: src/main/resources/assets/mca/api/gui/debug.json ================================================ [ { "id": 1, "identifier": "gui.button.debug.startraid", "x": 120, "y": -115, "width": 85, "height": 20, "notifyServer": true, "targetServer": true, "constraints": "" }, { "id": 2, "identifier": "gui.button.debug.spawnguards", "x": 120, "y": -93, "width": 85, "height": 20, "notifyServer": true, "targetServer": true, "constraints": "" }, { "id": 3, "identifier": "gui.button.debug.selectnearestvillager", "x": 120, "y": -71, "width": 85, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "" }, { "id": 4, "identifier": "gui.button.debug.startmining", "x": 120, "y": -49, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 5, "identifier": "gui.button.debug.startfishing", "x": 120, "y": -27, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 6, "identifier": "gui.button.debug.startchopping", "x": 120, "y": -5, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 7, "identifier": "gui.button.debug.starthunting", "x": 120, "y": 17, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 8, "identifier": "gui.button.debug.startharvesting", "x": 120, "y": 39, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 9, "identifier": "gui.button.debug.zombify", "x": 10, "y": -115, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 10, "identifier": "gui.button.debug.unzombify", "x": 10, "y": -93, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 11, "identifier": "gui.button.debug.marrytoplayer", "x": 10, "y": -71, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 12, "identifier": "gui.button.debug.rebuildvillage", "x": 10, "y": -49, "width": 85, "height": 20, "notifyServer": true, "targetServer": true, "constraints": "" }, { "id": 13, "identifier": "gui.button.debug.openinventory", "x": 10, "y": -27, "width": 85, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" } ] ================================================ FILE: src/main/resources/assets/mca/api/gui/editor.json ================================================ [ { "id": 1, "identifier": "gui.button.random", "x": -50, "y": -95, "width": 60, "height": 20, "notifyServer": true }, { "id": 2, "identifier": "gui.button.gender", "x": -190, "y": -40, "width": 175, "height": 20, "notifyServer": true }, { "id": 3, "identifier": "gui.button.texture.set", "x": 70, "y": -15, "width": 60, "height": 20 }, { "id": 4, "identifier": "gui.button.texture.randomize", "x": 140, "y": -15, "width": 60, "height": 20, "notifyServer": true }, { "id": 5, "identifier": "gui.button.profession.set", "x": 70, "y": 10, "width": 60, "height": 20 }, { "id": 6, "identifier": "gui.button.profession.randomize", "x": 140, "y": 10, "width": 60, "height": 20, "notifyServer": true }, { "id": 7, "identifier": "gui.button.infected", "x": -190, "y": 35, "width": 175, "height": 20, "notifyServer": true }, { "id": 8, "identifier": "gui.button.done", "x": -65, "y": 85, "width": 75, "height": 20 }, { "id": 9, "identifier": "gui.button.copyuuid", "x": 25, "y": 85, "width": 75, "height": 20 } ] ================================================ FILE: src/main/resources/assets/mca/api/gui/interact.json ================================================ [ { "id": 1, "identifier": "gui.button.backarrow", "x": 120, "y": -115, "width": 15, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "" }, { "id": 1, "identifier": "gui.button.chat", "x": 140, "y": -115, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "", "isInteraction": true }, { "id": 2, "identifier": "gui.button.joke", "x": 140, "y": -93, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "", "isInteraction": true }, { "id": 3, "identifier": "gui.button.gift", "x": 140, "y": -71, "width": 65, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "" }, { "id": 4, "identifier": "gui.button.shakehand", "x": 140, "y": -49, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "", "isInteraction": true }, { "id": 5, "identifier": "gui.button.tellstory", "x": 140, "y": -27, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "", "isInteraction": true }, { "id": 6, "identifier": "gui.button.flirt", "x": 140, "y": -5, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "adults", "isInteraction": true }, { "id": 7, "identifier": "gui.button.hug", "x": 140, "y": 17, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "adults", "isInteraction": true }, { "id": 8, "identifier": "gui.button.kiss", "x": 140, "y": 39, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "adults", "isInteraction": true } ] ================================================ FILE: src/main/resources/assets/mca/api/gui/location.json ================================================ [ { "id": 1, "identifier": "gui.button.backarrow", "x": 140, "y": -115, "width": 65, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "" }, { "id": 2, "identifier": "gui.button.sethome", "x": 140, "y": -93, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 3, "identifier": "gui.button.setworkplace", "x": 140, "y": -71, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 4, "identifier": "gui.button.sethangout", "x": 140, "y": -49, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" } ] ================================================ FILE: src/main/resources/assets/mca/api/gui/main.json ================================================ [ { "id": 1, "identifier": "gui.button.interact", "x": 140, "y": -115, "width": 65, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "" }, { "id": 2, "identifier": "gui.button.follow", "x": 140, "y": -93, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 3, "identifier": "gui.button.stay", "x": 140, "y": -71, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 4, "identifier": "gui.button.move", "x": 140, "y": -49, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 5, "identifier": "gui.button.trade", "x": 140, "y": -27, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "notfamily|hideonfail" }, { "id": 12, "identifier": "gui.button.inventory", "x": 140, "y": -27, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "family|hideonfail" }, { "id": 6, "identifier": "gui.button.location", "x": 140, "y": -5, "width": 65, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "" }, { "id": 7, "identifier": "gui.button.gohome", "x": 140, "y": 17, "width": 65, "height": 20, "notifyServer": true, "spouseOnly": false, "targetServer": false, "constraints": "" }, { "id": 8, "identifier": "gui.button.ridehorse", "x": 140, "y": 39, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 9, "identifier": "gui.button.work", "x": 140, "y": 61, "width": 65, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "family|hideonfail" }, { "id": 10, "identifier": "gui.button.procreate", "x": 140, "y": 83, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "spouse|hideonfail" } ] ================================================ FILE: src/main/resources/assets/mca/api/gui/work.json ================================================ [ { "id": 1, "identifier": "gui.button.backarrow", "x": 140, "y": -115, "width": 15, "height": 20, "notifyServer": false, "targetServer": false, "constraints": "" }, { "id": 2, "identifier": "gui.button.fishing", "x": 140, "y": -115, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 3, "identifier": "gui.button.harvesting", "x": 140, "y": -93, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 4, "identifier": "gui.button.hunting", "x": 140, "y": -71, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 5, "identifier": "gui.button.prospecting", "x": 140, "y": -49, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 5, "identifier": "gui.button.chopping", "x": 140, "y": -27, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" }, { "id": 6, "identifier": "gui.button.stopworking", "x": 140, "y": -5, "width": 65, "height": 20, "notifyServer": true, "targetServer": false, "constraints": "" } ] ================================================ FILE: src/main/resources/assets/mca/api/skins.json ================================================ [ { "gender": "male", "profession": "minecraft:farmer", "paths": [ "mca:skins/male/farmer/farmerm1_converted.png", "mca:skins/male/farmer/farmerm2_converted.png", "mca:skins/male/farmer/farmerm3_converted.png", "mca:skins/male/farmer/farmerm4_converted.png", "mca:skins/male/farmer/farmerm5_converted.png", "mca:skins/male/farmer/farmerm6_converted.png", "mca:skins/male/farmer/farmerm7_converted.png", "mca:skins/male/farmer/farmerm8_converted.png", "mca:skins/male/farmer/farmerm9_converted.png", "mca:skins/male/farmer/farmerm10_converted.png", "mca:skins/male/farmer/farmerm11_converted.png", "mca:skins/male/farmer/farmerm12_converted.png", "mca:skins/male/farmer/farmerm13_converted.png", "mca:skins/male/farmer/farmerm14_converted.png", "mca:skins/male/farmer/farmerm15_converted.png", "mca:skins/male/farmer/farmerm16_converted.png", "mca:skins/male/farmer/farmerm17_converted.png", "mca:skins/male/farmer/farmerm18_converted.png", "mca:skins/male/farmer/farmerm19_converted.png", "mca:skins/male/farmer/farmerm20_converted.png", "mca:skins/male/farmer/farmerm21_converted.png", "mca:skins/male/farmer/farmerm23_converted.png", "mca:skins/male/farmer/farmerm25_converted.png" ] }, { "gender": "female", "profession": "minecraft:farmer", "paths": [ "mca:skins/female/farmer/farmerf1_converted.png", "mca:skins/female/farmer/farmerf2_converted.png", "mca:skins/female/farmer/farmerf3_converted.png", "mca:skins/female/farmer/farmerf4_converted.png", "mca:skins/female/farmer/farmerf5_converted.png", "mca:skins/female/farmer/farmerf6_converted.png", "mca:skins/female/farmer/farmerf7_converted.png", "mca:skins/female/farmer/farmerf8_converted.png", "mca:skins/female/farmer/farmerf9_converted.png", "mca:skins/female/farmer/farmerf10_converted.png", "mca:skins/female/farmer/farmerf11_converted.png", "mca:skins/female/farmer/farmerf12_converted.png", "mca:skins/female/farmer/farmerf13_converted.png", "mca:skins/female/farmer/farmerf14_converted.png", "mca:skins/female/farmer/farmerf15_converted.png", "mca:skins/female/farmer/farmerf16_converted.png", "mca:skins/female/farmer/farmerf17_converted.png", "mca:skins/female/farmer/farmerf18_converted.png", "mca:skins/female/farmer/farmerf19_converted.png", "mca:skins/female/farmer/farmerf20_converted.png", "mca:skins/female/farmer/farmerf21_converted.png", "mca:skins/female/farmer/farmerf22_converted.png", "mca:skins/female/farmer/farmerf23_converted.png", "mca:skins/female/farmer/farmerf24_converted.png", "mca:skins/female/farmer/farmerf25_converted.png" ] }, { "gender": "male", "profession": "minecraft:librarian", "paths": [ "mca:skins/male/librarian/librarianm1_converted.png", "mca:skins/male/librarian/librarianm2_converted.png", "mca:skins/male/librarian/librarianm3_converted.png", "mca:skins/male/librarian/librarianm4_converted.png", "mca:skins/male/librarian/librarianm5_converted.png", "mca:skins/male/librarian/librarianm6_converted.png", "mca:skins/male/librarian/librarianm7_converted.png", "mca:skins/male/librarian/librarianm8_converted.png", "mca:skins/male/librarian/librarianm9_converted.png", "mca:skins/male/librarian/librarianm10_converted.png", "mca:skins/male/librarian/librarianm11_converted.png", "mca:skins/male/librarian/librarianm12_converted.png", "mca:skins/male/librarian/librarianm13_converted.png" ] }, { "gender": "female", "profession": "minecraft:librarian", "paths": [ "mca:skins/female/librarian/librarianf1_converted.png", "mca:skins/female/librarian/librarianf2_converted.png", "mca:skins/female/librarian/librarianf3_converted.png", "mca:skins/female/librarian/librarianf4_converted.png", "mca:skins/female/librarian/librarianf5_converted.png", "mca:skins/female/librarian/librarianf6_converted.png", "mca:skins/female/librarian/librarianf7_converted.png", "mca:skins/female/librarian/librarianf8_converted.png", "mca:skins/female/librarian/librarianf9_converted.png", "mca:skins/female/librarian/librarianf10_converted.png" ] }, { "gender": "male", "profession": "minecraft:priest", "paths": [ "mca:skins/male/priest/priestm1_converted.png", "mca:skins/male/priest/priestm2_converted.png", "mca:skins/male/priest/priestm3_converted.png", "mca:skins/male/priest/priestm4_converted.png", "mca:skins/male/priest/priestm5_converted.png", "mca:skins/male/priest/priestm6_converted.png", "mca:skins/male/priest/priestm7_converted.png", "mca:skins/male/priest/priestm8_converted.png", "mca:skins/male/priest/priestm9_converted.png", "mca:skins/male/priest/priestm10_converted.png", "mca:skins/male/priest/priestm11_converted.png", "mca:skins/male/priest/priestm12_converted.png" ] }, { "gender": "female", "profession": "minecraft:priest", "paths": [ "mca:skins/female/priest/priestf1_converted.png", "mca:skins/female/priest/priestf2_converted.png", "mca:skins/female/priest/priestf3_converted.png", "mca:skins/female/priest/priestf4_converted.png", "mca:skins/female/priest/priestf5_converted.png", "mca:skins/female/priest/priestf6_converted.png", "mca:skins/female/priest/priestf7_converted.png", "mca:skins/female/priest/priestf8_converted.png", "mca:skins/female/priest/priestf9_converted.png", "mca:skins/female/priest/priestf10_converted.png", "mca:skins/female/priest/priestf11_converted.png", "mca:skins/female/priest/priestf12_converted.png" ] }, { "gender": "male", "profession": "minecraft:smith", "paths": [ "mca:skins/male/smith/smithm1_converted.png", "mca:skins/male/smith/smithm2_converted.png", "mca:skins/male/smith/smithm3_converted.png", "mca:skins/male/smith/smithm4_converted.png", "mca:skins/male/smith/smithm5_converted.png", "mca:skins/male/smith/smithm6_converted.png", "mca:skins/male/smith/smithm7_converted.png", "mca:skins/male/smith/smithm8_converted.png", "mca:skins/male/smith/smithm9_converted.png" ] }, { "gender": "female", "profession": "minecraft:smith", "paths": [ "mca:skins/female/smith/smithf1_converted.png", "mca:skins/female/smith/smithf2_converted.png", "mca:skins/female/smith/smithf3_converted.png", "mca:skins/female/smith/smithf4_converted.png", "mca:skins/female/smith/smithf5_converted.png", "mca:skins/female/smith/smithf6_converted.png", "mca:skins/female/smith/smithf7_converted.png" ] }, { "gender": "male", "profession": "minecraft:butcher", "paths": [ "mca:skins/male/butcher/butcherm1_converted.png", "mca:skins/male/butcher/butcherm2_converted.png", "mca:skins/male/butcher/butcherm3_converted.png", "mca:skins/male/butcher/butcherm4_converted.png", "mca:skins/male/butcher/butcherm5_converted.png", "mca:skins/male/butcher/butcherm6_converted.png", "mca:skins/male/butcher/butcherm7_converted.png", "mca:skins/male/butcher/butcherm8_converted.png", "mca:skins/male/butcher/butcherm9_converted.png" ] }, { "gender": "female", "profession": "minecraft:butcher", "paths": [ "mca:skins/female/butcher/butcherf1_converted.png", "mca:skins/female/butcher/butcherf2_converted.png", "mca:skins/female/butcher/butcherf3_converted.png", "mca:skins/female/butcher/butcherf4_converted.png" ] }, { "gender": "male", "profession": "mca:baker", "paths": [ "mca:skins/male/baker/bakerm1_converted.png", "mca:skins/male/baker/bakerm2_converted.png", "mca:skins/male/baker/bakerm3_converted.png", "mca:skins/male/baker/bakerm4_converted.png", "mca:skins/male/baker/bakerm5_converted.png", "mca:skins/male/baker/bakerm6_converted.png", "mca:skins/male/baker/bakerm7_converted.png", "mca:skins/male/baker/bakerm8_converted.png", "mca:skins/male/baker/bakerm9_converted.png", "mca:skins/male/baker/bakerm10_converted.png" ] }, { "gender": "female", "profession": "mca:baker", "paths": [ "mca:skins/female/baker/bakerf1_converted.png", "mca:skins/female/baker/bakerf2_converted.png", "mca:skins/female/baker/bakerf3_converted.png", "mca:skins/female/baker/bakerf4_converted.png", "mca:skins/female/baker/bakerf5_converted.png", "mca:skins/female/baker/bakerf6_converted.png", "mca:skins/female/baker/bakerf7_converted.png", "mca:skins/female/baker/bakerf8_converted.png", "mca:skins/female/baker/bakerf9_converted.png", "mca:skins/female/baker/bakerf10_converted.png", "mca:skins/female/baker/bakerf11_converted.png", "mca:skins/female/baker/bakerf12_converted.png", "mca:skins/female/baker/bakerf13_converted.png" ] }, { "gender": "male", "profession": "mca:miner", "paths": [ "mca:skins/male/miner/minerm1_converted.png", "mca:skins/male/miner/minerm2_converted.png", "mca:skins/male/miner/minerm3_converted.png", "mca:skins/male/miner/minerm4_converted.png", "mca:skins/male/miner/minerm5_converted.png", "mca:skins/male/miner/minerm6_converted.png", "mca:skins/male/miner/minerm7_converted.png", "mca:skins/male/miner/minerm8_converted.png", "mca:skins/male/miner/minerm9_converted.png", "mca:skins/male/miner/minerm10_converted.png", "mca:skins/male/miner/minerm11_converted.png", "mca:skins/male/miner/minerm12_converted.png", "mca:skins/male/miner/minerm13_converted.png", "mca:skins/male/miner/minerm14_converted.png" ] }, { "gender": "female", "profession": "mca:miner", "paths": [ "mca:skins/female/miner/minerf1_converted.png", "mca:skins/female/miner/minerf2_converted.png", "mca:skins/female/miner/minerf3_converted.png", "mca:skins/female/miner/minerf4_converted.png", "mca:skins/female/miner/minerf5_converted.png", "mca:skins/female/miner/minerf6_converted.png", "mca:skins/female/miner/minerf7_converted.png", "mca:skins/female/miner/minerf8_converted.png", "mca:skins/female/miner/minerf9_converted.png", "mca:skins/female/miner/minerf10_converted.png", "mca:skins/female/miner/minerf11_converted.png", "mca:skins/female/miner/minerf12_converted.png", "mca:skins/female/miner/minerf13_converted.png", "mca:skins/female/miner/minerf14_converted.png", "mca:skins/female/miner/minerf15_converted.png" ] }, { "gender": "male", "profession": "mca:guard", "paths": [ "mca:skins/male/warrior/warriorm1_converted.png", "mca:skins/male/warrior/warriorm2_converted.png", "mca:skins/male/warrior/warriorm3_converted.png", "mca:skins/male/warrior/warriorm4_converted.png", "mca:skins/male/warrior/warriorm5_converted.png" ] }, { "gender": "female", "profession": "mca:guard", "paths": [ "mca:skins/female/warrior/warriorf1_converted.png", "mca:skins/female/warrior/warriorf2_converted.png", "mca:skins/female/warrior/warriorf3_converted.png", "mca:skins/female/warrior/warriorf4_converted.png", "mca:skins/female/warrior/warriorf5_converted.png", "mca:skins/female/warrior/warriorf6_converted.png" ] }, { "gender": "male", "profession": "mca:child", "paths": [ "mca:skins/male/child/childm1_converted.png", "mca:skins/male/child/childm2_converted.png", "mca:skins/male/child/childm3_converted.png", "mca:skins/male/child/childm4_converted.png", "mca:skins/male/child/childm5_converted.png", "mca:skins/male/child/childm6_converted.png", "mca:skins/male/child/childm7_converted.png", "mca:skins/male/child/childm8_converted.png", "mca:skins/male/child/childm9_converted.png", "mca:skins/male/child/childm10_converted.png", "mca:skins/male/child/childm11_converted.png", "mca:skins/male/child/childm12_converted.png", "mca:skins/male/child/childm13_converted.png", "mca:skins/male/child/childm14_converted.png", "mca:skins/male/child/childm15_converted.png", "mca:skins/male/child/childm16_converted.png", "mca:skins/male/child/childm17_converted.png", "mca:skins/male/child/childm18_converted.png", "mca:skins/male/child/childm19_converted.png", "mca:skins/male/child/childm20_converted.png", "mca:skins/male/child/childm21_converted.png", "mca:skins/male/child/childm22_converted.png", "mca:skins/male/child/childm23_converted.png", "mca:skins/male/child/childm24_converted.png", "mca:skins/male/child/childm25_converted.png", "mca:skins/male/child/childm26_converted.png", "mca:skins/male/child/childm27_converted.png" ] }, { "gender": "female", "profession": "mca:child", "paths": [ "mca:skins/female/child/childf1_converted.png", "mca:skins/female/child/childf2_converted.png", "mca:skins/female/child/childf3_converted.png", "mca:skins/female/child/childf4_converted.png", "mca:skins/female/child/childf5_converted.png", "mca:skins/female/child/childf6_converted.png", "mca:skins/female/child/childf7_converted.png", "mca:skins/female/child/childf8_converted.png", "mca:skins/female/child/childf9_converted.png", "mca:skins/female/child/childf10_converted.png", "mca:skins/female/child/childf11_converted.png", "mca:skins/female/child/childf12_converted.png", "mca:skins/female/child/childf13_converted.png", "mca:skins/female/child/childf14_converted.png", "mca:skins/female/child/childf15_converted.png", "mca:skins/female/child/childf16_converted.png", "mca:skins/female/child/childf17_converted.png", "mca:skins/female/child/childf18_converted.png", "mca:skins/female/child/childf19_converted.png", "mca:skins/female/child/childf20_converted.png", "mca:skins/female/child/childf21_converted.png" ] } ] ================================================ FILE: src/main/resources/assets/mca/blockstates/rose_gold_block.json ================================================ { "forge_marker": 1, "defaults": { "model": "mca:rose_gold_block" }, "variants": { "normal": [{}], "inventory": [{}] } } ================================================ FILE: src/main/resources/assets/mca/blockstates/rose_gold_ore.json ================================================ { "forge_marker": 1, "defaults": { "model": "mca:rose_gold_ore" }, "variants": { "normal": [{}], "inventory": [{}] } } ================================================ FILE: src/main/resources/assets/mca/blockstates/villager_spawner.json ================================================ { "forge_marker": 1, "defaults": { "model": "mca:villager_spawner" }, "variants": { "normal": [{}], "inventory": [{}] } } ================================================ FILE: src/main/resources/assets/mca/lang/en_us.lang ================================================ #X-Generator: crowdin.com itemGroup.MCA=Minecraft Comes Alive enum.agestate.baby=Baby enum.agestate.toddler=Toddler enum.agestate.child=Child enum.agestate.teen=Teen enum.agestate.adult=Adult entity.Villager.marauder=Marauder entity.Villager.outlaw=Outlaw entity.Villager.pillager=Pillager entity.Villager.miner=Miner entity.Villager.baker=Baker entity.Villager.warrior=Warrior entity.Villager.archer=Archer entity.Villager.hero=Hero entity.Villager.child=Child ############################## # Items & Blocks ############################## item.wedding_ring.name=Wedding Ring item.wedding_ring_rg.name=Rose Gold Wedding Ring item.engagement_ring.name=Engagement Ring item.engagement_ring_rg.name=Rose Gold Engagement Ring item.matchmakers_ring.name=Matchmaker's Ring item.baby_boy.name=Baby Boy item.baby_girl.name=Baby Girl item.egg_male.name=Spawn Male Villager item.egg_female.name=Spawn Female Villager item.divorce_papers.name=Divorce Papers item.rose_gold_ingot.name=Rose Gold Ingot item.new_outfit.name=New Outfit item.tombstone.name=Tombstone item.rose_gold_dust.name=Rose Gold Dust item.gold_dust.name=Gold Dust item.whistle.name=Whistle item.villager_editor.name=Villager Editor item.egg_grim_reaper.name=Spawn Grim Reaper item.staff_of_life.name=Staff of Life item.book_death.name=Death, and How to Cure It! item.book_romance.name=Relationships and You item.book_family.name=Managing Your Family Vol. XI item.book_rose_gold.name=On Rose Gold item.book_infection.name=Beware the Infection! tile.rose_gold_ore.name=Rose Gold Ore tile.rose_gold_block.name=Rose Gold Block tile.mca:villager_spawner.name=Villager Spawner tile.mca:rose_gold_block.name=Rose Gold Block tile.mca:rose_gold_ore.name=Rose Gold Ore ################################ # Relations ################################ relation.spouse=Spouse relation.daughter=Daughter relation.son=Son ########################## # Reactions ########################## reaction.onhit1=Ow\! That hurt\! reaction.onhit2=I'll get you for that\! reaction.onhit3=Ouch\! Why did you hit me? reaction.onhit4=That hurts, stop it\! reaction.onhit5=Agh\! That really hurt\! reaction.onhit6=Hey\! What do you think you're doing?\! reaction.onhit7=*Oof*\! That better have been an accident\! reaction.ranaway1=That's right, you'd better run\! reaction.ranaway2=If you come back, I'm calling the guards\! reaction.ranaway3=Come back and fight like a man\! reaction.ranaway4=If I see you again, I'm going to punch you\! reaction.ranaway5=I knew you were afraid of me\! reaction.ranaway6=Why are you running? Get back here so I can hit you\! reaction.ranaway7=I'm going to hit you if I see you again\! reaction.ranaway8=I'll get my friends and beat you up\! reaction.drawnweapon1=No\! Please don't hurt me\! reaction.drawnweapon2=Stop\! No\! reaction.drawnweapon3=Someone help me\! reaction.drawnweapon4=They're going to kill me\! Someone help\! reaction.drawnweapon5=You can take whatever you want, just please don't hurt me\! reaction.drawnweapon6=I don't want to die\! Stay away\! reaction.drawnweapon7=Mother Notch, please help me\! ######################### # Messages for chores ######################### mining.search.none=There's no %v1% nearby. mining.search.nearby=There's some %v1% nearby... mining.search.value=There's some %v1% %a2% blocks away. farming.nohoe=I'll need to have a hoe in order to farm. fishing.norod=I don't have a fishing rod! fishing.nowater=I don't see any water nearby... fishing.finished=I've finished fishing. cooking.nofood=I don't have any food to cook. cooking.nofuel=I don't have any fuel. cooking.nofurnace=There's no furnace nearby. ################# # GUI ################################ gui.button.debug.startraid=Start Raid gui.button.debug.spawnguards=Spawn Guards gui.button.debug.selectnearestvillager=Get Nearest Villager gui.button.debug.startmining=Start Mining gui.button.debug.startfishing=Start Fishing gui.button.debug.startchopping=Start Chopping gui.button.debug.starthunting=Start Hunting gui.button.debug.startharvesting=Start Harvest gui.button.debug.unzombify=Unzombify gui.button.debug.zombify=Zombify gui.button.debug.marrytoplayer=Marry to Player gui.button.debug.rebuildvillage=Rebuild Village gui.button.debug.openinventory=Open Inventory gui.button.yes=Yes gui.button.no=No gui.button.ok=Ok gui.button.done=Done gui.button.random=Random gui.button.interact=Interact gui.button.follow=Follow Me gui.button.stay=Stay Here gui.button.move=Move Freely gui.button.trade=Trade gui.button.sethome=Home gui.button.gohome=Go Home gui.button.setworkplace=Workplace gui.button.sethangout=Hangout gui.button.location=Locations gui.button.ridehorse=Ride Horse gui.button.special=Special gui.button.procreate=Procreate gui.button.work=Work gui.button.inventory=Inventory gui.button.chat=Chat gui.button.joke=Joke gui.button.gift=Gift gui.button.shakehand=Shake Hand gui.button.tellstory=Tell Story gui.button.flirt=Flirt gui.button.hug=Hug gui.button.kiss=Kiss gui.button.prospecting=Prospecting gui.button.hunting=Hunting gui.button.cooking=Cooking gui.button.fishing=Fishing gui.button.chopping=Chopping gui.button.harvesting=Harvesting gui.button.start=Start gui.button.stop=Stop gui.button.havebaby=Have Baby gui.button.divorce=Divorce gui.button.asktomarry=Ask to Marry gui.button.hire=Hire gui.button.hired=Hired gui.button.accept=Accept gui.button.combat=Combat gui.button.extend=Extend gui.button.dismiss=Dismiss gui.button.divorcespouse=Divorce Spouse gui.button.resetbaby=Reset Baby gui.button.exit=Exit gui.button.back=Back gui.button.backarrow=<< gui.button.adoptbaby=Adopt Baby gui.button.revive=Revive gui.button.infected=Change Infection gui.button.gender=Change Gender gui.button.texture.set=Set Skin gui.button.texture.randomize=Randomize gui.button.profession.set=Set Career gui.button.profession.randomize=Randomize gui.button.stopworking=Stop Work gui.button.copyuuid=Copy UUID gui.button.call=Call gui.title.namebaby.male=It's a boy\! gui.title.namebaby.female=It's a girl\! gui.title.namebaby=Name your baby\: gui.title.tombstone=Enter tombstone text\: gui.title.editor=Villager Editor gui.title.whistle=Call Family Member gui.title.staffoflife=Select a Villager to Revive gui.label.you=You gui.label.readytogrow=Ready to grow! gui.label.owner=Owner gui.label.infected=Infected! gui.label.name=Name: gui.label.age=Age: gui.label.unnamed=Unnamed gui.label.rightclicktoname=Right-click to name gui.label.minute=Minute gui.label.minutes=Minutes gui.label.parent=Parent: gui.label.male=Male gui.label.female=Female gui.label.prospecting=Prospecting gui.label.harvesting=Harvesting gui.label.chopping=Chopping gui.label.hunting=Hunting gui.label.fishing=Fishing gui.label.staying=Staying gui.label.following=Following gui.info.gift.line1=Gift Available gui.info.gift.line2=(Click to take) spouse.chore.mining.orenotify=There's some %v2% nearby... spouse.chore.mining.nopick=I forgot my pickaxe, dear, did you bring an extra one? spouse.chore.chopping.noaxe=Oh, I thought we were going for a picnic. I didn't bring an axe... spouse.chore.fishing.norod=I'd love to! But, I can't find my fishing rod. spouse.chore.hunting.nosword=I broke my sword yesterday. Do you have another one? spouse.chore.harvesting.nohoe=Do you have an extra hoe I could use? childp.chore.mining.orenotify=I think there's some %v2% nearby... childp.chore.mining.nopick=I can't do that without a pickaxe! childp.chore.chopping.noaxe=I can't chop wood without an axe... childp.chore.fishing.norod=I can't fish without a fishing rod! childp.chore.hunting.nosword=Can you give me a sword first? childp.chore.harvesting.nohoe=I don't have a hoe to harvest with. child.chore.mining.orenotify=I think there's some %v2% nearby... child.chore.mining.nopick=I can't do that without a pickaxe! child.chore.chopping.noaxe=I can't chop wood without an axe... child.chore.fishing.norod=I can't fish without a fishing rod! child.chore.hunting.nosword=Can you give me a sword first? child.chore.harvesting.nohoe=I don't have a hoe to harvest with. adult.chore.mining.orenotify=Found something! There's some %v2% nearby. adult.chore.mining.nopick=I don't have a pickaxe anymore. adult.chore.chopping.noaxe=I don't have an axe anymore. adult.chore.fishing.norod=I don't have a fishing rod anymore. adult.chore.hunting.nosword=I lost my sword! Do you have another? adult.chore.harvesting.nohoe=I don't have a hoe to harvest with. gui.interact.label.married=Married to %v1% gui.interact.label.engaged=Engaged to %v1% gui.interact.label.notmarried=Not married gui.interact.label.parents=Parents: %v1% and %v2% gui.interact.label.gift=Gift available. Click to claim. spouse.interaction.marry.fail.marriedtogiver1=It's a pretty ring, but I am already married to you, silly. spouse.interaction.marry.fail.marriedtogiver2=We are already married. Did you forget? adult.interaction.marry.fail.marriedtoother1=I'm sorry, no...I'm already married. adult.interaction.marry.fail.marriedtoother2=Oh, I thought you knew...I'm already married to someone. adult.interaction.marry.fail.marriedtoother3=What?\! I'm already married\! adult.interaction.marry.fail.playermarried1=Uh...I see that ring on your finger. You're already married\! adult.interaction.marry.fail.playermarried2=Just what are you trying to do? You're already married\! adult.interaction.marry.fail.playermarried3=What? Really? I think you're married to someone else, aren't you? adult.interaction.marry.fail.playermarried4=I'm appalled\! You already have a spouse. adult.interaction.marry.fail.lowhearts1=What? No\! I don't like you\! adult.interaction.marry.fail.lowhearts2=Oh, pretty ring\! Oh wait...it's for me? Um...no. adult.interaction.marry.fail.lowhearts3=Is that for me? Sorry, I just don't know you enough. adult.interaction.marry.fail.lowhearts4=I'm flattered, but I don't really know you. spouse.interaction.engage.success1=Yes\! I will marry you\! I love you\! spouse.interaction.engage.success2=Of course I'll marry you\! spouse.interaction.engage.success3=About time...just kidding\! Love you\! spouse.interaction.engage.success4=Is...is this real? I mean, this moment, not the ring. But the ring is real, right? spouse.interaction.marry.success1=It's a dream come true\! I'll love you forever\! spouse.interaction.marry.success2=We're finally married\! Now what? spouse.interaction.marry.success3=I'm happy to be married to you, %v1%. spouse.interaction.marry.success4=I can't wait to start our life together\! adult.interaction.matchmaker.fail.married1=I am already married to someone. adult.interaction.matchmaker.fail.married2=I'm happily married, I do not want another spouse. adult.interaction.matchmaker.fail.married3=I don't want that - I'm already married. adult.interaction.matchmaker.fail.engaged1=I am engaged to someone already, I can't take that ring. adult.interaction.matchmaker.fail.engaged2=I've promised to marry someone else. adult.interaction.matchmaker.fail.engaged3=Oh, thanks but I think I'm okay. I'm already engaged to someone. adult.interaction.matchmaker.fail.needtwo1=Don't you need two rings to arrange a marriage? adult.interaction.matchmaker.fail.needtwo2=Oh, okay\! But you need two rings first. adult.interaction.matchmaker.fail.needtwo3=My spouse and I will both need a ring, but you only have one. adult.interaction.matchmaker.fail.novillagers1=I don't see anyone close by. Who did you want me to marry? adult.interaction.matchmaker.fail.novillagers2=I just don't know...move me closer to the one you think is right for me. adult.interaction.matchmaker.fail.novillagers3=Oh, but there doesn't seem to be anyone close by. Who should I marry? adult.interaction.sethome.success1=Okay, this will be my new home point. adult.interaction.sethome.success2=I understand, I'll be sleeping here at night. adult.interaction.sethome.success3=Sure thing, %v1%. spouse.interaction.sethome.success1=I really like this place, good job %v1%! spouse.interaction.sethome.success2=This is like a dream home! childp.interaction.sethome.success1=Okay fine, where's my room? childp.interaction.sethome.success2=This is cool I guess. Can I go play now? childp.interaction.sethome.success3=Okay, but I want the biggest room! child.interaction.sethome.success2=This is cool I guess. adult.interaction.sethome.fail1=This doesn't look like a safe home point for me. There's some %v1% in the way. adult.interaction.sethome.fail2=Is there another place nearby? There's some %v1% in the way. adult.interaction.sethome.fail3=I can't have my home point here. There's some %v1% in the way. adult.interaction.setworkplace.success1=Sure thing, %v1%. spouse.interaction.setworkplace.success1=I really like this place. child.interaction.setworkplace.success1=Okay fine! childp.interaction.setworkplace.success1=Okay fine! adult.interaction.sethangout.success1=This is my favorite spot. I'm often here in the evening. spouse.interaction.sethangout.success1=I really like this place. child.interaction.sethangout.success1=Okay fine! I will play here before bedtime. childp.interaction.sethangout.success1=Okay fine! I will play here before bedtime. adult.interaction.gohome.success1=Alright, I'll go there immediately! adult.interaction.gohome.success2=Sure, I'll go home now. adult.interaction.gohome.success3=I'm going home. Goodbye! spouse.interaction.gohome.success1=Sure, dear, I'll head home now. spouse.interaction.gohome.success2=See you there, dear! childp.interaction.gohome.success1=See ya! childp.interaction.gohome.success2=Okay! Bye! child.interaction.gohome.success1=Okay! I think I remember where I live... adult.interaction.gohome.fail.nohome=I don't have a home... spouse.interaction.gohome.fail.nohome=Remind me again where our house was? child.interaction.gohome.fail.nohome=I don't remember where I live... childp.interaction.gohome.fail.nohome=I don't remember where home is! We move too much! child.interaction.ridehorse.fail.notnearby=Where are the horses? I want to ride! childp.interaction.ridehorse.fail.notnearby=Where is my horse? I hope I didn't lose it again... adult.interaction.ridehorse.fail.notnearby=I don't see any rideable horses nearby. spouse.interaction.ridehorse.fail.notnearby=Where is my horse, dear? I can't find it. spouse.interaction.procreate.fail.hasbaby1=We already have a baby...you didn't lose it did you?! spouse.interaction.procreate.fail.hasbaby2=...you lost baby Joby didn't you? Wait...was his name Joby? spouse.interaction.procreate.fail.lowhearts1=Spend more time with me! I'm not ready for a child. spouse.interaction.procreate.fail.lowhearts2=Hmm...not just yet. I think we need to spend more time together first. notify.spouseendedmarriage=%Name% has ended their marriage with you. notify.spousedied=Your spouse %v1% has died by %v2% notify.childdied=Your child %v1% has died by %v2% notify.child.grownup=%v1% has grown into an adult! notify.revival.disabled=Revivals have been disabled by the server administrator. notify.trading.disabled=Trading is disabled by the server administrator. gift.cake.fail=I will only eat cake if my spouse is nearby...please find them! ################################## # Responses to interactions ################################## adult.gift.fail1=This isn't a good gift... adult.gift.fail2=What made you think that I would like this? adult.gift.fail3=No thanks. adult.gift.fail4=I don't want that, why would I? adult.gift.fail5=Why are you giving me that? adult.gift.fail6=Is this supposed to be a gift? No thanks. adult.gift.good1=How considerate\! Thank you. adult.gift.good2=Thanks\! adult.gift.good3=How thoughtful\! adult.gift.good4=Oh, I love these\! adult.gift.good5=A gift? For me? How nice\! adult.gift.better1=Hey, this is pretty cool\! adult.gift.better2=Thanks, friend\! adult.gift.better3=%v1%, you're such a good friend\! adult.gift.better4=Oh wow, I actually needed one of these\! adult.gift.better5=This is a pretty good gift\! adult.gift.best1=I...I don't know what to say. Thank you so much, %v1%\! adult.gift.best2=How did you...nevermind, this is amazing\! adult.gift.best3=Oh wow, I've always wanted one of these\! adult.gift.best4=This is fantastic\! I'll put it to good use. adult.gift.best5=Thank you so much. I will remember this forever. adult.chat.success1=Man, cookies and milk does sound delicious right now. adult.chat.success2=Yes, I suppose the weather is nice today. adult.chat.success3=I'm doing just fine\! Hit my toe when I woke up, though. adult.chat.success4=An apple a day keeps the zombies away\! adult.chat.success5=My dream is to build my own village, but I'm so lazy. adult.chat.success6=I think I saw %Supporter% the other day in Diamond armor. adult.chat.success7=My friend %Supporter% told me that they found a chest full of diamonds yesterday! adult.chat.fail1=Did you seriously just say that? adult.chat.fail2=I don't believe it exploded on its own. adult.chat.fail3=You know, you're not that cool. adult.chat.fail4=Show off. adult.chat.fail5=You should be thrown in a dungeon\! adult.joke.success1=Haha\! Serves that Skelly right\! adult.joke.success2=*Laughs* That's hilarious\! adult.joke.success3=That's funny\! Did you hear the one about the cows? adult.joke.success4=Unfortunate for the sheep to lose its wool, but funny\! adult.joke.success5=That's the best I have ever heard\! adult.joke.success6=You might be funnier than %Supporter%\! adult.joke.fail1=Don't speak about my pig like that\! adult.joke.fail2=Ha. Ha. Not funny. adult.joke.fail3=Ah, you're not the funniest in town. adult.joke.fail4=That's low. adult.joke.fail5=You shouldn't joke about that. adult.shakehand.success1=You have a nice grip\! adult.shakehand.success2=Your grip shows me you have great power\! adult.shakehand.success3=Wow, you're so polite\! adult.shakehand.success4=Good day\! adult.shakehand.success5=Why, hello there\! adult.shakehand.fail1=Seriously? After you slaughtered the cow? adult.shakehand.fail2=Um, no that's okay. adult.shakehand.fail3=I'm not a stranger, you don't have to be so polite. adult.shakehand.fail4=Wow really? This isn't like you. adult.shakehand.fail5=Go away. adult.tellstory.success1=Really? I can't believe that all happened\! adult.tellstory.success2=I wish I was brave enough to take on a creeper. adult.tellstory.success3=That was a really good story\! Is it original? adult.tellstory.success4=All of that happened yesterday? No way\! adult.tellstory.success5=I was near there yesterday, I can't believe I didn't hear this already. adult.tellstory.success6=Haha! That definitely sounds like %Supporter%! Such an awesome person. adult.tellstory.success7=I've heard the Legend of %Supporter% almost a million times. Tell me again! adult.tellstory.fail1=*Ahem* That's my mother you're talking about. adult.tellstory.fail2=This is why the village talks about you. adult.tellstory.fail3=I don't get it... adult.tellstory.fail4=You're terrible\! Creepers have feelings too\! adult.tellstory.fail5=How could you kill a poor sheep?\! adult.flirt.success1=You're sooo brave\! adult.flirt.success2=Oh, you\! Stop being so cute\! adult.flirt.success3=*Blushes* Do you mean it? adult.flirt.success4=Oh, my... adult.flirt.success5=That was so adorable\! You had me at "hello"\! adult.flirt.fail1=If you mean that, then prove it. adult.flirt.fail2=Aw.... Wait, you told the baker the same thing\! adult.flirt.fail3=Not in a million years. adult.flirt.fail4=Pathetic much? adult.flirt.fail5=A zombie has a better chance than you. adult.hug.success1=Long time no see\! adult.hug.success2=Thank you, I needed that. adult.hug.success3=At least one thing made my day today. adult.hug.success4=You're as snuggly as a sheep\! adult.hug.fail1=You're covered in soot and mud\! adult.hug.fail2=No thanks. adult.hug.fail3=Uh, why? adult.hug.fail4=After you called me a dinosaur last week? No. adult.hug.fail5=Quite frankly, you don't deserve a hug after you did that. adult.kiss.success1=I wish this moment would last forever. adult.kiss.success2=I think I love you... adult.kiss.success3=Mmm, tastes like pumpkin pie\! adult.kiss.fail1=Not if someone can see. adult.kiss.fail2=You call that a kiss? adult.kiss.fail3=Ash kisses better than you. adult.kiss.fail4=Two words... breath mints\! adult.kiss.fail5=Thank you? adult.greeting1=Why, hello there\! adult.greeting2=Hey\! How are you today? adult.greeting3=Hey, good to see you\! adult.greeting4=What's going on with you today? adult.greeting5=How are you today? child.chat.success1=I heard stories about you\! Are you a hero? child.chat.success2=Hi. I was going to go try and climb to the roof. child.chat.success3=Do you wanna go burn stuff with me? child.chat.success4=I'm going to be a hunter like you and kill many things\! child.chat.success5=Hi\! What are you doing today? I'm going swimmin'\! child.chat.fail1=If you don't give me cookies I'll hold my breath. child.chat.fail2=My parents said not to talk to you, that you're bad. child.chat.fail3=*Laughs* You look smelly\! child.chat.fail4=Oh yeah? Well I'm gonna egg your house\! child.chat.fail5=Lalala, I'm not listening\! Lalala. child.joke.success1=You're funnier than daddy\! child.joke.success2=Tell me another one\! child.joke.success3=You're the funniest person alive\! child.joke.success4=I'm tellin' my momma that one\! *Laughs* child.joke.success5=It should eat a leaf\! child.joke.fail1=I don't get it. child.joke.fail2=You're not funny. Really. child.joke.fail3=You need to stop... child.joke.fail4=But, who's apple? child.joke.fail5=Don't be mean\! child.shakehand.success1=Hiya\! Someone I know likes you... child.shakehand.success2=Dad said this is a very nice thing to do. child.shakehand.success3=Now high five\! Down low... too slow\! child.shakehand.success4=Hi stranger\! child.shakehand.success5=*Giggles* I just cleaned a cow with this hand. child.shakehand.fail1=Stranger danger... child.shakehand.fail2=Mom, dad\! This person is trying to kidnap me\! child.shakehand.fail3=Don't touch me I'm famous\! child.shakehand.fail4=Ew, your hand has black stuff on it. child.shakehand.fail5=I'll only shake your hand if you give me a diamond. child.tellstory.success1=Wow\! You're a beast\! child.tellstory.success2=I want to be just like you when I grow up. Shh, don't tell dad. child.tellstory.success3=Can you adopt me?\! You're awesome\! child.tellstory.success4=I went fishing and almost drowned. child.tellstory.success5=Does this mean I can take whatever I want? I mean, "borrow?" child.tellstory.success6=Tell me again about %Supporter%!! child.tellstory.fail1=You're a meanie\! child.tellstory.fail2=I'm telling my mom what you said about her... child.tellstory.fail3=I believe you're speaking about my grandpa... child.tellstory.fail4=You're nothing but a scaredycat like dad said\! child.tellstory.fail5=How could you kill a poor chicken? child.greeting1=Hi, who are you? child.greeting2=Hi, what's your name? child.greeting3=Eek\! You look scary\! child.gift.fail1=Ew, I don't like this\! child.gift.fail2=Yuck\! I don't want this. child.gift.fail3=Why did you bring me this? It's dumb\! child.gift.fail4=I don't even know what this is\! child.gift.good1=Is it...is it all mine? child.gift.good2=Is this really for me? child.gift.good3=This is cool\! child.gift.better1=Awesome\! I'm going to show this to all my friends. child.gift.better2=You found it\! I lost this a few minutes ago. child.gift.better3=My friend stole one of these from me. Did you beat him up for me? child.gift.best1=%v1%, you give the best presents\! child.gift.best2=Finally\! My friend will stop bragging now. child.gift.best3=Wow\! Where did you get this thing? child.gift.best4=My Dad has one of these. Now I have one too\! childp.chat.success1=Oh, I was just going to go explorin' later. childp.chat.success2=Can we go camping? Please?\! childp.chat.success3=Hi, can you make me a cake? childp.chat.success4=Can I have my own room away from our house? That would be cool\! childp.chat.success5=Let's move into a cave\! That sounds so fun\! childp.chat.fail2=I don't think I'd like that very much. childp.chat.fail3=Is that why I've heard so much about "divorce"? What does that mean? childp.chat.fail4=I want a new daddy. childp.chat.fail5=I don't want a baby sister. childp.joke.success1=*Laughs* Tell that one again\! childp.joke.success2=I've got to tell my friend that one\! childp.joke.success3=How did the creeper explode?\! childp.joke.success4=*Laughs*Why is there no longer 3 of them? childp.joke.success5=*Laughs* ... *Laughs*... *Laughs* childp.joke.fail1=I thought you were funny, though... childp.joke.fail2=I like knock knock jokes better. childp.joke.fail3=I don't get it, that was dumb. childp.joke.fail4=*Yawn* My friend's dad is cooler and funnier than you. childp.joke.fail5=I'd rather have cake. childp.shakehand.success1=Why do I need to learn this stuff? childp.shakehand.success2=I heard that this is a polite thing to do. childp.shakehand.success3=I'm gonna be just like you when I grow up\! childp.shakehand.success4=Can I have cake now? childp.shakehand.success5=I don't get it, but okay\! childp.shakehand.fail1=I spit on my hand. childp.shakehand.fail2=You're such an old person. childp.shakehand.fail3=Only losers shake hands. childp.shakehand.fail4=I'll shake your hand if you give me cake. childp.shakehand.fail5=No, you'll slip and hit me. childp.tellstory.success1=What!? You really did that?\! But...what happened to your friend? childp.tellstory.success2=I want to explore a cave, too\! Let's go\! childp.tellstory.success3=One day I'll kill more creepers than you\! childp.tellstory.success4=Oh, oh, oh\! Can we climb a tree, too?\! childp.tellstory.success5=Did the lava hurt? childp.tellstory.fail1=I don't want to hear about grandma. childp.tellstory.fail2=You always say that. I just want a pet. childp.tellstory.fail3=You're just fibbing. I don't belive that. childp.tellstory.fail4=You said you didn't eat the cake and cookies... childp.tellstory.fail5=Someone said you were a bad person, and I believe them\! childp.hug.success1=*Kisses* You're the best ever\! childp.hug.success2=I'm going to be as strong as you are one day\! childp.hug.success3=hug anymore? childp.hug.success4=I love hugs\! You're soft and warm\! childp.hug.fail1=I'm too old for hugs\! childp.hug.fail2=Stop it\! I don't want people to see\! childp.hug.fail3=Go away, you're so annoying\! childp.hug.fail4=Just leave me alone or give me some cookies\! childp.hug.fail5=I'd rather hug a skeleton. childp.greeting1=Hey there\! childp.greeting2=Hey, what's going on? childp.greeting3=What are you doing? childp.greeting4=Where are you going? childp.gift.fail1=This...is a really bad gift. childp.gift.fail2=Ew, I've gotten so much better before! childp.gift.fail3=Didn't you give me this like, last year? childp.gift.fail4=I could get this easily, no thanks. childp.gift.good1=Oh, cool\! Thank you! childp.gift.good2=Is it my birthday? This is awesome! childp.gift.good3=This is much better than the last gift I got\! childp.gift.good4=Woo hoo\! It's mine, all mine\! childp.gift.good5=Can I...can I eat it? childp.gift.better1=For me? For free?\! childp.gift.better2=Ooh\! Shiny\! childp.gift.better3=I really like this one, can I have another? childp.gift.better4=All of my friends will be jealous now\! childp.gift.better5=This is so cool! I've wanted one of these forever! childp.gift.best1=This must have cost a fortune\! childp.gift.best2=I knew you would get me one of these. I just knew it\! childp.gift.best3=Yay\! I have the best parents in the world\! childp.gift.best4=This is so amazing\! I can't believe this is all mine\! childp.gift.best5=Thank you so much\! You're the best ever\! spouse.chat.success1=I cleaned the entire house. How was your day? spouse.chat.success2=Honey, let's go camping sometime. Doesn't that sound like fun? spouse.chat.success3=So today I saw a spider. It was huge so I ran away. spouse.chat.success4=We should build a new house together\! spouse.chat.success5=I almost walked into a lava pit the other day. That wouldn't have been good\! spouse.chat.fail1=I know we're not the poorest family, but... spouse.chat.fail2=I love being around you but I need some space. spouse.chat.fail3=Sometimes I wish I had my own "cave" to escape from you and everyone. spouse.chat.fail4=Go away, I'm not in the mood. spouse.chat.fail5=Where have you been? Are you seeing someone behind my back? spouse.joke.success1=*Laughs* I married you for your humor\! spouse.joke.success2=You should throw an egg at him next time\! spouse.joke.success3=Then the wolf fell in love with the sheep. spouse.joke.success4=That never gets old\! spouse.joke.success5=Here's one for you... How many chickens does a creeper blow up? spouse.joke.fail1=Lame... spouse.joke.fail2=Sweetheart, you're not funny. spouse.joke.fail3=Ha...Ha...Ha...Not funny. spouse.joke.fail4=You need to erase that from your mind. spouse.joke.fail5=Okay... spouse.shakehand.success1=Your hand is so soft\! spouse.shakehand.success2=Our hands fit perfectly together. spouse.shakehand.success3=One day people will forget to shake hands. spouse.shakehand.success4=Our children will need to be this polite. spouse.shakehand.success5=*Continues to shake hand* Tell me when to stop\! spouse.shakehand.fail1=shakehand? How about a kiss, instead? spouse.shakehand.fail2=*Squeezes hand hard* spouse.shakehand.fail3=Your hand is nasty, no way. spouse.shakehand.fail4=They have germs on them. spouse.shakehand.fail5=Why don't you get a decent job instead of shaking my hand? spouse.tellstory.success1=Let's not tell our children that one... spouse.tellstory.success2=You were so rebellious\! I love it\! spouse.tellstory.success3=Did you ever tell your parents about losing their rings? spouse.tellstory.success4=It was that moment when I fell in love with you\! spouse.tellstory.success5=Wow, you're the best hunter ever\! spouse.tellstory.fail1=Talk to me when you kill something other than a harmless cow. spouse.tellstory.fail2=Don't do something that reckless\! spouse.tellstory.fail3=You have a family to think about\! spouse.tellstory.fail4=...If you liked them why didn't you marry them, instead? spouse.tellstory.fail5=Why did you wear the pink fluffy underwear? Whose were they? spouse.flirt.success1=*Blushes* Well, how about we do something like that, then\! spouse.flirt.success2=Aw, you said that when we first met. spouse.flirt.success3=Baby, you're so cute\! spouse.flirt.success4=You bet I am\! spouse.flirt.success5=*Winks* You still got it\! spouse.flirt.fail1=*Sighs* spouse.flirt.fail2=This one is getting old... like you. spouse.flirt.fail3=We're married, we don't have to do this anymore. spouse.flirt.fail4=Talk to the tree, it cares more. spouse.flirt.fail5=Yeah, yeah... What was it you were saying? spouse.hug.success1=I love being entangled in your arms\! spouse.hug.success2=Wait, don't leave... you're warm. spouse.hug.success3=Would you rather only being able to hug or kiss? spouse.hug.success4=*Kisses* spouse.hug.success5=Let's stay like this forever\! spouse.hug.fail1=Why don't you go hug your ex? spouse.hug.fail2=No thanks. spouse.hug.fail3=Man, you stink. spouse.hug.fail4=What do you want? spouse.hug.fail5=Huge someone else. spouse.kiss.success1=I fall in love all over again when our lips meet\! spouse.kiss.success2=Time stops ticking when I'm with you. spouse.kiss.success3=Sweet as cake\! spouse.kiss.success4=I love you, baby\! spouse.kiss.success5=I wouldn't trade you for anyone in the world\! spouse.kiss.fail1=Not where someone can see us... spouse.kiss.fail2=We don't have to if you don't want to. spouse.kiss.fail3=Your breath smells like wolf kibble. spouse.kiss.fail4=Go take a drink from the lake. spouse.kiss.fail5=Now that we're married I can tell you how lousy you are at kissing. spouse.greeting1=Hi honey, where have you been? spouse.greeting2=Hello dear, how is your day going? spouse.greeting3=Oh, %v1%\! You look tired. spouse.greeting4=Hey %v1%\! You look hungry. Would you like me to cook something? spouse.greeting5=%v1%, you're back\! I missed you. spouse.lowhearts.greeting1=There you are. Where did you go? You never tell me anything anymore. spouse.lowhearts.greeting2=Are you going to say hi to me this time? spouse.lowhearts.greeting3=Um, hi! I still exist, you know! spouse.lowhearts.greeting4=%v1%, are you ignoring me on purpose? spouse.lowhearts.greeting5=I'm starting to feel like you don't pay attention to me. spouse.endmarriage1=I've had it. You don't treat me well enough. I'm leaving you! spouse.endmarriage2=I'm leaving. Forever! Don't look for me. spouse.endmarriage3=I'm sorry - I thought we could work things out, but it's not working for me. Goodbye. spouse.endmarriage4=%v1%, this is goodbye. Don't try to follow me. spouse.gift.fail1=Oh honey...this is just terrible. spouse.gift.fail2=Um, is this supposed to be a gift for me? spouse.gift.fail3=Throw away your own junk\! Oh, this was a gift?...sorry. spouse.gift.fail4=I thought you knew me better than that. I hate these. spouse.gift.good1=%v1%, you're so sweet. spouse.gift.good2=Ah\! You're too good to me. spouse.gift.good3=This is unexpected, thank you, dear\! spouse.gift.good4=Aw, how sweet of you. spouse.gift.good5=Thanks, hun\! spouse.gift.better1=Oh wow, this is actually really nice\! spouse.gift.better2=I love it\! Thank you\! spouse.gift.better3=This is amazing, dear\! spouse.gift.better4=You got this for me? How sweet\! spouse.gift.better5=Oh, thank you %v1%\! spouse.gift.best1=Oh %v1%, I love you\! spouse.gift.best2=You are *way* too good to me\! spouse.gift.best3=This must have been extremely expensive\! Thank you\! spouse.gift.best4=I...can't believe you'd get me something so thoughtful\! ================================================ FILE: src/main/resources/assets/mca/lang/names.lang ================================================ name.male1=Aaron name.male2=Abdul name.male3=Abe name.male4=Abel name.male5=Abraham name.male6=Abram name.male7=Adalberto name.male8=Adam name.male9=Adan name.male10=Adolfo name.male11=Adolph name.male12=Adrian name.male13=Agustin name.male14=Ahmad name.male15=Ahmed name.male16=Alan name.male17=Alaric name.male18=Albert name.male19=Alberto name.male20=Alden name.male21=Aldo name.male22=Alec name.male23=Alejandro name.male24=Alex name.male25=Alexander name.male26=Alexis name.male27=Alfonso name.male28=Alfonzo name.male29=Alfred name.male30=Alfredo name.male31=Ali name.male32=Allan name.male33=Allen name.male34=Alonso name.male35=Alonzo name.male36=Alphonse name.male37=Alphonso name.male38=Alton name.male39=Alva name.male40=Alvaro name.male41=Alvin name.male42=Amado name.male43=Ambrose name.male44=Amos name.male45=Anderson name.male46=Andre name.male47=Andrea name.male48=Andreas name.male49=Andres name.male50=Andrew name.male51=Andy name.male52=Angel name.male53=Angelo name.male54=Anibal name.male55=Anthony name.male56=Antoine name.male57=Anton name.male58=Antone name.male59=Antonia name.male60=Antonio name.male61=Antony name.male62=Antwan name.male63=Archie name.male64=Arden name.male65=Ariel name.male66=Arlen name.male67=Arlie name.male68=Armand name.male69=Armando name.male70=Armon name.male71=Arnold name.male72=Arnoldo name.male73=Arnulfo name.male74=Aron name.male75=Arron name.male76=Art name.male77=Arthur name.male78=Arturo name.male79=Asa name.male80=Ashley name.male81=Aubrey name.male82=August name.male83=Augustine name.male84=Augustus name.male85=Aurelio name.male86=Austin name.male87=Avery name.male88=Ayden name.male89=Bailey name.male90=Barney name.male91=Barrett name.male92=Barry name.male93=Bart name.male94=Barton name.male95=Basil name.male96=Beau name.male97=Ben name.male98=Benedict name.male99=Benito name.male100=Benjamin name.male101=Bennett name.male102=Bennie name.male103=Benny name.male104=Benton name.male105=Bernard name.male106=Bernardo name.male107=Bernie name.male108=Berry name.male109=Bert name.male110=Bertram name.male111=Bill name.male112=Billie name.male113=Billy name.male114=Blaine name.male115=Blair name.male116=Blake name.male117=Bob name.male118=Bobbie name.male119=Bobby name.male120=Booker name.male121=Boris name.male122=Boyce name.male123=Boyd name.male124=Bracken name.male125=Brad name.male126=Bradford name.male127=Bradley name.male128=Bradly name.male129=Brady name.male130=Brain name.male131=Branden name.male132=Brandon name.male133=Brant name.male134=Brayden name.male135=Brendan name.male136=Brendon name.male137=Brent name.male138=Brenton name.male139=Bret name.male140=Brett name.male141=Brian name.male142=Brice name.male143=Britt name.male144=Brock name.male145=Broderick name.male146=Brooks name.male147=Bruce name.male148=Bruno name.male149=Bryan name.male150=Bryant name.male151=Bryce name.male152=Bryon name.male153=Bryson name.male154=Buck name.male155=Bud name.male156=Buddy name.male157=Buford name.male158=Burl name.male159=Burt name.male160=Burton name.male161=Buster name.male162=Byron name.male163=Caleb name.male164=Calvin name.male165=Cameron name.male166=Carey name.male167=Carl name.male168=Carlo name.male169=Carlos name.male170=Carlton name.male171=Carmelo name.male172=Carmen name.male173=Carmine name.male174=Carol name.male175=Carrol name.male176=Carroll name.male177=Carson name.male178=Carter name.male179=Cary name.male180=Casey name.male181=Cason name.male182=Cecil name.male183=Cedric name.male184=Cedrick name.male185=Cesar name.male186=Chad name.male187=Chadwick name.male188=Chance name.male189=Chancey name.male190=Chang name.male191=Charles name.male192=Charley name.male193=Charlie name.male194=Chas name.male195=Chase name.male196=Chauncey name.male197=Chester name.male198=Chet name.male199=Chi name.male200=Chong name.male201=Chris name.male202=Christian name.male203=Christop name.male204=Christoper name.male205=Christopher name.male206=Chuck name.male207=Chung name.male208=Clair name.male209=Clarence name.male210=Clark name.male211=Claud name.male212=Claude name.male213=Claudio name.male214=Clay name.male215=Clayton name.male216=Clement name.male217=Clemente name.male218=Cleo name.male219=Cletus name.male220=Cleveland name.male221=Cliff name.male222=Clifford name.male223=Clifton name.male224=Clint name.male225=Clinton name.male226=Clyde name.male227=Cody name.male228=Colby name.male229=Cole name.male230=Coleman name.male231=Colin name.male232=Collin name.male233=Colton name.male234=Columbus name.male235=Connie name.male236=Connor name.male237=Conrad name.male238=Cordell name.male239=Corey name.male240=Coriander name.male241=Cornelius name.male242=Cornell name.male243=Cortez name.male244=Cory name.male245=Courtney name.male246=Coy name.male247=Craig name.male248=Cristobal name.male249=Cristopher name.male250=Cruz name.male251=Curt name.male252=Curtis name.male253=Cyril name.male254=Cyrus name.male255=Dale name.male256=Dallas name.male257=Dallis name.male258=Dalton name.male259=Damian name.male260=Damien name.male261=Damion name.male262=Damon name.male263=Dan name.male264=Dana name.male265=Dane name.male266=Danial name.male267=Daniel name.male268=Danilo name.male269=Dannie name.male270=Danny name.male271=Dante name.male272=Darell name.male273=Daren name.male274=Darin name.male275=Dario name.male276=Darius name.male277=Darnell name.male278=Daron name.male279=Darrel name.male280=Darrell name.male281=Darren name.male282=Darrick name.male283=Darrin name.male284=Darron name.male285=Darryl name.male286=Darwin name.male287=Daryl name.male288=Dave name.male289=David name.male290=Davis name.male291=Dean name.male292=Deandre name.male293=Deangelo name.male294=Dee name.male295=Del name.male296=Delbert name.male297=Delmar name.male298=Delmer name.male299=Demarcus name.male300=Demetrius name.male301=Denis name.male302=Dennis name.male303=Denny name.male304=Denver name.male305=Deon name.male306=Derek name.male307=Derick name.male308=Derrick name.male309=Deshawn name.male310=Desmond name.male311=Devin name.male312=Devon name.male313=Dewayne name.male314=Dewey name.male315=Dewitt name.male316=Dexter name.male317=Dick name.male318=Diego name.male319=Dillon name.male320=Dino name.male321=Dion name.male322=Dirk name.male323=Domenic name.male324=Domingo name.male325=Dominic name.male326=Dominick name.male327=Dominique name.male328=Don name.male329=Donald name.male330=Dong name.male331=Donn name.male332=Donnell name.male333=Donnie name.male334=Donny name.male335=Donovan name.male336=Donte name.male337=Dorian name.male338=Dorsey name.male339=Doug name.male340=Douglas name.male341=Douglass name.male342=Doyle name.male343=Draven name.male344=Drew name.male345=Duane name.male346=Dudley name.male347=Duncan name.male348=Dustin name.male349=Dusty name.male350=Dwain name.male351=Dwayne name.male352=Dwight name.male353=Dylan name.male354=Earl name.male355=Earle name.male356=Earnest name.male357=Eddie name.male358=Eddy name.male359=Edgar name.male360=Edgardo name.male361=Edison name.male362=Edmond name.male363=Edmund name.male364=Edmundo name.male365=Eduardo name.male366=Edward name.male367=Edwardo name.male368=Edwin name.male369=Efrain name.male370=Efren name.male371=Elbert name.male372=Elden name.male373=Eldon name.male374=Eldridge name.male375=Eli name.male376=Elias name.male377=Elijah name.male378=Eliseo name.male379=Elisha name.male380=Elliot name.male381=Elliott name.male382=Ellis name.male383=Ellsworth name.male384=Elmer name.male385=Elmo name.male386=Eloy name.male387=Elroy name.male388=Elton name.male389=Elvin name.male390=Elvis name.male391=Elwood name.male392=Emanuel name.male393=Emerson name.male394=Emery name.male395=Emil name.male396=Emile name.male397=Emilio name.male398=Emit name.male399=Emmanuel name.male400=Emmett name.male401=Emmitt name.male402=Emory name.male403=Enoch name.male404=Enrique name.male405=Erasmo name.male406=Eric name.male407=Erich name.male408=Erick name.male409=Erik name.male410=Erin name.male411=Ernest name.male412=Ernesto name.male413=Ernie name.male414=Errol name.male415=Ervin name.male416=Erwin name.male417=Esteban name.male418=Ethan name.male419=Eugene name.male420=Eugenio name.male421=Eusebio name.male422=Evan name.male423=Everett name.male424=Everette name.male425=Ezekiel name.male426=Ezequiel name.male427=Ezra name.male428=Fabian name.male429=Faustino name.male430=Fausto name.male431=Federico name.male432=Felipe name.male433=Felix name.male434=Felton name.male435=Ferdinand name.male436=Fermin name.male437=Fernando name.male438=Fidel name.male439=Filiberto name.male440=Fletcher name.male441=Florencio name.male442=Florentino name.male443=Floyd name.male444=Ford name.male445=Forest name.male446=Forrest name.male447=Foster name.male448=Frances name.male449=Francesco name.male450=Francis name.male451=Francisco name.male452=Frank name.male453=Frankie name.male454=Franklin name.male455=Franklyn name.male456=Fred name.male457=Freddie name.male458=Freddy name.male459=Frederic name.male460=Frederick name.male461=Fredric name.male462=Fredrick name.male463=Freeman name.male464=Fritz name.male465=Gabriel name.male466=Gage name.male467=Gail name.male468=Gale name.male469=Galen name.male470=Garfield name.male471=Garland name.male472=Garret name.male473=Garrett name.male474=Garry name.male475=Garth name.male476=Gary name.male477=Gaston name.male478=Gavin name.male479=Gayle name.male480=Gaylord name.male481=Genaro name.male482=Gene name.male483=Geoffrey name.male484=George name.male485=Gerald name.male486=Geraldo name.male487=Gerard name.male488=Gerardo name.male489=German name.male490=Gerry name.male491=Gil name.male492=Gilbert name.male493=Gilberto name.male494=Gino name.male495=Giovanni name.male496=Giuseppe name.male497=Glen name.male498=Glenn name.male499=Gonzalo name.male500=Gordon name.male501=Grady name.male502=Graham name.male503=Graig name.male504=Grant name.male505=Granville name.male506=Grayson name.male507=Greg name.male508=Gregg name.male509=Gregorio name.male510=Gregory name.male511=Grover name.male512=Guadalupe name.male513=Guillermo name.male514=Gus name.male515=Gustavo name.male516=Guy name.male517=Hai name.male518=Hal name.male519=Hank name.male520=Hans name.male521=Harlan name.male522=Harland name.male523=Harley name.male524=Harold name.male525=Harris name.male526=Harrison name.male527=Harry name.male528=Harvey name.male529=Hassan name.male530=Hayden name.male531=Haywood name.male532=Heath name.male533=Hector name.male534=Henry name.male535=Herb name.male536=Herbert name.male537=Heriberto name.male538=Herman name.male539=Herschel name.male540=Hershel name.male541=Hilario name.male542=Hilton name.male543=Hipolito name.male544=Hiram name.male545=Hobert name.male546=Hollis name.male547=Homer name.male548=Hong name.male549=Horace name.male550=Horacio name.male551=Hosea name.male552=Houston name.male553=Howard name.male554=Hoyt name.male555=Hubert name.male556=Huey name.male557=Hugh name.male558=Hugo name.male559=Humberto name.male560=Hung name.male561=Hunter name.male562=Hyman name.male563=Ian name.male564=Ignacio name.male565=Ike name.male566=Ira name.male567=Irvin name.male568=Irving name.male569=Irwin name.male570=Isaac name.male571=Isaiah name.male572=Isaias name.male573=Isiah name.male574=Isidro name.male575=Ismael name.male576=Israel name.male577=Isreal name.male578=Issac name.male579=Ivan name.male580=Ivory name.male581=Jacinto name.male582=Jack name.male583=Jackie name.male584=Jackson name.male585=Jacob name.male586=Jacques name.male587=Jae name.male588=Jaime name.male589=Jake name.male590=Jamaal name.male591=Jamal name.male592=Jamar name.male593=Jame name.male594=Jamel name.male595=James name.male596=Jamey name.male597=Jamie name.male598=Jamison name.male599=Jan name.male600=Jared name.male601=Jarod name.male602=Jarred name.male603=Jarrett name.male604=Jarrod name.male605=Jarvis name.male606=Jason name.male607=Jasper name.male608=Javier name.male609=Jaxon name.male610=Jay name.male611=Jaylen name.male612=Jaylon name.male613=Jayson name.male614=Jean name.male615=Jed name.male616=Jeferson name.male617=Jeff name.male618=Jefferey name.male619=Jefferson name.male620=Jeffery name.male621=Jeffrey name.male622=Jeffry name.male623=Jerald name.male624=Jeramy name.male625=Jere name.male626=Jeremiah name.male627=Jeremy name.male628=Jerimiah name.male629=Jermaine name.male630=Jerold name.male631=Jerome name.male632=Jeromy name.male633=Jerrell name.male634=Jerrod name.male635=Jerrold name.male636=Jerry name.male637=Jess name.male638=Jesse name.male639=Jessie name.male640=Jesus name.male641=Jewel name.male642=Jewell name.male643=Jim name.male644=Jimmie name.male645=Jimmy name.male646=Joan name.male647=Joaquin name.male648=Jody name.male649=Joe name.male650=Joel name.male651=Joesph name.male652=Joey name.male653=John name.male654=Johnathan name.male655=Johnathon name.male656=Johnie name.male657=Johnnie name.male658=Johnny name.male659=Johnson name.male660=Jon name.male661=Jonah name.male662=Jonas name.male663=Jonathan name.male664=Jonathon name.male665=Jordan name.male666=Jordon name.male667=Jorge name.male668=Jose name.male669=Josef name.male670=Joseph name.male671=Josh name.male672=Joshua name.male673=Josiah name.male674=Jospeh name.male675=Josue name.male676=Juan name.male677=Jude name.male678=Judson name.male679=Jules name.male680=Julian name.male681=Julio name.male682=Julius name.male683=Junior name.male684=Justin name.male685=Kareem name.male686=Karl name.male687=Kasey name.male688=Keenan name.male689=Keith name.male690=Kelley name.male691=Kelly name.male692=Kelvin name.male693=Ken name.male694=Kendall name.male695=Kendrick name.male696=Keneth name.male697=Kenneth name.male698=Kennith name.male699=Kenny name.male700=Kent name.male701=Kenton name.male702=Kermit name.male703=Kerry name.male704=Keven name.male705=Kevin name.male706=Kieth name.male707=Kim name.male708=King name.male709=Kip name.male710=Kirby name.male711=Kirk name.male712=Korey name.male713=Kory name.male714=Kraig name.male715=Kris name.male716=Kristofer name.male717=Kristopher name.male718=Kurt name.male719=Kurtis name.male720=Kyle name.male721=Lacy name.male722=Lamar name.male723=Lamont name.male724=Lance name.male725=Landon name.male726=Lane name.male727=Lanny name.male728=Larry name.male729=Latyn name.male730=Lauren name.male731=Laurence name.male732=Lavern name.male733=Laverne name.male734=Lawerence name.male735=Lawrence name.male736=Lazaro name.male737=Leandro name.male738=Lee name.male739=Leif name.male740=Leigh name.male741=Leland name.male742=Lemuel name.male743=Len name.male744=Lenard name.male745=Lenny name.male746=Leo name.male747=Leon name.male748=Leonard name.male749=Leonardo name.male750=Leonel name.male751=Leopoldo name.male752=Leroy name.male753=Les name.male754=Lesley name.male755=Leslie name.male756=Lester name.male757=Levi name.male758=Lewis name.male759=Liam name.male760=Lincoln name.male761=Linden name.male762=Lindsay name.male763=Lindsey name.male764=Linel name.male765=Lino name.male766=Linwood name.male767=Lionel name.male768=Lloyd name.male769=Logan name.male770=Lon name.male771=Long name.male772=Lonnie name.male773=Lonny name.male774=Loren name.male775=Lorenzo name.male776=Lou name.male777=Louie name.male778=Louis name.male779=Lowell name.male780=Loyd name.male781=Lucas name.male782=Luciano name.male783=Lucien name.male784=Lucio name.male785=Lucius name.male786=Luigi name.male787=Luis name.male788=Luke name.male789=Lupe name.male790=Luther name.male791=Lyle name.male792=Lyman name.male793=Lyndon name.male794=Lynn name.male795=Lynwood name.male796=Mac name.male797=Mack name.male798=Major name.male799=Malcolm name.male800=Malcom name.male801=Malik name.male802=Man name.male803=Manual name.male804=Manuel name.male805=Marc name.male806=Marcel name.male807=Marcelino name.male808=Marcellus name.male809=Marcelo name.male810=March name.male811=Marco name.male812=Marcos name.male813=Marcus name.male814=Margarito name.male815=Maria name.male816=Mariano name.male817=Mario name.male818=Marion name.male819=Mark name.male820=Markus name.male821=Marlin name.male822=Marlon name.male823=Marquis name.male824=Marshall name.male825=Martin name.male826=Marty name.male827=Marvin name.male828=Mary name.male829=Mason name.male830=Mathew name.male831=Matt name.male832=Matthew name.male833=Maurice name.male834=Mauricio name.male835=Mauro name.male836=Maverick name.male837=Max name.male838=Maximo name.male839=Maxwell name.male840=Maynard name.male841=Mckinley name.male842=Mel name.male843=Melvin name.male844=Merle name.male845=Merlin name.male846=Merrill name.male847=Mervin name.male848=Micah name.male849=Michael name.male850=Michal name.male851=Michale name.male852=Micheal name.male853=Michel name.male854=Mickey name.male855=Miguel name.male856=Mike name.male857=Mikel name.male858=Milan name.male859=Miles name.male860=Milford name.male861=Millard name.male862=Milo name.male863=Milton name.male864=Minh name.male865=Miquel name.male866=Mitch name.male867=Mitchel name.male868=Mitchell name.male869=Modesto name.male870=Mohamed name.male871=Mohammad name.male872=Mohammed name.male873=Moises name.male874=Monroe name.male875=Monte name.male876=Monty name.male877=Morgan name.male878=Morris name.male879=Morton name.male880=Mose name.male881=Moses name.male882=Moshe name.male883=Murray name.male884=Myles name.male885=Myron name.male886=Napoleon name.male887=Narcissus name.male888=Nathan name.male889=Nathanael name.male890=Nathanial name.male891=Nathaniel name.male892=Neal name.male893=Ned name.male894=Neil name.male895=Nelson name.male896=Nestor name.male897=Neville name.male898=Newton name.male899=Nicholas name.male900=Nick name.male901=Nickolas name.male902=Nicky name.male903=Nicolas name.male904=Nigel name.male905=Noah name.male906=Noble name.male907=Noe name.male908=Noel name.male909=Nolan name.male910=Norbert name.male911=Norberto name.male912=Norman name.male913=Normand name.male914=Norris name.male915=Numbers name.male916=Octavio name.male917=Odell name.male918=Odis name.male919=Olen name.male920=Olin name.male921=Oliver name.male922=Ollie name.male923=Omar name.male924=Omer name.male925=Oren name.male926=Orlando name.male927=Orval name.male928=Orville name.male929=Oscar name.male930=Osvaldo name.male931=Oswaldo name.male932=Otha name.male933=Otis name.male934=Otto name.male935=Owen name.male936=Pablo name.male937=Palmer name.male938=Paris name.male939=Parker name.male940=Pasquale name.male941=Pat name.male942=Patricia name.male943=Patrick name.male944=Paul name.male945=Pedro name.male946=Percy name.male947=Perry name.male948=Pete name.male949=Peter name.male950=Phil name.male951=Philip name.male952=Phillip name.male953=Pierre name.male954=Porfirio name.male955=Porter name.male956=Preston name.male957=Prince name.male958=Quentin name.male959=Quincy name.male960=Quinn name.male961=Quintin name.male962=Quinton name.male963=Rafael name.male964=Raleigh name.male965=Ralph name.male966=Ramiro name.male967=Ramon name.male968=Ramsay name.male969=Randal name.male970=Randall name.male971=Randell name.male972=Randolph name.male973=Randy name.male974=Raphael name.male975=Rashad name.male976=Raul name.male977=Ray name.male978=Rayford name.male979=Raymon name.male980=Raymond name.male981=Raymundo name.male982=Reed name.male983=Reese name.male984=Refugio name.male985=Reggie name.male986=Reginald name.male987=Reid name.male988=Reinaldo name.male989=Renaldo name.male990=Renato name.male991=Rene name.male992=Reuben name.male993=Rex name.male994=Rey name.male995=Reyes name.male996=Reynaldo name.male997=Rhett name.male998=Ricardo name.male999=Rich name.male1000=Richard name.male1001=Richie name.male1002=Rick name.male1003=Rickey name.male1004=Rickie name.male1005=Ricky name.male1006=Rico name.male1007=Rigoberto name.male1008=Riley name.male1009=Rob name.male1010=Robbie name.male1011=Robby name.male1012=Robert name.male1013=Roberto name.male1014=Robin name.male1015=Robt name.male1016=Rocco name.male1017=Rocky name.male1018=Rod name.male1019=Roderick name.male1020=Rodger name.male1021=Rodney name.male1022=Rodolfo name.male1023=Rodrick name.male1024=Rodrigo name.male1025=Rogelio name.male1026=Roger name.male1027=Roland name.male1028=Rolando name.male1029=Rolf name.male1030=Rolland name.male1031=Roman name.male1032=Romeo name.male1033=Ron name.male1034=Ronald name.male1035=Ronnie name.male1036=Ronny name.male1037=Roosevelt name.male1038=Rory name.male1039=Rosario name.male1040=Roscoe name.male1041=Rosendo name.male1042=Ross name.male1043=Roxas name.male1044=Roy name.male1045=Royal name.male1046=Royce name.male1047=Ruben name.male1048=Rubin name.male1049=Rudolf name.male1050=Rudolph name.male1051=Rudy name.male1052=Rueben name.male1053=Rufus name.male1054=Rupert name.male1055=Russ name.male1056=Russel name.male1057=Russell name.male1058=Rusty name.male1059=Ryan name.male1060=Rye name.male1061=Rylan name.male1062=Sal name.male1063=Salvador name.male1064=Salvatore name.male1065=Sam name.male1066=Sammie name.male1067=Sammy name.male1068=Samual name.male1069=Samuel name.male1070=Sandy name.male1071=Sanford name.male1072=Sang name.male1073=Santiago name.male1074=Santo name.male1075=Santos name.male1076=Sasha name.male1077=Saul name.male1078=Sawyer name.male1079=Scot name.male1080=Scott name.male1081=Scottie name.male1082=Scotty name.male1083=Sean name.male1084=Sebastian name.male1085=Sergio name.male1086=Seth name.male1087=Seymore name.male1088=Seymour name.male1089=Shad name.male1090=Shane name.male1091=Shannon name.male1092=Shaun name.male1093=Shawn name.male1094=Shayne name.male1095=Shelby name.male1096=Sheldon name.male1097=Shelton name.male1098=Sherman name.male1099=Sherwood name.male1100=Shirley name.male1101=Shon name.male1102=Sid name.male1103=Sidney name.male1104=Silas name.male1105=Simon name.male1106=Snake name.male1107=Sol name.male1108=Solomon name.male1109=Son name.male1110=Sonny name.male1111=Soren name.male1112=Sorrel name.male1113=Spencer name.male1114=Stacey name.male1115=Stacy name.male1116=Stan name.male1117=Stanford name.male1118=Stanley name.male1119=Stanton name.male1120=Stefan name.male1121=Stephan name.male1122=Stephen name.male1123=Sterling name.male1124=Steve name.male1125=Steven name.male1126=Stevie name.male1127=Stewart name.male1128=Stuart name.male1129=Sung name.male1130=Sydney name.male1131=Sylvester name.male1132=Tad name.male1133=Tanner name.male1134=Taylor name.male1135=Ted name.male1136=Teddy name.male1137=Teodoro name.male1138=Terence name.male1139=Terrance name.male1140=Terrell name.male1141=Terrence name.male1142=Terry name.male1143=Thad name.male1144=Thaddeus name.male1145=Thanh name.male1146=Theo name.male1147=Theodore name.male1148=Theron name.male1149=Thomas name.male1150=Thorn name.male1151=Thurman name.male1152=Tim name.male1153=Timmy name.male1154=Timon name.male1155=Timonthy name.male1156=Timothy name.male1157=Titus name.male1158=Tobias name.male1159=Toby name.male1160=Tod name.male1161=Todd name.male1162=Tom name.male1163=Tomas name.male1164=Tommie name.male1165=Tommy name.male1166=Toney name.male1167=Tony name.male1168=Tory name.male1169=Tracey name.male1170=Tracy name.male1171=Travis name.male1172=Trent name.male1173=Trenton name.male1174=Trevor name.male1175=Trey name.male1176=Trinidad name.male1177=Tristan name.male1178=Troy name.male1179=Truman name.male1180=Tuan name.male1181=Tyler name.male1182=Tyree name.male1183=Tyrell name.male1184=Tyron name.male1185=Tyrone name.male1186=Tyson name.male1187=Ulysses name.male1188=Val name.male1189=Valentin name.male1190=Valentine name.male1191=Van name.male1192=Vance name.male1193=Vaughn name.male1194=Vern name.male1195=Vernon name.male1196=Vicente name.male1197=Victor name.male1198=Vince name.male1199=Vincent name.male1200=Vincenzo name.male1201=Virgil name.male1202=Virgilio name.male1203=Vito name.male1204=Von name.male1205=Wade name.male1206=Waldo name.male1207=Walker name.male1208=Wallace name.male1209=Wallis name.male1210=Wally name.male1211=Walter name.male1212=Walton name.male1213=Ward name.male1214=Warner name.male1215=Warren name.male1216=Waylon name.male1217=Wayne name.male1218=Weldon name.male1219=Wendell name.male1220=Werner name.male1221=Wes name.male1222=Wesley name.male1223=Wesley name.male1224=Weston name.male1225=Weston name.male1226=Whit name.male1227=Whit name.male1228=Whitney name.male1229=Whitney name.male1230=Wilber name.male1231=Wilber name.male1232=Wilbert name.male1233=Wilbert name.male1234=Wilbur name.male1235=Wilbur name.male1236=Wilburn name.male1237=Wilburn name.male1238=Wiley name.male1239=Wiley name.male1240=Wilford name.male1241=Wilford name.male1242=Wilfred name.male1243=Wilfred name.male1244=Wilfredo name.male1245=Wilfredo name.male1246=Will name.male1247=Will name.male1248=Willard name.male1249=Willard name.male1250=William name.male1251=William name.male1252=Williams name.male1253=Williams name.male1254=Willian name.male1255=Willian name.male1256=Willie name.male1257=Willie name.male1258=Willis name.male1259=Willis name.male1260=Willy name.male1261=Willy name.male1262=Wilmer name.male1263=Wilmer name.male1264=Wilson name.male1265=Wilson name.male1266=Wilton name.male1267=Wilton name.male1268=Winford name.male1269=Winford name.male1270=Winfred name.male1271=Winfred name.male1272=Winston name.male1273=Winston name.male1274=Woodrow name.male1275=Woodrow name.male1276=Wyatt name.male1277=Wyatt name.male1278=Wyatt name.male1279=Xavier name.male1280=Xavier name.male1281=Yong name.male1282=Yong name.male1283=Young name.male1284=Young name.male1285=Yustin name.male1286=Yustin name.male1287=Zach name.male1288=Zach name.male1289=Zachariah name.male1290=Zachariah name.male1291=Zachary name.male1292=Zachary name.male1293=Zachery name.male1294=Zachery name.male1295=Zack name.male1296=Zack name.male1297=Zackary name.male1298=Zackary name.male1299=Zane name.male1300=Zane name.male1301=Zephyr name.male1302=Zephyr name.female1=Aaron name.female2=Abbey name.female3=Abbie name.female4=Abby name.female5=Abigail name.female6=Ada name.female7=Adah name.female8=Adaline name.female9=Adam name.female10=Addie name.female11=Addison name.female12=Adel name.female13=Adela name.female14=Adelaida name.female15=Adelaide name.female16=Adele name.female17=Adelia name.female18=Adelina name.female19=Adeline name.female20=Adella name.female21=Adelle name.female22=Adena name.female23=Adina name.female24=Adria name.female25=Adrian name.female26=Adriana name.female27=Adriane name.female28=Adrianna name.female29=Adrianne name.female30=Adrien name.female31=Adriene name.female32=Adrienne name.female33=Adrina name.female34=Afton name.female35=Agatha name.female36=Agnes name.female37=Agnus name.female38=Agripina name.female39=Agueda name.female40=Agustina name.female41=Aida name.female42=Aide name.female43=Aiko name.female44=Aileen name.female45=Ailene name.female46=Aimee name.female47=Aisha name.female48=Akiko name.female49=Akilah name.female50=Alahondra name.female51=Alaina name.female52=Alaine name.female53=Alana name.female54=Alane name.female55=Alanna name.female56=Alayna name.female57=Alba name.female58=Albert name.female59=Alberta name.female60=Albertha name.female61=Albertina name.female62=Albertine name.female63=Albina name.female64=Alda name.female65=Alease name.female66=Alecia name.female67=Aleen name.female68=Aleida name.female69=Aleisha name.female70=Alejandra name.female71=Alejandrina name.female72=Alena name.female73=Alene name.female74=Alesha name.female75=Aleshia name.female76=Alesia name.female77=Alessandra name.female78=Aleta name.female79=Aletha name.female80=Alethea name.female81=Alethia name.female82=Alex name.female83=Alexa name.female84=Alexander name.female85=Alexandra name.female86=Alexandria name.female87=Alexia name.female88=Alexis name.female89=Alfreda name.female90=Alfredia name.female91=Ali name.female92=Alia name.female93=Alica name.female94=Alice name.female95=Alicia name.female96=Alida name.female97=Alina name.female98=Aline name.female99=Alisa name.female100=Alise name.female101=Alisha name.female102=Alishia name.female103=Alisia name.female104=Alison name.female105=Alissa name.female106=Alita name.female107=Alix name.female108=Aliza name.female109=Alla name.female110=Alleen name.female111=Allegra name.female112=Allen name.female113=Allena name.female114=Allene name.female115=Allie name.female116=Alline name.female117=Allison name.female118=Allyn name.female119=Allyson name.female120=Alma name.female121=Almeda name.female122=Almeta name.female123=Alona name.female124=Alpha name.female125=Alta name.female126=Altagracia name.female127=Altha name.female128=Althea name.female129=Alva name.female130=Alvera name.female131=Alverta name.female132=Alvina name.female133=Alyce name.female134=Alycia name.female135=Alysa name.female136=Alyse name.female137=Alysha name.female138=Alysia name.female139=Alyson name.female140=Alyssa name.female141=Amada name.female142=Amal name.female143=Amalia name.female144=Amanda name.female145=Amaryllis name.female146=Amber name.female147=Amberly name.female148=Amee name.female149=Amelia name.female150=America name.female151=Amethyst name.female152=Ami name.female153=Amie name.female154=Amiee name.female155=Amina name.female156=Amira name.female157=Ammie name.female158=Amparo name.female159=Amy name.female160=Ana name.female161=Anabel name.female162=Analisa name.female163=Anamaria name.female164=Anastacia name.female165=Anastasia name.female166=Andera name.female167=Andra name.female168=Andre name.female169=Andrea name.female170=Andree name.female171=Andrew name.female172=Andria name.female173=Anette name.female174=Angel name.female175=Angela name.female176=Angele name.female177=Angelena name.female178=Angeles name.female179=Angelia name.female180=Angelic name.female181=Angelica name.female182=Angelika name.female183=Angelina name.female184=Angeline name.female185=Angelique name.female186=Angelita name.female187=Angella name.female188=Angelo name.female189=Angelyn name.female190=Angie name.female191=Angila name.female192=Angla name.female193=Angle name.female194=Anglea name.female195=Anh name.female196=Anika name.female197=Anisa name.female198=Anisha name.female199=Anissa name.female200=Anita name.female201=Anitra name.female202=Anja name.female203=Anjanette name.female204=Anjelica name.female205=Ann name.female206=Anna name.female207=Annabel name.female208=Annabell name.female209=Annabelle name.female210=Annabellie name.female211=Annalee name.female212=Annalisa name.female213=Annamae name.female214=Annamaria name.female215=Annamarie name.female216=Anne name.female217=Anneliese name.female218=Annelle name.female219=Annemarie name.female220=Annett name.female221=Annetta name.female222=Annette name.female223=Annice name.female224=Annie name.female225=Annika name.female226=Annis name.female227=Annita name.female228=Annmarie name.female229=Anthony name.female230=Antionette name.female231=Antoinette name.female232=Antonetta name.female233=Antonette name.female234=Antonia name.female235=Antonietta name.female236=Antonina name.female237=Antonio name.female238=Anya name.female239=Apolonia name.female240=April name.female241=Apryl name.female242=Ara name.female243=Araceli name.female244=Aracelis name.female245=Aracely name.female246=Arcelia name.female247=Ardath name.female248=Ardelia name.female249=Ardell name.female250=Ardella name.female251=Ardelle name.female252=Ardis name.female253=Ardith name.female254=Areona name.female255=Aretha name.female256=Argelia name.female257=Argentina name.female258=Ariana name.female259=Ariane name.female260=Arianna name.female261=Arianne name.female262=Arica name.female263=Arie name.female264=Ariel name.female265=Arielle name.female266=Arla name.female267=Arlean name.female268=Arleen name.female269=Arlena name.female270=Arlene name.female271=Arletha name.female272=Arletta name.female273=Arlette name.female274=Arlinda name.female275=Arline name.female276=Arlyne name.female277=Armanda name.female278=Armandina name.female279=Armida name.female280=Arminda name.female281=Arnetta name.female282=Arnette name.female283=Arnita name.female284=Arthur name.female285=Artie name.female286=Arvilla name.female287=Asha name.female288=Ashanti name.female289=Ashely name.female290=Ashlea name.female291=Ashlee name.female292=Ashleigh name.female293=Ashley name.female294=Ashli name.female295=Ashlie name.female296=Ashly name.female297=Ashlyn name.female298=Ashton name.female299=Asia name.female300=Asley name.female301=Assunta name.female302=Astrid name.female303=Asuncion name.female304=Athena name.female305=Aubrey name.female306=Audie name.female307=Audra name.female308=Audrea name.female309=Audrey name.female310=Audria name.female311=Audrie name.female312=Audry name.female313=August name.female314=Augusta name.female315=Augustina name.female316=Augustine name.female317=Aundrea name.female318=Aura name.female319=Aurea name.female320=Aurelia name.female321=Aurora name.female322=Aurore name.female323=Austin name.female324=Autumn name.female325=Ava name.female326=Avelina name.female327=Avery name.female328=Avis name.female329=Avril name.female330=Awilda name.female331=Ayako name.female332=Ayana name.female333=Ayanna name.female334=Ayesha name.female335=Azalea name.female336=Azalee name.female337=Azucena name.female338=Azzie name.female339=Babara name.female340=Babette name.female341=Bailey name.female342=Bambi name.female343=Bao name.female344=Barabara name.female345=Barb name.female346=Barbar name.female347=Barbara name.female348=Barbara-Anne name.female349=Barbera name.female350=Barbie name.female351=Barbra name.female352=Bari name.female353=Barrie name.female354=Basilia name.female355=Bea name.female356=Beata name.female357=Beatrice name.female358=Beatris name.female359=Beatriz name.female360=Beaulah name.female361=Bebe name.female362=Becki name.female363=Beckie name.female364=Becky name.female365=Bee name.female366=Belen name.female367=Belia name.female368=Belinda name.female369=Belkis name.female370=Bell name.female371=Bella name.female372=Belle name.female373=Belva name.female374=Benita name.female375=Bennie name.female376=Berenice name.female377=Berna name.female378=Bernadette name.female379=Bernadine name.female380=Bernarda name.female381=Bernardina name.female382=Bernardine name.female383=Berneice name.female384=Bernetta name.female385=Bernice name.female386=Bernie name.female387=Berniece name.female388=Bernita name.female389=Berry name.female390=Berta name.female391=Bertha name.female392=Bertie name.female393=Beryl name.female394=Bess name.female395=Bessie name.female396=Beth name.female397=Bethanie name.female398=Bethann name.female399=Bethany name.female400=Bethel name.female401=Betsey name.female402=Betsy name.female403=Bette name.female404=Bettie name.female405=Bettina name.female406=Betty name.female407=Bettyann name.female408=Bettye name.female409=Beula name.female410=Beulah name.female411=Bev name.female412=Beverlee name.female413=Beverley name.female414=Beverly name.female415=Bianca name.female416=Bibi name.female417=Billi name.female418=Billie name.female419=Billy name.female420=Billye name.female421=Birdie name.female422=Birgit name.female423=Blair name.female424=Blake name.female425=Blanca name.female426=Blanch name.female427=Blanche name.female428=Blondell name.female429=Blossom name.female430=Blythe name.female431=Bobbi name.female432=Bobbie name.female433=Bobby name.female434=Bobbye name.female435=Bobette name.female436=Bok name.female437=Bong name.female438=Bonita name.female439=Bonnie name.female440=Bonny name.female441=Branda name.female442=Brande name.female443=Brandee name.female444=Brandi name.female445=Brandie name.female446=Brandon name.female447=Brandy name.female448=Breana name.female449=Breann name.female450=Breanna name.female451=Breanne name.female452=Bree name.female453=Brenda name.female454=Brenna name.female455=Brett name.female456=Brian name.female457=Briana name.female458=Brianna name.female459=Brianne name.female460=Briar name.female461=Bridget name.female462=Bridgett name.female463=Bridgette name.female464=Brielle name.female465=Brigette name.female466=Brigid name.female467=Brigida name.female468=Brigitte name.female469=Brinda name.female470=Britany name.female471=Britney name.female472=Britni name.female473=Britt name.female474=Britta name.female475=Brittaney name.female476=Brittani name.female477=Brittanie name.female478=Brittany name.female479=Britteny name.female480=Brittney name.female481=Brittni name.female482=Brittny name.female483=Bronwyn name.female484=Brook name.female485=Brooke name.female486=Bruna name.female487=Brunilda name.female488=Bryanna name.female489=Brynn name.female490=Buena name.female491=Buffy name.female492=Bula name.female493=Bulah name.female494=Bunny name.female495=Burma name.female496=Caitlin name.female497=Caitlyn name.female498=Calandra name.female499=Calista name.female500=Calla name.female501=Callie name.female502=Camelia name.female503=Camellia name.female504=Cameron name.female505=Cami name.female506=Camie name.female507=Camila name.female508=Camilla name.female509=Camille name.female510=Cammie name.female511=Cammy name.female512=Candace name.female513=Candance name.female514=Candelaria name.female515=Candi name.female516=Candice name.female517=Candida name.female518=Candie name.female519=Candis name.female520=Candra name.female521=Candy name.female522=Candyce name.female523=Caprice name.female524=Cara name.female525=Caren name.female526=Carey name.female527=Cari name.female528=Caridad name.female529=Carie name.female530=Carin name.female531=Carina name.female532=Carisa name.female533=Carissa name.female534=Carita name.female535=Carl name.female536=Carla name.female537=Carlee name.female538=Carleen name.female539=Carlena name.female540=Carlene name.female541=Carletta name.female542=Carley name.female543=Carli name.female544=Carlie name.female545=Carline name.female546=Carlita name.female547=Carlos name.female548=Carlota name.female549=Carlotta name.female550=Carly name.female551=Carlyn name.female552=Carma name.female553=Carman name.female554=Carmel name.female555=Carmela name.female556=Carmelia name.female557=Carmelina name.female558=Carmelita name.female559=Carmella name.female560=Carmen name.female561=Carmina name.female562=Carmon name.female563=Carol name.female564=Carola name.female565=Carolann name.female566=Carole name.female567=Carolee name.female568=Carolin name.female569=Carolina name.female570=Caroline name.female571=Caroll name.female572=Carolyn name.female573=Carolyne name.female574=Carolynn name.female575=Caron name.female576=Caroyln name.female577=Carri name.female578=Carrie name.female579=Carrol name.female580=Carroll name.female581=Carry name.female582=Cary name.female583=Caryl name.female584=Carylon name.female585=Caryn name.female586=Casandra name.female587=Casey name.female588=Casie name.female589=Casimira name.female590=Cassandra name.female591=Cassaundra name.female592=Cassey name.female593=Cassi name.female594=Cassidy name.female595=Cassie name.female596=Cassondra name.female597=Cassy name.female598=Catalina name.female599=Catarina name.female600=Caterina name.female601=Catharine name.female602=Catherin name.female603=Catherina name.female604=Catherine name.female605=Cathern name.female606=Catheryn name.female607=Cathey name.female608=Cathi name.female609=Cathie name.female610=Cathleen name.female611=Cathrine name.female612=Cathryn name.female613=Cathy name.female614=Catina name.female615=Catrice name.female616=Catrina name.female617=Cayla name.female618=Cecelia name.female619=Cecil name.female620=Cecila name.female621=Cecile name.female622=Cecilia name.female623=Cecille name.female624=Cecily name.female625=Celena name.female626=Celesta name.female627=Celeste name.female628=Celestina name.female629=Celestine name.female630=Celia name.female631=Celina name.female632=Celinda name.female633=Celine name.female634=Celsa name.female635=Ceola name.female636=Chae name.female637=Chan name.female638=Chana name.female639=Chanda name.female640=Chandra name.female641=Chanel name.female642=Chanell name.female643=Chanelle name.female644=Chang name.female645=Chantal name.female646=Chantay name.female647=Chante name.female648=Chantel name.female649=Chantell name.female650=Chantelle name.female651=Chara name.female652=Chariisa name.female653=Charis name.female654=Charise name.female655=Charissa name.female656=Charisse name.female657=Charita name.female658=Charity name.female659=Charla name.female660=Charleen name.female661=Charlena name.female662=Charlene name.female663=Charles name.female664=Charlesetta name.female665=Charlette name.female666=Charlie name.female667=Charline name.female668=Charlott name.female669=Charlotte name.female670=Charlsie name.female671=Charlyn name.female672=Charmain name.female673=Charmaine name.female674=Charolette name.female675=Chasidy name.female676=Chasity name.female677=Chassidy name.female678=Chassity name.female679=Chastity name.female680=Chau name.female681=Chaya name.female682=Chelsea name.female683=Chelsey name.female684=Chelsie name.female685=Cher name.female686=Chere name.female687=Cheree name.female688=Cherelle name.female689=Cheri name.female690=Cherie name.female691=Cherilyn name.female692=Cherise name.female693=Cherish name.female694=Cherly name.female695=Cherlyn name.female696=Cherri name.female697=Cherrie name.female698=Cherry name.female699=Cherryl name.female700=Chery name.female701=Cheryl name.female702=Cheryle name.female703=Cheryll name.female704=Cheyenne name.female705=Chi name.female706=Chia name.female707=Chieko name.female708=Chin name.female709=China name.female710=Ching name.female711=Chiquita name.female712=Chloe name.female713=Chong name.female714=Chris name.female715=Chrissy name.female716=Christa name.female717=Christal name.female718=Christeen name.female719=Christel name.female720=Christen name.female721=Christena name.female722=Christene name.female723=Christi name.female724=Christia name.female725=Christian name.female726=Christiana name.female727=Christiane name.female728=Christie name.female729=Christin name.female730=Christina name.female731=Christine name.female732=Christinia name.female733=Christopher name.female734=Christy name.female735=Chrystal name.female736=Chu name.female737=Chun name.female738=Chung name.female739=Ciara name.female740=Cicely name.female741=Ciera name.female742=Cierra name.female743=Cinda name.female744=Cinderella name.female745=Cindi name.female746=Cindie name.female747=Cindy name.female748=Cinthia name.female749=Cira name.female750=Clair name.female751=Claire name.female752=Clara name.female753=Clare name.female754=Clarence name.female755=Claretha name.female756=Claretta name.female757=Claribel name.female758=Clarice name.female759=Clarinda name.female760=Clarine name.female761=Claris name.female762=Clarisa name.female763=Clarissa name.female764=Clarita name.female765=Classie name.female766=Claude name.female767=Claudette name.female768=Claudia name.female769=Claudie name.female770=Claudine name.female771=Clelia name.female772=Clemencia name.female773=Clementina name.female774=Clementine name.female775=Clemmie name.female776=Cleo name.female777=Cleopatra name.female778=Cleora name.female779=Cleotilde name.female780=Cleta name.female781=Clora name.female782=Clorinda name.female783=Clotilde name.female784=Clover name.female785=Clyde name.female786=Codi name.female787=Cody name.female788=Colby name.female789=Coleen name.female790=Colene name.female791=Coletta name.female792=Colette name.female793=Colleen name.female794=Collen name.female795=Collene name.female796=Collette name.female797=Concepcion name.female798=Conception name.female799=Concetta name.female800=Concha name.female801=Conchita name.female802=Connie name.female803=Constance name.female804=Consuela name.female805=Consuelo name.female806=Contessa name.female807=Cora name.female808=Coral name.female809=Coralee name.female810=Coralie name.female811=Corazon name.female812=Cordelia name.female813=Cordia name.female814=Cordie name.female815=Coreen name.female816=Corene name.female817=Coretta name.female818=Corey name.female819=Cori name.female820=Corie name.female821=Corina name.female822=Corine name.female823=Corinna name.female824=Corinne name.female825=Corliss name.female826=Cornelia name.female827=Corrie name.female828=Corrin name.female829=Corrina name.female830=Corrine name.female831=Corrinne name.female832=Cortney name.female833=Cory name.female834=Courtney name.female835=Creola name.female836=Cris name.female837=Criselda name.female838=Crissy name.female839=Crista name.female840=Cristal name.female841=Cristen name.female842=Cristi name.female843=Cristie name.female844=Cristin name.female845=Cristina name.female846=Cristine name.female847=Cristy name.female848=Cruz name.female849=Crysta name.female850=Crystal name.female851=Crystle name.female852=Curtis name.female853=Cyndi name.female854=Cyndy name.female855=Cynthia name.female856=Cyrstal name.female857=Cythia name.female858=Dacia name.female859=Dagmar name.female860=Dagny name.female861=Dahlia name.female862=Daina name.female863=Daine name.female864=Daisey name.female865=Daisy name.female866=Daisy-Mae name.female867=Dakota name.female868=Dale name.female869=Dalene name.female870=Dalia name.female871=Dalie name.female872=Dalila name.female873=Dallas name.female874=Dallis name.female875=Damaris name.female876=Dan name.female877=Dana name.female878=Danae name.female879=Danelle name.female880=Danette name.female881=Dani name.female882=Dania name.female883=Danica name.female884=Daniel name.female885=Daniela name.female886=Daniele name.female887=Daniell name.female888=Daniella name.female889=Danielle name.female890=Danika name.female891=Danille name.female892=Danita name.female893=Dann name.female894=Danna name.female895=Dannette name.female896=Dannie name.female897=Dannielle name.female898=Danuta name.female899=Danyel name.female900=Danyell name.female901=Danyelle name.female902=Daphine name.female903=Daphne name.female904=Dara name.female905=Darby name.female906=Darcel name.female907=Darcey name.female908=Darci name.female909=Darcie name.female910=Darcy name.female911=Daria name.female912=Darla name.female913=Darleen name.female914=Darlena name.female915=Darlene name.female916=Darline name.female917=Darnell name.female918=Daryl name.female919=David name.female920=Davida name.female921=Davina name.female922=Dawn name.female923=Dawna name.female924=Dawne name.female925=Dayle name.female926=Dayna name.female927=Daysi name.female928=Deadra name.female929=Dean name.female930=Deana name.female931=Deandra name.female932=Deandrea name.female933=Deane name.female934=Deann name.female935=Deanna name.female936=Deanne name.female937=Deb name.female938=Debbi name.female939=Debbie name.female940=Debbra name.female941=Debby name.female942=Debera name.female943=Debi name.female944=Debie name.female945=Debora name.female946=Deborah name.female947=Debra name.female948=Debrah name.female949=Debroah name.female950=Dede name.female951=Dedra name.female952=Dee name.female953=Deeann name.female954=Deeanna name.female955=Deedee name.female956=Deedra name.female957=Deena name.female958=Deetta name.female959=Deidra name.female960=Deidre name.female961=Deirdre name.female962=Deja name.female963=Delaine name.female964=Delana name.female965=Delaney name.female966=Delcie name.female967=Delena name.female968=Delfina name.female969=Delia name.female970=Delicia name.female971=Delila name.female972=Delilah name.female973=Delinda name.female974=Delisa name.female975=Dell name.female976=Della name.female977=Delma name.female978=Delmy name.female979=Delois name.female980=Deloise name.female981=Delora name.female982=Deloras name.female983=Delores name.female984=Deloris name.female985=Delorse name.female986=Delpha name.female987=Delphia name.female988=Delphine name.female989=Delsie name.female990=Delta name.female991=Demetra name.female992=Demetria name.female993=Demetrice name.female994=Demetrius name.female995=Dena name.female996=Denae name.female997=Deneen name.female998=Denese name.female999=Denice name.female1000=Denise name.female1001=Denisha name.female1002=Denisse name.female1003=Denita name.female1004=Denna name.female1005=Dennis name.female1006=Dennise name.female1007=Denny name.female1008=Denyse name.female1009=Deon name.female1010=Deonna name.female1011=Desirae name.female1012=Desire name.female1013=Desiree name.female1014=Despina name.female1015=Dessi name.female1016=Dessie name.female1017=Destiny name.female1018=Detra name.female1019=Devin name.female1020=Devon name.female1021=Devona name.female1022=Devora name.female1023=Devorah name.female1024=Dia name.female1025=Diamond name.female1026=Dian name.female1027=Diana name.female1028=Diane name.female1029=Diann name.female1030=Dianna name.female1031=Dianne name.female1032=Diedra name.female1033=Diedre name.female1034=Dierdre name.female1035=Digna name.female1036=Dimple name.female1037=Dina name.female1038=Dinah name.female1039=Dinorah name.female1040=Dion name.female1041=Dione name.female1042=Dionna name.female1043=Dionne name.female1044=Divina name.female1045=Dixie name.female1046=Dodie name.female1047=Dollie name.female1048=Dolly name.female1049=Dolores name.female1050=Doloris name.female1051=Domenica name.female1052=Dominga name.female1053=Dominica name.female1054=Dominique name.female1055=Dominque name.female1056=Domitila name.female1057=Domonique name.female1058=Dona name.female1059=Donald name.female1060=Donella name.female1061=Donetta name.female1062=Donette name.female1063=Dong name.female1064=Donita name.female1065=Donna name.female1066=Donna-Jo name.female1067=Donnetta name.female1068=Donnette name.female1069=Donnie name.female1070=Donya name.female1071=Dora name.female1072=Dorathy name.female1073=Dorcas name.female1074=Doreatha name.female1075=Doreen name.female1076=Dorene name.female1077=Doretha name.female1078=Dorethea name.female1079=Doretta name.female1080=Dori name.female1081=Doria name.female1082=Dorian name.female1083=Dorie name.female1084=Dorinda name.female1085=Dorine name.female1086=Doris name.female1087=Dorla name.female1088=Dorotha name.female1089=Dorothea name.female1090=Dorothy name.female1091=Dorris name.female1092=Dortha name.female1093=Dorthea name.female1094=Dorthey name.female1095=Dorthy name.female1096=Dot name.female1097=Dottie name.female1098=Dotty name.female1099=Dovie name.female1100=Dreama name.female1101=Drema name.female1102=Drew name.female1103=Drucilla name.female1104=Drusilla name.female1105=Dulce name.female1106=Dulcie name.female1107=Dung name.female1108=Dusti name.female1109=Dusty name.female1110=Dwana name.female1111=Dyan name.female1112=Earlean name.female1113=Earleen name.female1114=Earlene name.female1115=Earlie name.female1116=Earline name.female1117=Earnestine name.female1118=Eartha name.female1119=Easter name.female1120=Eboni name.female1121=Ebonie name.female1122=Ebony name.female1123=Echo name.female1124=Eda name.female1125=Edda name.female1126=Eddie name.female1127=Edelmira name.female1128=Eden name.female1129=Edie name.female1130=Edith name.female1131=Edna name.female1132=Edra name.female1133=Edris name.female1134=Edward name.female1135=Edwina name.female1136=Edyth name.female1137=Edythe name.female1138=Effie name.female1139=Ehtel name.female1140=Eileen name.female1141=Eilene name.female1142=Ela name.female1143=Eladia name.female1144=Elaina name.female1145=Elaine name.female1146=Elana name.female1147=Elane name.female1148=Elanor name.female1149=Elayne name.female1150=Elba name.female1151=Elda name.female1152=Eldora name.female1153=Eleanor name.female1154=Eleanora name.female1155=Eleanore name.female1156=Elease name.female1157=Elena name.female1158=Elene name.female1159=Eleni name.female1160=Elenor name.female1161=Elenora name.female1162=Elenore name.female1163=Eleonor name.female1164=Eleonora name.female1165=Eleonore name.female1166=Elfreda name.female1167=Elfrieda name.female1168=Elfriede name.female1169=Elia name.female1170=Eliana name.female1171=Elicia name.female1172=Elida name.female1173=Elidia name.female1174=Elin name.female1175=Elina name.female1176=Elinor name.female1177=Elinore name.female1178=Elisa name.female1179=Elisabeth name.female1180=Elise name.female1181=Elisha name.female1182=Elissa name.female1183=Eliz name.female1184=Eliza name.female1185=Elizabet name.female1186=Elizabeth name.female1187=Elizbeth name.female1188=Elizebeth name.female1189=Elke name.female1190=Ella name.female1191=Ellamae name.female1192=Ellan name.female1193=Ellen name.female1194=Ellena name.female1195=Elli name.female1196=Ellie name.female1197=Ellis name.female1198=Elly name.female1199=Ellyn name.female1200=Elma name.female1201=Elmer name.female1202=Elmira name.female1203=Elna name.female1204=Elnora name.female1205=Elodia name.female1206=Elois name.female1207=Eloisa name.female1208=Eloise name.female1209=Elouise name.female1210=Elsa name.female1211=Else name.female1212=Elsie name.female1213=Elsy name.female1214=Elva name.female1215=Elvera name.female1216=Elvia name.female1217=Elvie name.female1218=Elvina name.female1219=Elvira name.female1220=Elwanda name.female1221=Elyse name.female1222=Elza name.female1223=Ema name.female1224=Emelda name.female1225=Emelia name.female1226=Emelina name.female1227=Emeline name.female1228=Emely name.female1229=Emerald name.female1230=Emerita name.female1231=Emiko name.female1232=Emilee name.female1233=Emilia name.female1234=Emilie name.female1235=Emily name.female1236=Emma name.female1237=Emmaline name.female1238=Emmie name.female1239=Emmy name.female1240=Emogene name.female1241=Ena name.female1242=Enda name.female1243=Enedina name.female1244=Eneida name.female1245=Enid name.female1246=Enola name.female1247=Enriqueta name.female1248=Epifania name.female1249=Era name.female1250=Eric name.female1251=Erica name.female1252=Ericka name.female1253=Erika name.female1254=Erin name.female1255=Erinn name.female1256=Erlene name.female1257=Erlinda name.female1258=Erline name.female1259=Erma name.female1260=Ermelinda name.female1261=Erminia name.female1262=Erna name.female1263=Ernestina name.female1264=Ernestine name.female1265=Eryn name.female1266=Esmeralda name.female1267=Esperanza name.female1268=Essie name.female1269=Esta name.female1270=Estefana name.female1271=Estela name.female1272=Estell name.female1273=Estella name.female1274=Estelle name.female1275=Ester name.female1276=Esther name.female1277=Estrella name.female1278=Etha name.female1279=Ethel name.female1280=Ethelene name.female1281=Ethelyn name.female1282=Ethyl name.female1283=Etsuko name.female1284=Etta name.female1285=Ettie name.female1286=Eufemia name.female1287=Eugena name.female1288=Eugene name.female1289=Eugenia name.female1290=Eugenie name.female1291=Eula name.female1292=Eulah name.female1293=Eulalia name.female1294=Eun name.female1295=Euna name.female1296=Eunice name.female1297=Eura name.female1298=Eusebia name.female1299=Eustolia name.female1300=Eva name.female1301=Evadne name.female1302=Evalyn name.female1303=Evan name.female1304=Evangelina name.female1305=Evangeline name.female1306=Eve name.female1307=Evelia name.female1308=Evelin name.female1309=Evelina name.female1310=Eveline name.female1311=Evelyn name.female1312=Evelyne name.female1313=Evelynn name.female1314=Evette name.female1315=Evia name.female1316=Evie name.female1317=Evita name.female1318=Evon name.female1319=Evonne name.female1320=Ewa name.female1321=Exie name.female1322=Fabiola name.female1323=Fae name.female1324=Fairy name.female1325=Faith name.female1326=Fall name.female1327=Fallon name.female1328=Fannie name.female1329=Fanny name.female1330=Farah name.female1331=Farrah name.female1332=Fatima name.female1333=Fatimah name.female1334=Faustina name.female1335=Faviola name.female1336=Fawn name.female1337=Fay name.female1338=Faye name.female1339=Felecia name.female1340=Felica name.female1341=Felice name.female1342=Felicia name.female1343=Felicidad name.female1344=Felicita name.female1345=Felicitas name.female1346=Felipa name.female1347=Felisa name.female1348=Felisha name.female1349=Fermina name.female1350=Fern name.female1351=Fernanda name.female1352=Fernande name.female1353=Ferne name.female1354=Fidela name.female1355=Fidelia name.female1356=Filomena name.female1357=Fiona name.female1358=Flavia name.female1359=Fleta name.female1360=Flo name.female1361=Flor name.female1362=Flora name.female1363=Florance name.female1364=Florence name.female1365=Florencia name.female1366=Florene name.female1367=Florentina name.female1368=Floretta name.female1369=Floria name.female1370=Florida name.female1371=Florinda name.female1372=Florine name.female1373=Florrie name.female1374=Flossie name.female1375=Floy name.female1376=Fonda name.female1377=Fran name.female1378=France name.female1379=Francene name.female1380=Frances name.female1381=Francesca name.female1382=Franchesca name.female1383=Francie name.female1384=Francina name.female1385=Francine name.female1386=Francis name.female1387=Francisca name.female1388=Francisco name.female1389=Francoise name.female1390=Frank name.female1391=Frankie name.female1392=Fransisca name.female1393=Fred name.female1394=Freda name.female1395=Fredda name.female1396=Freddie name.female1397=Frederica name.female1398=Fredericka name.female1399=Fredia name.female1400=Fredricka name.female1401=Freeda name.female1402=Freida name.female1403=Frida name.female1404=Frieda name.female1405=Fumiko name.female1406=Gabriel name.female1407=Gabriela name.female1408=Gabriele name.female1409=Gabriella name.female1410=Gabrielle name.female1411=Gail name.female1412=Gala name.female1413=Gale name.female1414=Galina name.female1415=Garnet name.female1416=Garnett name.female1417=Gary name.female1418=Gaye name.female1419=Gayla name.female1420=Gayle name.female1421=Gaylene name.female1422=Gaynell name.female1423=Gaynelle name.female1424=Gearldine name.female1425=Gema name.female1426=Gemma name.female1427=Gena name.female1428=Gene name.female1429=Genesis name.female1430=Geneva name.female1431=Genevie name.female1432=Genevieve name.female1433=Genevive name.female1434=Genia name.female1435=Genie name.female1436=Genna name.female1437=Gennie name.female1438=Genny name.female1439=Genoveva name.female1440=Georgann name.female1441=George name.female1442=Georgeann name.female1443=Georgeanna name.female1444=Georgene name.female1445=Georgetta name.female1446=Georgette name.female1447=Georgia name.female1448=Georgiana name.female1449=Georgiann name.female1450=Georgianna name.female1451=Georgianne name.female1452=Georgie name.female1453=Georgina name.female1454=Georgine name.female1455=Gerald name.female1456=Geraldine name.female1457=Geralyn name.female1458=Gerda name.female1459=Geri name.female1460=Germaine name.female1461=Gerri name.female1462=Gerry name.female1463=Gertha name.female1464=Gertie name.female1465=Gertrud name.female1466=Gertrude name.female1467=Gertrudis name.female1468=Gertude name.female1469=Ghislaine name.female1470=Gia name.female1471=Gianna name.female1472=Gidget name.female1473=Gigi name.female1474=Gilberte name.female1475=Gilda name.female1476=Gillian name.female1477=Gilma name.female1478=Gina name.female1479=Ginette name.female1480=Ginger name.female1481=Ginny name.female1482=Giovanna name.female1483=Gisela name.female1484=Gisele name.female1485=Giselle name.female1486=Gita name.female1487=Giuseppina name.female1488=Gladis name.female1489=Glady name.female1490=Gladys name.female1491=Glayds name.female1492=Glenda name.female1493=Glendora name.female1494=Glenn name.female1495=Glenna name.female1496=Glennie name.female1497=Glennis name.female1498=Glinda name.female1499=Gloria name.female1500=Glory name.female1501=Glynda name.female1502=Glynis name.female1503=Golda name.female1504=Golden name.female1505=Goldie name.female1506=Grace name.female1507=Gracia name.female1508=Gracie name.female1509=Graciela name.female1510=Grayce name.female1511=Grazyna name.female1512=Gregoria name.female1513=Gregory name.female1514=Greta name.female1515=Gretchen name.female1516=Gretta name.female1517=Gricelda name.female1518=Grisel name.female1519=Griselda name.female1520=Guadalupe name.female1521=Gudrun name.female1522=Guillermina name.female1523=Gurpreet name.female1524=Gussie name.female1525=Gwen name.female1526=Gwenda name.female1527=Gwendolyn name.female1528=Gwenn name.female1529=Gwyn name.female1530=Gwyneth name.female1531=Hae name.female1532=Hailey name.female1533=Haley name.female1534=Halina name.female1535=Halley name.female1536=Hallie name.female1537=Han name.female1538=Hana name.female1539=Hang name.female1540=Hanh name.female1541=Hanna name.female1542=Hannah name.female1543=Hannelore name.female1544=Harmony name.female1545=Harold name.female1546=Harriet name.female1547=Harriett name.female1548=Harriette name.female1549=Hassie name.female1550=Hattie name.female1551=Haydee name.female1552=Hayley name.female1553=Haylie-Anne name.female1554=Hazel name.female1555=Heather name.female1556=Hedwig name.female1557=Hedy name.female1558=Heide name.female1559=Heidi name.female1560=Heidy name.female1561=Heike name.female1562=Helaine name.female1563=Helen name.female1564=Helena name.female1565=Helene name.female1566=Helga name.female1567=Hellen name.female1568=Henrietta name.female1569=Henriette name.female1570=Henry name.female1571=Herlinda name.female1572=Herma name.female1573=Hermelinda name.female1574=Hermila name.female1575=Hermina name.female1576=Hermine name.female1577=Herminia name.female1578=Herta name.female1579=Hertha name.female1580=Hester name.female1581=Hettie name.female1582=Hiedi name.female1583=Hien name.female1584=Hilaria name.female1585=Hilary name.female1586=Hilda name.female1587=Hilde name.female1588=Hildegard name.female1589=Hildegarde name.female1590=Hildred name.female1591=Hillary name.female1592=Hilma name.female1593=Hiroko name.female1594=Hisako name.female1595=Hoa name.female1596=Holley name.female1597=Holli name.female1598=Hollie name.female1599=Hollis name.female1600=Holly name.female1601=Honey name.female1602=Hong name.female1603=Hope name.female1604=Hortencia name.female1605=Hortense name.female1606=Hortensia name.female1607=Hsiu name.female1608=Hue name.female1609=Hui name.female1610=Hulda name.female1611=Huong name.female1612=Hyacinth name.female1613=Hyo name.female1614=Hyon name.female1615=Hyun name.female1616=Ida name.female1617=Idalia name.female1618=Idell name.female1619=Idella name.female1620=Iesha name.female1621=Ignacia name.female1622=Ila name.female1623=Ilana name.female1624=Ilda name.female1625=Ileana name.female1626=Ileen name.female1627=Ilene name.female1628=Iliana name.female1629=Illa name.female1630=Ilona name.female1631=Ilse name.female1632=Iluminada name.female1633=Ima name.female1634=Imelda name.female1635=Imogen name.female1636=Imogene name.female1637=Ina name.female1638=India name.female1639=Indigo name.female1640=Indira name.female1641=Inell name.female1642=Ines name.female1643=Inez name.female1644=Inga name.female1645=Inge name.female1646=Ingeborg name.female1647=Inger name.female1648=Ingrid name.female1649=Inocencia name.female1650=Iola name.female1651=Iona name.female1652=Ione name.female1653=Ira name.female1654=Iraida name.female1655=Irena name.female1656=Irene name.female1657=Irina name.female1658=Iris name.female1659=Irish name.female1660=Irma name.female1661=Irmgard name.female1662=Isa name.female1663=Isabel name.female1664=Isabell name.female1665=Isabella name.female1666=Isabelle name.female1667=Isadora name.female1668=Isaura name.female1669=Isela name.female1670=Isidra name.female1671=Isis name.female1672=Isobel name.female1673=Iva name.female1674=Ivana name.female1675=Ivelisse name.female1676=Ivette name.female1677=Ivey name.female1678=Ivonne name.female1679=Ivory name.female1680=Ivy name.female1681=Izetta name.female1682=Izola name.female1683=Jacalyn name.female1684=Jacelyn name.female1685=Jacinda name.female1686=Jacinta name.female1687=Jack name.female1688=Jackeline name.female1689=Jackelyn name.female1690=Jacki name.female1691=Jackie name.female1692=Jacklyn name.female1693=Jackqueline name.female1694=Jaclyn name.female1695=Jacqualine name.female1696=Jacque name.female1697=Jacquelin name.female1698=Jacqueline name.female1699=Jacquelyn name.female1700=Jacquelyne name.female1701=Jacquelynn name.female1702=Jacquetta name.female1703=Jacqui name.female1704=Jacquie name.female1705=Jacquiline name.female1706=Jacquline name.female1707=Jacqulyn name.female1708=Jada name.female1709=Jade name.female1710=Jadwiga name.female1711=Jae name.female1712=Jaime name.female1713=Jaimee name.female1714=Jaimie name.female1715=Jaleesa name.female1716=Jalisa name.female1717=Jama name.female1718=Jame name.female1719=Jamee name.female1720=James name.female1721=Jamey name.female1722=Jami name.female1723=Jamie name.female1724=Jamika name.female1725=Jamila name.female1726=Jammie name.female1727=Jan name.female1728=Jana name.female1729=Janae name.female1730=Janay name.female1731=Jane name.female1732=Janean name.female1733=Janee name.female1734=Janeen name.female1735=Janel name.female1736=Janell name.female1737=Janella name.female1738=Janelle name.female1739=Janene name.female1740=Janessa name.female1741=Janet name.female1742=Janeth name.female1743=Janett name.female1744=Janetta name.female1745=Janette name.female1746=Janey name.female1747=Jani name.female1748=Janice name.female1749=Janie name.female1750=Janiece name.female1751=Janina name.female1752=Janine name.female1753=Janis name.female1754=Janise name.female1755=Janita name.female1756=Jann name.female1757=Janna name.female1758=Jannet name.female1759=Jannette name.female1760=Jannie name.female1761=January name.female1762=Janyce name.female1763=Jaqueline name.female1764=Jaquelyn name.female1765=Jasmin name.female1766=Jasmine name.female1767=Jason name.female1768=Jassie name.female1769=Jaunita name.female1770=Jay name.female1771=Jaye name.female1772=Jayme name.female1773=Jaymie name.female1774=Jayna name.female1775=Jayne name.female1776=Jazmin name.female1777=Jazmine name.female1778=Jean name.female1779=Jeana name.female1780=Jeane name.female1781=Jeanelle name.female1782=Jeanene name.female1783=Jeanett name.female1784=Jeanetta name.female1785=Jeanette name.female1786=Jeanice name.female1787=Jeanie name.female1788=Jeanine name.female1789=Jeanmarie name.female1790=Jeanna name.female1791=Jeanne name.female1792=Jeannetta name.female1793=Jeannette name.female1794=Jeannie name.female1795=Jeannine name.female1796=Jeffie name.female1797=Jeffrey name.female1798=Jen name.female1799=Jena name.female1800=Jenae name.female1801=Jene name.female1802=Jenee name.female1803=Jenell name.female1804=Jenelle name.female1805=Jenette name.female1806=Jeneva name.female1807=Jeni name.female1808=Jenice name.female1809=Jenifer name.female1810=Jeniffer name.female1811=Jenine name.female1812=Jenise name.female1813=Jenna name.female1814=Jennefer name.female1815=Jennell name.female1816=Jennette name.female1817=Jenni name.female1818=Jennie name.female1819=Jennifer name.female1820=Jenniffer name.female1821=Jennine name.female1822=Jenny name.female1823=Jeraldine name.female1824=Jeremy name.female1825=Jeri name.female1826=Jerica name.female1827=Jerilyn name.female1828=Jerlene name.female1829=Jerri name.female1830=Jerrica name.female1831=Jerrie name.female1832=Jerry name.female1833=Jesenia name.female1834=Jesica name.female1835=Jesse name.female1836=Jessenia name.female1837=Jessi name.female1838=Jessia name.female1839=Jessica name.female1840=Jessie name.female1841=Jessika name.female1842=Jessimine name.female1843=Jestine name.female1844=Jesus name.female1845=Jesusa name.female1846=Jesusita name.female1847=Jetta name.female1848=Jettie name.female1849=Jewel name.female1850=Jewell name.female1851=Jill name.female1852=Jillian name.female1853=Jimmie name.female1854=Jimmy name.female1855=Jin name.female1856=Jina name.female1857=Jinny name.female1858=Joan name.female1859=Joana name.female1860=Joane name.female1861=Joanie name.female1862=Joann name.female1863=Joanna name.female1864=Joanne name.female1865=Joannie name.female1866=Joaquina name.female1867=Jocelyn name.female1868=Jodee name.female1869=Jodi name.female1870=Jodie name.female1871=Jody name.female1872=Joeann name.female1873=Joel name.female1874=Joella name.female1875=Joelle name.female1876=Joellen name.female1877=Joetta name.female1878=Joette name.female1879=Joey name.female1880=Johana name.female1881=Johanna name.female1882=Johanne name.female1883=John name.female1884=Johna name.female1885=Johnetta name.female1886=Johnette name.female1887=Johnie name.female1888=Johnna name.female1889=Johnnie name.female1890=Johnny name.female1891=Johnsie name.female1892=Joie name.female1893=Jolanda name.female1894=Joleen name.female1895=Jolene name.female1896=Jolie name.female1897=Joline name.female1898=Jolyn name.female1899=Jolynn name.female1900=Jona name.female1901=Jone name.female1902=Jonell name.female1903=Jonelle name.female1904=Jong name.female1905=Joni name.female1906=Jonie name.female1907=Jonna name.female1908=Jonnie name.female1909=Jordan name.female1910=Jose name.female1911=Josefa name.female1912=Josefina name.female1913=Josefine name.female1914=Joselyn name.female1915=Joseph name.female1916=Josephina name.female1917=Josephine name.female1918=Josette name.female1919=Joshua name.female1920=Josie name.female1921=Joslyn name.female1922=Josphine name.female1923=Jovan name.female1924=Jovita name.female1925=Joy name.female1926=Joya name.female1927=Joyce name.female1928=Joycelyn name.female1929=Joye name.female1930=Juan name.female1931=Juana name.female1932=Juanita name.female1933=Jubilee name.female1934=Jude name.female1935=Judi name.female1936=Judie name.female1937=Judith name.female1938=Judy name.female1939=Jule name.female1940=Julee name.female1941=Julene name.female1942=Juli name.female1943=Julia name.female1944=Julian name.female1945=Juliana name.female1946=Juliane name.female1947=Juliann name.female1948=Julianna name.female1949=Julianne name.female1950=Julie name.female1951=Julieann name.female1952=Julienne name.female1953=Juliet name.female1954=Julieta name.female1955=Julietta name.female1956=Juliette name.female1957=Julio name.female1958=Julissa name.female1959=June name.female1960=Jung name.female1961=Junie name.female1962=Junita name.female1963=Junko name.female1964=Justa name.female1965=Justin name.female1966=Justina name.female1967=Justine name.female1968=Jutta name.female1969=Kacey name.female1970=Kaci name.female1971=Kacie name.female1972=Kacy name.female1973=Kai name.female1974=Kaila name.female1975=Kaitlin name.female1976=Kaitlyn name.female1977=Kala name.female1978=Kaleigh name.female1979=Kaley name.female1980=Kali name.female1981=Kallie name.female1982=Kalyn name.female1983=Kamala name.female1984=Kami name.female1985=Kamilah name.female1986=Kandace name.female1987=Kandi name.female1988=Kandice name.female1989=Kandis name.female1990=Kandra name.female1991=Kandy name.female1992=Kanesha name.female1993=Kanisha name.female1994=Kara name.female1995=Kara-May name.female1996=Karan name.female1997=Kareen name.female1998=Karen name.female1999=Karena name.female2000=Karey name.female2001=Kari name.female2002=Karie name.female2003=Karima name.female2004=Karin name.female2005=Karina name.female2006=Karine name.female2007=Karisa name.female2008=Karissa name.female2009=Karl name.female2010=Karla name.female2011=Karleen name.female2012=Karlene name.female2013=Karly name.female2014=Karlyn name.female2015=Karma name.female2016=Karmen name.female2017=Karol name.female2018=Karole name.female2019=Karoline name.female2020=Karolyn name.female2021=Karon name.female2022=Karren name.female2023=Karri name.female2024=Karrie name.female2025=Karry name.female2026=Kary name.female2027=Karyl name.female2028=Karyn name.female2029=Kasandra name.female2030=Kasey name.female2031=Kasha name.female2032=Kasi name.female2033=Kasie name.female2034=Kassandra name.female2035=Kassie name.female2036=Kate name.female2037=Katelin name.female2038=Katelyn name.female2039=Katelynn name.female2040=Katerine name.female2041=Kathaleen name.female2042=Katharina name.female2043=Katharine name.female2044=Katharyn name.female2045=Kathe name.female2046=Katheleen name.female2047=Katherin name.female2048=Katherina name.female2049=Katherine name.female2050=Kathern name.female2051=Katheryn name.female2052=Kathey name.female2053=Kathi name.female2054=Kathie name.female2055=Kathleen name.female2056=Kathlene name.female2057=Kathline name.female2058=Kathlyn name.female2059=Kathrin name.female2060=Kathrine name.female2061=Kathryn name.female2062=Kathryne name.female2063=Kathy name.female2064=Kathyrn name.female2065=Kati name.female2066=Katia name.female2067=Katie name.female2068=Katina name.female2069=Katlyn name.female2070=Katrice name.female2071=Katrina name.female2072=Kattie name.female2073=Katy name.female2074=Kay name.female2075=Kayce name.female2076=Kaycee name.female2077=Kaye name.female2078=Kayla name.female2079=Kaylee name.female2080=Kayleen name.female2081=Kayleigh name.female2082=Kaylene name.female2083=Kazuko name.female2084=Kecia name.female2085=Keeley name.female2086=Keely name.female2087=Keena name.female2088=Keesha name.female2089=Keiko name.female2090=Keila name.female2091=Keira name.female2092=Keisha name.female2093=Keith name.female2094=Keitha name.female2095=Keli name.female2096=Kelle name.female2097=Kellee name.female2098=Kelley name.female2099=Kelli name.female2100=Kellie name.female2101=Kelly name.female2102=Kellye name.female2103=Kelsey name.female2104=Kelsi name.female2105=Kelsie name.female2106=Kemberly name.female2107=Kena name.female2108=Kenda name.female2109=Kendal name.female2110=Kendall name.female2111=Kendra name.female2112=Kenia name.female2113=Kenisha name.female2114=Kenna name.female2115=Kenneth name.female2116=Kenya name.female2117=Kenyatta name.female2118=Kenyetta name.female2119=Kera name.female2120=Keren name.female2121=Keri name.female2122=Kerri name.female2123=Kerrie name.female2124=Kerry name.female2125=Kerstin name.female2126=Kesha name.female2127=Keshia name.female2128=Keturah name.female2129=Keva name.female2130=Kevin name.female2131=Khadijah name.female2132=Khalilah name.female2133=Kia name.female2134=Kiana name.female2135=Kiara name.female2136=Kiera name.female2137=Kiersten name.female2138=Kiesha name.female2139=Kiley name.female2140=Kim name.female2141=Kimber name.female2142=Kimberely name.female2143=Kimberlee name.female2144=Kimberley name.female2145=Kimberli name.female2146=Kimberlie name.female2147=Kimberly name.female2148=Kimbery name.female2149=Kimbra name.female2150=Kimi name.female2151=Kimiko name.female2152=Kina name.female2153=Kindra name.female2154=Kira name.female2155=Kirby name.female2156=Kirsten name.female2157=Kirstie name.female2158=Kirstin name.female2159=Kisha name.female2160=Kit name.female2161=Kittie name.female2162=Kitty name.female2163=Kiyoko name.female2164=Kizzie name.female2165=Kizzy name.female2166=Klara name.female2167=Kori name.female2168=Kortney name.female2169=Kourtney name.female2170=Kris name.female2171=Krishna name.female2172=Krissy name.female2173=Krista name.female2174=Kristal name.female2175=Kristan name.female2176=Kristeen name.female2177=Kristel name.female2178=Kristen name.female2179=Kristi name.female2180=Kristian name.female2181=Kristie name.female2182=Kristin name.female2183=Kristina name.female2184=Kristine name.female2185=Kristle name.female2186=Kristy name.female2187=Kristyn name.female2188=Krysta name.female2189=Krystal name.female2190=Krysten name.female2191=Krystin name.female2192=Krystina name.female2193=Krystle name.female2194=Krystyna name.female2195=Kyla name.female2196=Kyle name.female2197=Kylee name.female2198=Kylie name.female2199=Kymberly name.female2200=Kyoko name.female2201=Kyong name.female2202=Kyra name.female2203=Kyung name.female2204=Lacey name.female2205=Lachelle name.female2206=Laci name.female2207=Lacie name.female2208=Lacresha name.female2209=Lacy name.female2210=Ladawn name.female2211=Ladonna name.female2212=Lady name.female2213=Lael name.female2214=Lahoma name.female2215=Lai name.female2216=Laila name.female2217=Laine name.female2218=Lajuana name.female2219=Lakeesha name.female2220=Lakeisha name.female2221=Lakendra name.female2222=Lakenya name.female2223=Lakesha name.female2224=Lakeshia name.female2225=Lakia name.female2226=Lakiesha name.female2227=Lakisha name.female2228=Lakita name.female2229=Lala name.female2230=Lamonica name.female2231=Lan name.female2232=Lana name.female2233=Lane name.female2234=Lanell name.female2235=Lanelle name.female2236=Lanette name.female2237=Lang name.female2238=Lani name.female2239=Lanie name.female2240=Lanita name.female2241=Lannie name.female2242=Lanora name.female2243=Laquanda name.female2244=Laquita name.female2245=Lara name.female2246=Larae name.female2247=Laraine name.female2248=Laree name.female2249=Larhonda name.female2250=Larisa name.female2251=Larissa name.female2252=Larita name.female2253=Laronda name.female2254=Larraine name.female2255=Larry name.female2256=Larue name.female2257=Lasandra name.female2258=Lashanda name.female2259=Lashandra name.female2260=Lashaun name.female2261=Lashaunda name.female2262=Lashawn name.female2263=Lashawna name.female2264=Lashawnda name.female2265=Lashay name.female2266=Lashell name.female2267=Lashon name.female2268=Lashonda name.female2269=Lashunda name.female2270=Lasonya name.female2271=Latanya name.female2272=Latarsha name.female2273=Latasha name.female2274=Latashia name.female2275=Latesha name.female2276=Latia name.female2277=Laticia name.female2278=Latina name.female2279=Latisha name.female2280=Latonia name.female2281=Latonya name.female2282=Latoria name.female2283=Latosha name.female2284=Latoya name.female2285=Latoyia name.female2286=Latrice name.female2287=Latricia name.female2288=Latrina name.female2289=Latrisha name.female2290=Launa name.female2291=Laura name.female2292=Lauralee name.female2293=Lauran name.female2294=Laure name.female2295=Laureen name.female2296=Laurel name.female2297=Lauren name.female2298=Laurena name.female2299=Laurence name.female2300=Laurene name.female2301=Lauretta name.female2302=Laurette name.female2303=Lauri name.female2304=Laurice name.female2305=Laurie name.female2306=Laurinda name.female2307=Laurine name.female2308=Lauryn name.female2309=Lavada name.female2310=Lavelle name.female2311=Lavenia name.female2312=Lavera name.female2313=Lavern name.female2314=Laverna name.female2315=Laverne name.female2316=Laveta name.female2317=Lavette name.female2318=Lavina name.female2319=Lavinia name.female2320=Lavon name.female2321=Lavona name.female2322=Lavonda name.female2323=Lavone name.female2324=Lavonia name.female2325=Lavonna name.female2326=Lavonne name.female2327=Lawana name.female2328=Lawanda name.female2329=Lawanna name.female2330=Lawrence name.female2331=Layla name.female2332=Layne name.female2333=Lea name.female2334=Leah name.female2335=Lean name.female2336=Leana name.female2337=Leandra name.female2338=Leann name.female2339=Leanna name.female2340=Leanne name.female2341=Leanora name.female2342=Leatha name.female2343=Leatrice name.female2344=Lecia name.female2345=Leda name.female2346=Lee name.female2347=Leeann name.female2348=Leeanna name.female2349=Leeanne name.female2350=Leena name.female2351=Leesa name.female2352=Leia name.female2353=Leida name.female2354=Leigh name.female2355=Leigha name.female2356=Leighann name.female2357=Leila name.female2358=Leilani name.female2359=Leisa name.female2360=Leisha name.female2361=Lekisha name.female2362=Lela name.female2363=Lelah name.female2364=Lelia name.female2365=Lena name.female2366=Lenita name.female2367=Lenna name.female2368=Lennie name.female2369=Lenora name.female2370=Lenore name.female2371=Leola name.female2372=Leoma name.female2373=Leon name.female2374=Leona name.female2375=Leonarda name.female2376=Leone name.female2377=Leonia name.female2378=Leonida name.female2379=Leonie name.female2380=Leonila name.female2381=Leonor name.female2382=Leonora name.female2383=Leonore name.female2384=Leontine name.female2385=Leora name.female2386=Leota name.female2387=Lera name.female2388=Lesa name.female2389=Lesha name.female2390=Lesia name.female2391=Leslee name.female2392=Lesley name.female2393=Lesli name.female2394=Leslie name.female2395=Leslie-Annie name.female2396=Lessie name.female2397=Lester name.female2398=Leta name.female2399=Letha name.female2400=Leticia name.female2401=Letisha name.female2402=Letitia name.female2403=Lettie name.female2404=Letty name.female2405=Lewis name.female2406=Lexie name.female2407=Lezlie name.female2408=Lia name.female2409=Liana name.female2410=Liane name.female2411=Lianne name.female2412=Libbie name.female2413=Libby name.female2414=Liberty name.female2415=Librada name.female2416=Lida name.female2417=Lidia name.female2418=Lidya name.female2419=Lien name.female2420=Lieselotte name.female2421=Ligia name.female2422=Lila name.female2423=Lili name.female2424=Lilia name.female2425=Lilian name.female2426=Liliana name.female2427=Lilith name.female2428=Lilla name.female2429=Lilli name.female2430=Lillia name.female2431=Lilliam name.female2432=Lillian name.female2433=Lilliana name.female2434=Lillie name.female2435=Lilly name.female2436=Lily name.female2437=Lin name.female2438=Lina name.female2439=Linda name.female2440=Lindsay name.female2441=Lindsey name.female2442=Lindsy name.female2443=Lindy name.female2444=Linette name.female2445=Ling name.female2446=Linh name.female2447=Linn name.female2448=Linnea name.female2449=Linnie name.female2450=Linsey name.female2451=Lisa name.female2452=Lisabeth name.female2453=Lisandra name.female2454=Lisbeth name.female2455=Lise name.female2456=Lisette name.female2457=Lisha name.female2458=Lissa name.female2459=Lissette name.female2460=Lita name.female2461=Livia name.female2462=Liz name.female2463=Liza name.female2464=Lizabeth name.female2465=Lizbeth name.female2466=Lizeth name.female2467=Lizette name.female2468=Lizzette name.female2469=Lizzie name.female2470=Lizzy name.female2471=Loan name.female2472=Logan name.female2473=Loida name.female2474=Lois name.female2475=Loise name.female2476=Lola name.female2477=Lolita name.female2478=Loma name.female2479=Lona name.female2480=Londa name.female2481=London name.female2482=Loni name.female2483=Lonna name.female2484=Lonnie name.female2485=Lora name.female2486=Loraine name.female2487=Loralee name.female2488=Lore name.female2489=Lorean name.female2490=Loree name.female2491=Loreen name.female2492=Lorelei name.female2493=Loren name.female2494=Lorena name.female2495=Lorene name.female2496=Lorenza name.female2497=Loreta name.female2498=Loretta name.female2499=Lorette name.female2500=Lori name.female2501=Loria name.female2502=Loriann name.female2503=Lorie name.female2504=Lorilee name.female2505=Lorina name.female2506=Lorinda name.female2507=Lorine name.female2508=Loris name.female2509=Lorita name.female2510=Lorna name.female2511=Lorraine name.female2512=Lorretta name.female2513=Lorri name.female2514=Lorriane name.female2515=Lorrie name.female2516=Lorrine name.female2517=Lory name.female2518=Lottie name.female2519=Lotus name.female2520=Louann name.female2521=Louanne name.female2522=Louella name.female2523=Louetta name.female2524=Louie name.female2525=Louis name.female2526=Louisa name.female2527=Louise name.female2528=Loura name.female2529=Lourdes name.female2530=Lourie name.female2531=Louvenia name.female2532=Love name.female2533=Lovella name.female2534=Lovetta name.female2535=Lovie name.female2536=Loyce name.female2537=Luana name.female2538=Luann name.female2539=Luanna name.female2540=Luanne name.female2541=Luba name.female2542=Luci name.female2543=Lucia name.female2544=Luciana name.female2545=Lucie name.female2546=Lucienne name.female2547=Lucila name.female2548=Lucile name.female2549=Lucilla name.female2550=Lucille name.female2551=Lucina name.female2552=Lucinda name.female2553=Lucine name.female2554=Lucrecia name.female2555=Lucretia name.female2556=Lucy name.female2557=Ludie name.female2558=Ludivina name.female2559=Lue name.female2560=Luella name.female2561=Luetta name.female2562=Luis name.female2563=Luisa name.female2564=Luise name.female2565=Lula name.female2566=Lulu name.female2567=Luna name.female2568=Lupe name.female2569=Lupita name.female2570=Lura name.female2571=Lurlene name.female2572=Lurline name.female2573=Luvenia name.female2574=Lyda name.female2575=Lydia name.female2576=Lyla name.female2577=Lyn name.female2578=Lynda name.female2579=Lyndia name.female2580=Lyndsay name.female2581=Lyndsey name.female2582=Lynell name.female2583=Lynelle name.female2584=Lynetta name.female2585=Lynette name.female2586=Lynn name.female2587=Lynna name.female2588=Lynne name.female2589=Lynnette name.female2590=Lynsey name.female2591=Lyric name.female2592=Mabel name.female2593=Mabelle name.female2594=Mable name.female2595=Macey name.female2596=Machelle name.female2597=Maci name.female2598=Macie name.female2599=Mackenzie name.female2600=Macy name.female2601=Madalene name.female2602=Madaline name.female2603=Madalyn name.female2604=Maddie name.female2605=Madelaine name.female2606=Madeleine name.female2607=Madelene name.female2608=Madeline name.female2609=Madelyn name.female2610=Madge name.female2611=Madie name.female2612=Madison name.female2613=Madlyn name.female2614=Madonna name.female2615=Mae name.female2616=Maegan name.female2617=Mafalda name.female2618=Magali name.female2619=Magaly name.female2620=Magan name.female2621=Magaret name.female2622=Magda name.female2623=Magdalen name.female2624=Magdalena name.female2625=Magdalene name.female2626=Magen name.female2627=Maggie name.female2628=Magnolia name.female2629=Mahalia name.female2630=Mai name.female2631=Maia name.female2632=Maida name.female2633=Maile name.female2634=Maira name.female2635=Maire name.female2636=Maisha name.female2637=Maisie name.female2638=Majorie name.female2639=Makeda name.female2640=Malana name.female2641=Malena name.female2642=Malia name.female2643=Malika name.female2644=Malinda name.female2645=Malisa name.female2646=Malissa name.female2647=Malka name.female2648=Mallie name.female2649=Mallory name.female2650=Malorie name.female2651=Malvina name.female2652=Mamie name.female2653=Mammie name.female2654=Mana name.female2655=Manda name.female2656=Mandi name.female2657=Mandie name.female2658=Mandy name.female2659=Manie name.female2660=Manuela name.female2661=Many name.female2662=Mao name.female2663=Maple name.female2664=Mara name.female2665=Maragaret name.female2666=Maragret name.female2667=Maranda name.female2668=Marcela name.female2669=Marcelene name.female2670=Marcelina name.female2671=Marceline name.female2672=Marcell name.female2673=Marcella name.female2674=Marcelle name.female2675=Marcene name.female2676=Marchelle name.female2677=Marci name.female2678=Marcia name.female2679=Marcie name.female2680=Marcy name.female2681=Mardell name.female2682=Maren name.female2683=Marg name.female2684=Margaret name.female2685=Margareta name.female2686=Margarete name.female2687=Margarett name.female2688=Margaretta name.female2689=Margarette name.female2690=Margarita name.female2691=Margarite name.female2692=Margart name.female2693=Marge name.female2694=Margene name.female2695=Margeret name.female2696=Margert name.female2697=Margery name.female2698=Marget name.female2699=Margherita name.female2700=Margie name.female2701=Margit name.female2702=Margo name.female2703=Margorie name.female2704=Margot name.female2705=Margret name.female2706=Margrett name.female2707=Marguerita name.female2708=Marguerite name.female2709=Margurite name.female2710=Margy name.female2711=Marhta name.female2712=Mari name.female2713=Maria name.female2714=Mariah name.female2715=Mariam name.female2716=Marian name.female2717=Mariana name.female2718=Marianela name.female2719=Mariann name.female2720=Marianna name.female2721=Marianne name.female2722=Maribel name.female2723=Maribeth name.female2724=Marica name.female2725=Maricela name.female2726=Maricruz name.female2727=Marie name.female2728=Mariel name.female2729=Mariela name.female2730=Mariella name.female2731=Marielle name.female2732=Marietta name.female2733=Mariette name.female2734=Mariko name.female2735=Marilee name.female2736=Marilou name.female2737=Marilu name.female2738=Marilyn name.female2739=Marilynn name.female2740=Marin name.female2741=Marina name.female2742=Marinda name.female2743=Marine name.female2744=Mario name.female2745=Marion name.female2746=Marioth name.female2747=Maris name.female2748=Marisa name.female2749=Marisela name.female2750=Marisha name.female2751=Marisol name.female2752=Marissa name.female2753=Marita name.female2754=Maritza name.female2755=Marivel name.female2756=Marjorie name.female2757=Marjory name.female2758=Mark name.female2759=Marketta name.female2760=Markita name.female2761=Marla name.female2762=Marlana name.female2763=Marleen name.female2764=Marlen name.female2765=Marlena name.female2766=Marlene name.female2767=Marlin name.female2768=Marline name.female2769=Marlo name.female2770=Marlyn name.female2771=Marlys name.female2772=Marna name.female2773=Marni name.female2774=Marnie name.female2775=Marquerite name.female2776=Marquetta name.female2777=Marquita name.female2778=Marquitta name.female2779=Marry name.female2780=Marsha name.female2781=Marshall name.female2782=Marta name.female2783=Marth name.female2784=Martha name.female2785=Marti name.female2786=Martin name.female2787=Martina name.female2788=Martine name.female2789=Marty name.female2790=Marva name.female2791=Marvel name.female2792=Marvella name.female2793=Marvis name.female2794=Marx name.female2795=Mary name.female2796=Mary-Anne name.female2797=Marya name.female2798=Maryalice name.female2799=Maryam name.female2800=Maryann name.female2801=Maryanna name.female2802=Maryanne name.female2803=Marybelle name.female2804=Marybeth name.female2805=Maryellen name.female2806=Maryetta name.female2807=Maryjane name.female2808=Maryjo name.female2809=Maryland name.female2810=Marylee name.female2811=Marylin name.female2812=Maryln name.female2813=Marylou name.female2814=Marylouise name.female2815=Marylyn name.female2816=Marylynn name.female2817=Maryrose name.female2818=Masako name.female2819=Matha name.female2820=Mathilda name.female2821=Mathilde name.female2822=Matilda name.female2823=Matilde name.female2824=Matthew name.female2825=Mattie name.female2826=Maud name.female2827=Maude name.female2828=Maudie name.female2829=Maura name.female2830=Maureen name.female2831=Maurice name.female2832=Maurine name.female2833=Maurita name.female2834=Mavis name.female2835=Maxie name.female2836=Maxima name.female2837=Maximina name.female2838=Maxine name.female2839=May name.female2840=Maya name.female2841=Maybell name.female2842=Maybelle name.female2843=Mayberry name.female2844=Maye name.female2845=Mayflower name.female2846=Mayme name.female2847=Mayola name.female2848=Mayra name.female2849=Mazie name.female2850=Mckenzie name.female2851=Meagan name.female2852=Meaghan name.female2853=Mechelle name.female2854=Meda name.female2855=Meg name.female2856=Megan name.female2857=Meggan name.female2858=Meghan name.female2859=Meghann name.female2860=Mei name.female2861=Melaine name.female2862=Melani name.female2863=Melania name.female2864=Melanie name.female2865=Melany name.female2866=Melba name.female2867=Melda name.female2868=Melia name.female2869=Melida name.female2870=Melina name.female2871=Melinda name.female2872=Melisa name.female2873=Melissa name.female2874=Melissia name.female2875=Melita name.female2876=Mellie name.female2877=Mellisa name.female2878=Mellissa name.female2879=Melodee name.female2880=Melodi name.female2881=Melodie name.female2882=Melody name.female2883=Melonie name.female2884=Melony name.female2885=Melva name.female2886=Melvin name.female2887=Melvina name.female2888=Melynda name.female2889=Mendy name.female2890=Mercedes name.female2891=Mercedez name.female2892=Mercy name.female2893=Meredith name.female2894=Meri name.female2895=Merideth name.female2896=Meridith name.female2897=Merilyn name.female2898=Merissa name.female2899=Merle name.female2900=Merlene name.female2901=Merlyn name.female2902=Merna name.female2903=Merri name.female2904=Merrie name.female2905=Merrilee name.female2906=Merrill name.female2907=Merry name.female2908=Mertie name.female2909=Meryl name.female2910=Meta name.female2911=Mia name.female2912=Mica name.female2913=Micaela name.female2914=Micah name.female2915=Micha name.female2916=Michael name.female2917=Michaela name.female2918=Michaele name.female2919=Michal name.female2920=Micheal name.female2921=Michel name.female2922=Michele name.female2923=Michelina name.female2924=Micheline name.female2925=Michell name.female2926=Michelle name.female2927=Michiko name.female2928=Mickey name.female2929=Micki name.female2930=Mickie name.female2931=Miesha name.female2932=Migdalia name.female2933=Mignon name.female2934=Miguelina name.female2935=Mika name.female2936=Mikaela name.female2937=Mike name.female2938=Miki name.female2939=Mikki name.female2940=Mila name.female2941=Milagro name.female2942=Milagros name.female2943=Milda name.female2944=Mildred name.female2945=Milissa name.female2946=Millicent name.female2947=Millie name.female2948=Milly name.female2949=Mimi name.female2950=Min name.female2951=Mina name.female2952=Minda name.female2953=Mindi name.female2954=Mindy name.female2955=Minerva name.female2956=Ming name.female2957=Minh name.female2958=Minna name.female2959=Minnie name.female2960=Minta name.female2961=Mira name.female2962=Miranda name.female2963=Mireille name.female2964=Mirella name.female2965=Mireya name.female2966=Miriam name.female2967=Mirian name.female2968=Mirna name.female2969=Mirta name.female2970=Mirtha name.female2971=Misha name.female2972=Miss name.female2973=Missy name.female2974=Misti name.female2975=Mistie name.female2976=Misty name.female2977=Mitchell name.female2978=Mitsue name.female2979=Mitsuko name.female2980=Mittie name.female2981=Mitzi name.female2982=Mitzie name.female2983=Miyoko name.female2984=Modesta name.female2985=Moira name.female2986=Mollie name.female2987=Molly name.female2988=Mona name.female2989=Monet name.female2990=Monica name.female2991=Monika name.female2992=Monique name.female2993=Monnie name.female2994=Monserrate name.female2995=Moon name.female2996=Mora name.female2997=Morgan name.female2998=Morgana name.female2999=Moriah name.female3000=Mozell name.female3001=Mozella name.female3002=Mozelle name.female3003=Mui name.female3004=Muoi name.female3005=Muriel name.female3006=Mya name.female3007=Myesha name.female3008=Myong name.female3009=Myra name.female3010=Myriam name.female3011=Myrl name.female3012=Myrle name.female3013=Myrna name.female3014=Myrta name.female3015=Myrtice name.female3016=Myrtie name.female3017=Myrtis name.female3018=Myrtle name.female3019=Myung name.female3020=Nada name.female3021=Nadene name.female3022=Nadia name.female3023=Nadine name.female3024=Naida name.female3025=Nakesha name.female3026=Nakia name.female3027=Nakisha name.female3028=Nakita name.female3029=Nam name.female3030=Nan name.female3031=Nana name.female3032=Nancee name.female3033=Nancey name.female3034=Nanci name.female3035=Nancie name.female3036=Nancy name.female3037=Nanette name.female3038=Nani name.female3039=Nannette name.female3040=Nannie name.female3041=Naoma name.female3042=Naomi name.female3043=Narcisa name.female3044=Natacha name.female3045=Natalia name.female3046=Natalie name.female3047=Natalya name.female3048=Natasha name.female3049=Natashia name.female3050=Nathalie name.female3051=Natisha name.female3052=Natividad name.female3053=Natosha name.female3054=Necole name.female3055=Neda name.female3056=Nedra name.female3057=Neely name.female3058=Neida name.female3059=Nelda name.female3060=Nelia name.female3061=Nelida name.female3062=Nell name.female3063=Nella name.female3064=Nelle name.female3065=Nellie name.female3066=Nelly name.female3067=Nena name.female3068=Nenita name.female3069=Neoma name.female3070=Neomi name.female3071=Nereida name.female3072=Nerissa name.female3073=Nery name.female3074=Neta name.female3075=Nettie name.female3076=Neva name.female3077=Nevada name.female3078=Ngan name.female3079=Ngoc name.female3080=Nguyet name.female3081=Nia name.female3082=Nichelle name.female3083=Nichol name.female3084=Nichole name.female3085=Nicholle name.female3086=Nicki name.female3087=Nickie name.female3088=Nickole name.female3089=Nicky name.female3090=Nicol name.female3091=Nicola name.female3092=Nicolasa name.female3093=Nicole name.female3094=Nicolette name.female3095=Nicolle name.female3096=Nida name.female3097=Nidia name.female3098=Niesha name.female3099=Nieves name.female3100=Niki name.female3101=Nikia name.female3102=Nikita name.female3103=Nikki name.female3104=Nikole name.female3105=Nila name.female3106=Nilda name.female3107=Nilsa name.female3108=Nina name.female3109=Ninfa name.female3110=Nisha name.female3111=Nita name.female3112=Nobuko name.female3113=Noel name.female3114=Noelia name.female3115=Noella name.female3116=Noelle name.female3117=Noemi name.female3118=Nohemi name.female3119=Nola name.female3120=Noma name.female3121=Nona name.female3122=Nora name.female3123=Norah name.female3124=Noreen name.female3125=Norene name.female3126=Noriko name.female3127=Norine name.female3128=Norma name.female3129=Norman name.female3130=Nova name.female3131=Novella name.female3132=Nubia name.female3133=Numbers name.female3134=Nydia name.female3135=Nyla name.female3136=Obdulia name.female3137=Ocie name.female3138=Octavia name.female3139=Oda name.female3140=Odelia name.female3141=Odell name.female3142=Odessa name.female3143=Odette name.female3144=Odilia name.female3145=Ofelia name.female3146=Ola name.female3147=Olene name.female3148=Oleta name.female3149=Olevia name.female3150=Olga name.female3151=Olimpia name.female3152=Olinda name.female3153=Oliva name.female3154=Olive name.female3155=Olivia name.female3156=Ollie name.female3157=Olympia name.female3158=Oma name.female3159=Omega name.female3160=Ona name.female3161=Oneida name.female3162=Onie name.female3163=Onita name.female3164=Opal name.female3165=Ophelia name.female3166=Ora name.female3167=Oralee name.female3168=Oralia name.female3169=Oretha name.female3170=Orpha name.female3171=Oscar name.female3172=Ossie name.female3173=Otelia name.female3174=Otha name.female3175=Otilia name.female3176=Ouida name.female3177=Ozell name.female3178=Ozella name.female3179=Ozie name.female3180=Page name.female3181=Paige name.female3182=Palma name.female3183=Palmira name.female3184=Pam name.female3185=Pamala name.female3186=Pamela name.female3187=Pamela-May name.female3188=Pamelia name.female3189=Pamella name.female3190=Pamila name.female3191=Pamula name.female3192=Pandora name.female3193=Pansy name.female3194=Paola name.female3195=Paris name.female3196=Parthenia name.female3197=Particia name.female3198=Pasty name.female3199=Pat name.female3200=Patience name.female3201=Patria name.female3202=Patrica name.female3203=Patrice name.female3204=Patricia name.female3205=Patrick name.female3206=Patrina name.female3207=Patsy name.female3208=Patti name.female3209=Pattie name.female3210=Patty name.female3211=Paul name.female3212=Paula name.female3213=Paulene name.female3214=Pauletta name.female3215=Paulette name.female3216=Paulina name.female3217=Pauline name.female3218=Paulita name.female3219=Paysley name.female3220=Paz name.female3221=Pearl name.female3222=Pearle name.female3223=Pearlene name.female3224=Pearlie name.female3225=Pearline name.female3226=Pearly name.female3227=Peg name.female3228=Peggie name.female3229=Peggy name.female3230=Pei name.female3231=Penelope name.female3232=Penney name.female3233=Penni name.female3234=Pennie name.female3235=Penny name.female3236=Peony name.female3237=Perla name.female3238=Perry name.female3239=Petal name.female3240=Peter name.female3241=Petra name.female3242=Petrina name.female3243=Petronila name.female3244=Petunia name.female3245=Phebe name.female3246=Phillis name.female3247=Philomena name.female3248=Phoebe name.female3249=Phung name.female3250=Phuong name.female3251=Phylicia name.female3252=Phylis name.female3253=Phyliss name.female3254=Phyllis name.female3255=Pia name.female3256=Piedad name.female3257=Pilar name.female3258=Ping name.female3259=Pinkie name.female3260=Piper name.female3261=Pok name.female3262=Polly name.female3263=Poppy name.female3264=Porsche name.female3265=Porsha name.female3266=Portia name.female3267=Precious name.female3268=Presley name.female3269=Pricilla name.female3270=Princess name.female3271=Priscila name.female3272=Priscilla name.female3273=Providencia name.female3274=Prudence name.female3275=Pura name.female3276=Qiana name.female3277=Queen name.female3278=Queenie name.female3279=Quiana name.female3280=Quinn name.female3281=Quyen name.female3282=Rachael name.female3283=Rachal name.female3284=Racheal name.female3285=Rachel name.female3286=Rachele name.female3287=Rachell name.female3288=Rachelle name.female3289=Racquel name.female3290=Rae name.female3291=Raeann name.female3292=Raelene name.female3293=Rafaela name.female3294=Raguel name.female3295=Raina name.female3296=Raisa name.female3297=Ramona name.female3298=Ramonita name.female3299=Rana name.female3300=Ranae name.female3301=Randa name.female3302=Randee name.female3303=Randi name.female3304=Randy name.female3305=Ranee name.female3306=Raquel name.female3307=Rasheeda name.female3308=Rashida name.female3309=Raven name.female3310=Ray name.female3311=Ray-Annie name.female3312=Raye name.female3313=Raylene name.female3314=Raymond name.female3315=Raymonde name.female3316=Rayna name.female3317=Rayne name.female3318=Reagan name.female3319=Reanna name.female3320=Reatha name.female3321=Reba name.female3322=Rebbeca name.female3323=Rebbecca name.female3324=Rebeca name.female3325=Rebecca name.female3326=Rebecka name.female3327=Rebekah name.female3328=Reda name.female3329=Reena name.female3330=Refugia name.female3331=Refugio name.female3332=Regan name.female3333=Regena name.female3334=Regenia name.female3335=Regina name.female3336=Regine name.female3337=Reginia name.female3338=Reiko name.female3339=Reina name.female3340=Reita name.female3341=Rema name.female3342=Remedios name.female3343=Remona name.female3344=Rena name.female3345=Renae name.female3346=Renata name.female3347=Renate name.female3348=Renay name.female3349=Renda name.female3350=Rene name.female3351=Renea name.female3352=Renee name.female3353=Renetta name.female3354=Renita name.female3355=Renna name.female3356=Ressie name.female3357=Reta name.female3358=Retha name.female3359=Retta name.female3360=Reva name.female3361=Reyna name.female3362=Reynalda name.female3363=Rhea name.female3364=Rheba name.female3365=Rhiannon name.female3366=Rhoda name.female3367=Rhona name.female3368=Rhonda name.female3369=Ria name.female3370=Ricarda name.female3371=Richard name.female3372=Richelle name.female3373=Ricki name.female3374=Rickie name.female3375=Rikki name.female3376=Rima name.female3377=Rina name.female3378=Risa name.female3379=Rita name.female3380=Riva name.female3381=Rivka name.female3382=Robbi name.female3383=Robbie name.female3384=Robbin name.female3385=Robbyn name.female3386=Robena name.female3387=Robert name.female3388=Roberta name.female3389=Roberto name.female3390=Robin name.female3391=Robyn name.female3392=Rochel name.female3393=Rochell name.female3394=Rochelle name.female3395=Rocio name.female3396=Rolanda name.female3397=Rolande name.female3398=Roma name.female3399=Romaine name.female3400=Romana name.female3401=Romelia name.female3402=Romona name.female3403=Rona name.female3404=Ronald name.female3405=Ronda name.female3406=Roni name.female3407=Ronna name.female3408=Ronni name.female3409=Ronnie name.female3410=Rory name.female3411=Rosa name.female3412=Rosalba name.female3413=Rosalee name.female3414=Rosalia name.female3415=Rosalie name.female3416=Rosalina name.female3417=Rosalind name.female3418=Rosalinda name.female3419=Rosaline name.female3420=Rosalva name.female3421=Rosalyn name.female3422=Rosamaria name.female3423=Rosamond name.female3424=Rosana name.female3425=Rosann name.female3426=Rosanna name.female3427=Rosanne name.female3428=Rosaria name.female3429=Rosario name.female3430=Rosaura name.female3431=Rose name.female3432=Roseann name.female3433=Roseanna name.female3434=Roseanne name.female3435=Roselee name.female3436=Roselia name.female3437=Roseline name.female3438=Rosella name.female3439=Roselle name.female3440=Roselyn name.female3441=Rosemarie name.female3442=Rosemary name.female3443=Rosena name.female3444=Rosenda name.female3445=Rosetta name.female3446=Rosette name.female3447=Rosia name.female3448=Rosie name.female3449=Rosina name.female3450=Rosio name.female3451=Rosita name.female3452=Roslyn name.female3453=Rossana name.female3454=Rossie name.female3455=Rosy name.female3456=Rowena name.female3457=Roxana name.female3458=Roxane name.female3459=Roxann name.female3460=Roxanna name.female3461=Roxanne name.female3462=Roxie name.female3463=Roxy name.female3464=Roy name.female3465=Royce name.female3466=Rozanne name.female3467=Rozella name.female3468=Rubi name.female3469=Rubie name.female3470=Ruby name.female3471=Rubye name.female3472=Rudy name.female3473=Rufina name.female3474=Russell name.female3475=Ruth name.female3476=Rutha name.female3477=Ruthann name.female3478=Ruthanne name.female3479=Ruthe name.female3480=Ruthie name.female3481=Ryan name.female3482=Ryann name.female3483=Sabina name.female3484=Sabine name.female3485=Sabra name.female3486=Sabrina name.female3487=Sacha name.female3488=Sachiko name.female3489=Sade name.female3490=Sadie name.female3491=Sadye name.female3492=Saffron name.female3493=Sage name.female3494=Salena name.female3495=Salina name.female3496=Salley name.female3497=Sallie name.female3498=Sally name.female3499=Salome name.female3500=Sam name.female3501=Samantha name.female3502=Samara name.female3503=Samatha name.female3504=Samella name.female3505=Samira name.female3506=Sammie name.female3507=Sammy name.female3508=Samuel name.female3509=Sana name.female3510=Sanda name.female3511=Sandee name.female3512=Sandi name.female3513=Sandie name.female3514=Sandra name.female3515=Sandy name.female3516=Sang name.female3517=Sanjuana name.female3518=Sanjuanita name.female3519=Sanora name.female3520=Santa name.female3521=Santana name.female3522=Santina name.female3523=Santos name.female3524=Sapphire name.female3525=Sara name.female3526=Sarah name.female3527=Sarai name.female3528=Saran name.female3529=Sari name.female3530=Sarina name.female3531=Sarita name.female3532=Sasha name.female3533=Saturnina name.female3534=Sau name.female3535=Saundra name.female3536=Savanna name.female3537=Savannah name.female3538=Scarlet name.female3539=Scarlett name.female3540=Scott name.female3541=Scottie name.female3542=Sean name.female3543=Season name.female3544=Sebrina name.female3545=Seema name.female3546=Selena name.female3547=Selene name.female3548=Selina name.female3549=Selma name.female3550=Sena name.female3551=Senaida name.female3552=September name.female3553=Serafina name.female3554=Serena name.female3555=Serina name.female3556=Serita name.female3557=Setsuko name.female3558=Sha name.female3559=Shae name.female3560=Shaina name.female3561=Shakia name.female3562=Shakira name.female3563=Shakita name.female3564=Shala name.female3565=Shalanda name.female3566=Shalon name.female3567=Shalonda name.female3568=Shameka name.female3569=Shamika name.female3570=Shan name.female3571=Shana name.female3572=Shanae name.female3573=Shanda name.female3574=Shandi name.female3575=Shandra name.female3576=Shane name.female3577=Shaneka name.female3578=Shanel name.female3579=Shanell name.female3580=Shanelle name.female3581=Shani name.female3582=Shanice name.female3583=Shanika name.female3584=Shaniqua name.female3585=Shanita name.female3586=Shanna name.female3587=Shannan name.female3588=Shannon name.female3589=Shanon name.female3590=Shanta name.female3591=Shantae name.female3592=Shantay name.female3593=Shante name.female3594=Shantel name.female3595=Shantell name.female3596=Shantelle name.female3597=Shanti name.female3598=Shaquana name.female3599=Shaquita name.female3600=Shara name.female3601=Sharan name.female3602=Sharda name.female3603=Sharee name.female3604=Sharell name.female3605=Sharen name.female3606=Shari name.female3607=Sharice name.female3608=Sharie name.female3609=Sharika name.female3610=Sharilyn name.female3611=Sharita name.female3612=Sharla name.female3613=Sharleen name.female3614=Sharlene name.female3615=Sharmaine name.female3616=Sharolyn name.female3617=Sharon name.female3618=Sharonda name.female3619=Sharri name.female3620=Sharron name.female3621=Sharyl name.female3622=Sharyn name.female3623=Shasta name.female3624=Shaun name.female3625=Shauna name.female3626=Shaunda name.female3627=Shaunna name.female3628=Shaunta name.female3629=Shaunte name.female3630=Shavon name.female3631=Shavonda name.female3632=Shavonne name.female3633=Shawana name.female3634=Shawanda name.female3635=Shawanna name.female3636=Shawn name.female3637=Shawna name.female3638=Shawnda name.female3639=Shawnee name.female3640=Shawnna name.female3641=Shawnta name.female3642=Shawny name.female3643=Shay name.female3644=Shayla name.female3645=Shayna name.female3646=Shayne name.female3647=Shea name.female3648=Sheba name.female3649=Sheena name.female3650=Sheila name.female3651=Sheilah name.female3652=Shela name.female3653=Shelba name.female3654=Shelby name.female3655=Shelia name.female3656=Shella name.female3657=Shelley name.female3658=Shelli name.female3659=Shellie name.female3660=Shelly name.female3661=Shemeka name.female3662=Shemika name.female3663=Shena name.female3664=Shenika name.female3665=Shenita name.female3666=Shenna name.female3667=Shera name.female3668=Sheree name.female3669=Sherell name.female3670=Sheri name.female3671=Sherice name.female3672=Sheridan name.female3673=Sherie name.female3674=Sherika name.female3675=Sherill name.female3676=Sherilyn name.female3677=Sherise name.female3678=Sherita name.female3679=Sherlene name.female3680=Sherley name.female3681=Sherly name.female3682=Sherlyn name.female3683=Sheron name.female3684=Sherrell name.female3685=Sherri name.female3686=Sherrie name.female3687=Sherril name.female3688=Sherrill name.female3689=Sherron name.female3690=Sherry name.female3691=Sherryl name.female3692=Shery name.female3693=Sheryl name.female3694=Sheryll name.female3695=Shiela name.female3696=Shila name.female3697=Shiloh name.female3698=Shin name.female3699=Shira name.female3700=Shirely name.female3701=Shirl name.female3702=Shirlee name.female3703=Shirleen name.female3704=Shirlene name.female3705=Shirley name.female3706=Shirly name.female3707=Shizue name.female3708=Shizuko name.female3709=Shona name.female3710=Shonda name.female3711=Shondra name.female3712=Shonna name.female3713=Shonta name.female3714=Shoshana name.female3715=Shu name.female3716=Shyla name.female3717=Sibyl name.female3718=Sidney name.female3719=Sierra name.female3720=Signe name.female3721=Sigrid name.female3722=Silva name.female3723=Silvana name.female3724=Silvia name.female3725=Sima name.female3726=Simona name.female3727=Simone name.female3728=Simonne name.female3729=Sina name.female3730=Sindy name.female3731=Siobhan name.female3732=Sirena name.female3733=Siu name.female3734=Sixta name.female3735=Skye name.female3736=Slyvia name.female3737=Socorro name.female3738=Sofia name.female3739=Soila name.female3740=Sol name.female3741=Solange name.female3742=Soledad name.female3743=Somer name.female3744=Sommer name.female3745=Son name.female3746=Sona name.female3747=Sondra name.female3748=Song name.female3749=Sonia name.female3750=Sonja name.female3751=Sonya name.female3752=Soo name.female3753=Sook name.female3754=Soon name.female3755=Sophia name.female3756=Sophie name.female3757=Soraya name.female3758=Sparkle name.female3759=Spring name.female3760=Stacee name.female3761=Stacey name.female3762=Staci name.female3763=Stacia name.female3764=Stacie name.female3765=Stacy name.female3766=Star name.female3767=Starla name.female3768=Starling name.female3769=Starr name.female3770=Stasia name.female3771=Stefani name.female3772=Stefania name.female3773=Stefanie name.female3774=Stefany name.female3775=Steffanie name.female3776=Stella name.female3777=Stepanie name.female3778=Stephaine name.female3779=Stephane name.female3780=Stephani name.female3781=Stephania name.female3782=Stephanie name.female3783=Stephany name.female3784=Stephen name.female3785=Stephenie name.female3786=Stephine name.female3787=Stephnie name.female3788=Steven name.female3789=Stevie name.female3790=Stormy name.female3791=Suanne name.female3792=Sudie name.female3793=Sue name.female3794=Sueann name.female3795=Suellen name.female3796=Suk name.female3797=Sulema name.female3798=Sumiko name.female3799=Summer name.female3800=Sun name.female3801=Sunday name.female3802=Sung name.female3803=Sunni name.female3804=Sunny name.female3805=Sunshine name.female3806=Susan name.female3807=Susana name.female3808=Susann name.female3809=Susanna name.female3810=Susannah name.female3811=Susanne name.female3812=Susie name.female3813=Susy name.female3814=Suzan name.female3815=Suzann name.female3816=Suzanna name.female3817=Suzanne name.female3818=Suzette name.female3819=Suzi name.female3820=Suzie name.female3821=Suzy name.female3822=Svetlana name.female3823=Sybil name.female3824=Syble name.female3825=Sydney name.female3826=Sylvia name.female3827=Sylvie name.female3828=Synthia name.female3829=Syreeta name.female3830=Tabatha name.female3831=Tabetha name.female3832=Tabitha name.female3833=Tai name.female3834=Taina name.female3835=Taisha name.female3836=Tajuana name.female3837=Takako name.female3838=Takisha name.female3839=Talia name.female3840=Talisha name.female3841=Talitha name.female3842=Tally name.female3843=Tam name.female3844=Tama name.female3845=Tamala name.female3846=Tamar name.female3847=Tamara name.female3848=Tamatha name.female3849=Tambra name.female3850=Tameika name.female3851=Tameka name.female3852=Tamekia name.female3853=Tamela name.female3854=Tamera name.female3855=Tamesha name.female3856=Tami name.female3857=Tamica name.female3858=Tamie name.female3859=Tamika name.female3860=Tamiko name.female3861=Tamisha name.female3862=Tammara name.female3863=Tammera name.female3864=Tammi name.female3865=Tammie name.female3866=Tammy name.female3867=Tamra name.female3868=Tana name.female3869=Tandra name.female3870=Tandy name.female3871=Taneka name.female3872=Tanesha name.female3873=Tangela name.female3874=Tania name.female3875=Tanika name.female3876=Tanisha name.female3877=Tanja name.female3878=Tanna name.female3879=Tansy name.female3880=Tanya name.female3881=Tara name.female3882=Tarah name.female3883=Taren name.female3884=Tari name.female3885=Tarra name.female3886=Tarsha name.female3887=Taryn name.female3888=Tasha name.female3889=Tashia name.female3890=Tashina name.female3891=Tasia name.female3892=Tatiana name.female3893=Tatum name.female3894=Tatyana name.female3895=Taunya name.female3896=Tawana name.female3897=Tawanda name.female3898=Tawanna name.female3899=Tawna name.female3900=Tawny name.female3901=Tawnya name.female3902=Taylor name.female3903=Tayna name.female3904=Teena name.female3905=Tegan name.female3906=Teisha name.female3907=Telma name.female3908=Temeka name.female3909=Temika name.female3910=Tempie name.female3911=Temple name.female3912=Tena name.female3913=Tenesha name.female3914=Tenisha name.female3915=Tennie name.female3916=Tennille name.female3917=Teodora name.female3918=Teofila name.female3919=Tequila name.female3920=Tera name.female3921=Tereasa name.female3922=Teresa name.female3923=Terese name.female3924=Teresia name.female3925=Teresita name.female3926=Teressa name.female3927=Teri name.female3928=Terica name.female3929=Terina name.female3930=Terisa name.female3931=Terra name.female3932=Terrell name.female3933=Terresa name.female3934=Terri name.female3935=Terrie name.female3936=Terrilyn name.female3937=Terry name.female3938=Tesha name.female3939=Tess name.female3940=Tessa name.female3941=Tessie name.female3942=Thalia name.female3943=Thanh name.female3944=Thao name.female3945=Thea name.female3946=Theda name.female3947=Thelma name.female3948=Theo name.female3949=Theodora name.female3950=Theola name.female3951=Theresa name.female3952=Therese name.female3953=Theresia name.female3954=Theressa name.female3955=Thersa name.female3956=Thi name.female3957=Thomas name.female3958=Thomasena name.female3959=Thomasina name.female3960=Thomasine name.female3961=Thora name.female3962=Thresa name.female3963=Thuy name.female3964=Tia name.female3965=Tiana name.female3966=Tianna name.female3967=Tiara name.female3968=Tien name.female3969=Tiera name.female3970=Tierra name.female3971=Tiesha name.female3972=Tifany name.female3973=Tiff name.female3974=Tiffaney name.female3975=Tiffani name.female3976=Tiffanie name.female3977=Tiffany name.female3978=Tiffiny name.female3979=Tijuana name.female3980=Tilda name.female3981=Tillie name.female3982=Timika name.female3983=Timothy name.female3984=Tina name.female3985=Tinisha name.female3986=Tiny name.female3987=Tisa name.female3988=Tish name.female3989=Tisha name.female3990=Tobi name.female3991=Tobie name.female3992=Toby name.female3993=Toccara name.female3994=Toi name.female3995=Tomasa name.female3996=Tomeka name.female3997=Tomi name.female3998=Tomika name.female3999=Tomiko name.female4000=Tommie name.female4001=Tommy name.female4002=Tommye name.female4003=Tomoko name.female4004=Tona name.female4005=Tonda name.female4006=Tonette name.female4007=Toni name.female4008=Tonia name.female4009=Tonie name.female4010=Tonisha name.female4011=Tonita name.female4012=Tonja name.female4013=Tony name.female4014=Tonya name.female4015=Topaz name.female4016=Tora name.female4017=Tori name.female4018=Torie name.female4019=Torri name.female4020=Torrie name.female4021=Tory name.female4022=Tosha name.female4023=Toshia name.female4024=Toshiko name.female4025=Tova name.female4026=Towanda name.female4027=Toya name.female4028=Tracee name.female4029=Tracey name.female4030=Traci name.female4031=Tracie name.female4032=Tracy name.female4033=Tran name.female4034=Trang name.female4035=Travis name.female4036=Treasa name.female4037=Treena name.female4038=Trena name.female4039=Tresa name.female4040=Tressa name.female4041=Tressie name.female4042=Treva name.female4043=Tricia name.female4044=Trina name.female4045=Trinh name.female4046=Trinidad name.female4047=Trinity name.female4048=Trish name.female4049=Trisha name.female4050=Trista name.female4051=Tristan name.female4052=Troy name.female4053=Trudi name.female4054=Trudie name.female4055=Trudy name.female4056=Trula name.female4057=Tula name.female4058=Tuyet name.female4059=Twana name.female4060=Twanda name.female4061=Twanna name.female4062=Twila name.female4063=Twyla name.female4064=Tyesha name.female4065=Tyisha name.female4066=Tyler name.female4067=Tynisha name.female4068=Tyra name.female4069=Ula name.female4070=Ulrike name.female4071=Una name.female4072=Unique name.female4073=Ursula name.female4074=Usha name.female4075=Vada name.female4076=Val name.female4077=Valarie name.female4078=Valda name.female4079=Valencia name.female4080=Valene name.female4081=Valentina name.female4082=Valentine name.female4083=Valeri name.female4084=Valeria name.female4085=Valerie name.female4086=Valery name.female4087=Vallie name.female4088=Valorie name.female4089=Valrie name.female4090=Van name.female4091=Vanda name.female4092=Vanesa name.female4093=Vanessa name.female4094=Vanetta name.female4095=Vania name.female4096=Vanita name.female4097=Vanna name.female4098=Vannesa name.female4099=Vannessa name.female4100=Vashti name.female4101=Vasiliki name.female4102=Veda name.female4103=Velda name.female4104=Velia name.female4105=Vella name.female4106=Velma name.female4107=Velva name.female4108=Velvet name.female4109=Vena name.female4110=Venessa name.female4111=Venetta name.female4112=Venice name.female4113=Venita name.female4114=Vennie name.female4115=Venus name.female4116=Veola name.female4117=Vera name.female4118=Verda name.female4119=Verdell name.female4120=Verdie name.female4121=Verena name.female4122=Vergie name.female4123=Verla name.female4124=Verlene name.female4125=Verlie name.female4126=Verline name.female4127=Verna name.female4128=Vernell name.female4129=Vernetta name.female4130=Vernia name.female4131=Vernice name.female4132=Vernie name.female4133=Vernita name.female4134=Vernon name.female4135=Verona name.female4136=Veronica name.female4137=Veronika name.female4138=Veronique name.female4139=Versie name.female4140=Vertie name.female4141=Vesta name.female4142=Veta name.female4143=Vicenta name.female4144=Vickey name.female4145=Vicki name.female4146=Vickie name.female4147=Vicky name.female4148=Victor name.female4149=Victoria name.female4150=Victorina name.female4151=Vida name.female4152=Viki name.female4153=Vikki name.female4154=Vilma name.female4155=Vina name.female4156=Vincenza name.female4157=Vinita name.female4158=Vinnie name.female4159=Viola name.female4160=Violet name.female4161=Violeta name.female4162=Violette name.female4163=Virgen name.female4164=Virgie name.female4165=Virgil name.female4166=Virgina name.female4167=Virginia name.female4168=Vita name.female4169=Viva name.female4170=Vivan name.female4171=Vivian name.female4172=Viviana name.female4173=Vivien name.female4174=Vivienne name.female4175=Voncile name.female4176=Vonda name.female4177=Vonnie name.female4178=Wai name.female4179=Walter name.female4180=Waltraud name.female4181=Wan name.female4182=Wanda name.female4183=Waneta name.female4184=Wanetta name.female4185=Wanita name.female4186=Wava name.female4187=Wei name.female4188=Wen name.female4189=Wendi name.female4190=Wendie name.female4191=Wendolyn name.female4192=Wendy name.female4193=Wenona name.female4194=Wesley name.female4195=Whitley name.female4196=Whitney name.female4197=Wilda name.female4198=Wilhelmina name.female4199=Wilhemina name.female4200=Willa name.female4201=Willena name.female4202=Willene name.female4203=Willetta name.female4204=Willette name.female4205=Willia name.female4206=William name.female4207=Willie name.female4208=Williemae name.female4209=Willodean name.female4210=Willow name.female4211=Wilma name.female4212=Windy name.female4213=Winifred name.female4214=Winnie name.female4215=Winnifred name.female4216=Winona name.female4217=Winter name.female4218=Wonda name.female4219=Wynell name.female4220=Wynona name.female4221=Xenia name.female4222=Xiao name.female4223=Xiomara name.female4224=Xochitl name.female4225=Xuan name.female4226=Yadira name.female4227=Yaeko name.female4228=Yael name.female4229=Yahaira name.female4230=Yajaira name.female4231=Yan name.female4232=Yang name.female4233=Yanira name.female4234=Yasmin name.female4235=Yasmine name.female4236=Yasuko name.female4237=Yelena name.female4238=Yen name.female4239=Yesenia name.female4240=Yessenia name.female4241=Yetta name.female4242=Yevette name.female4243=Ying name.female4244=Yoko name.female4245=Yolanda name.female4246=Yolande name.female4247=Yolando name.female4248=Yolonda name.female4249=Yon name.female4250=Yong name.female4251=Yoshie name.female4252=Yoshiko name.female4253=Youlanda name.female4254=Young name.female4255=Yuette name.female4256=Yuk name.female4257=Yuki name.female4258=Yukiko name.female4259=Yuko name.female4260=Yulanda name.female4261=Yun name.female4262=Yung name.female4263=Yuonne name.female4264=Yuri name.female4265=Yuriko name.female4266=Yvette name.female4267=Yvone name.female4268=Yvonne name.female4269=Zada name.female4270=Zaida name.female4271=Zana name.female4272=Zandra name.female4273=Zelda name.female4274=Zella name.female4275=Zelma name.female4276=Zena name.female4277=Zenaida name.female4278=Zenia name.female4279=Zenobia name.female4280=Zetta name.female4281=Zina name.female4282=Zinnia name.female4283=Zita name.female4284=Zoe name.female4285=Zofia name.female4286=Zoila name.female4287=Zola name.female4288=Zona name.female4289=Zonia name.female4290=Zora name.female4291=Zoraida name.female4292=Zula name.female4293=Zulema name.female4294=Zulma ================================================ FILE: src/main/resources/assets/mca/models/block/rose_gold_block.json ================================================ { "parent": "block/cube_all", "textures": { "all": "mca:blocks/rose_gold_block" } } ================================================ FILE: src/main/resources/assets/mca/models/block/rose_gold_ore.json ================================================ { "parent": "block/cube_all", "textures": { "all": "mca:blocks/rose_gold_ore" } } ================================================ FILE: src/main/resources/assets/mca/models/block/villager_spawner.json ================================================ { "parent": "block/cube_all", "textures": { "all": "mca:blocks/villager_spawner" } } ================================================ FILE: src/main/resources/assets/mca/models/item/baby_boy.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/baby_boy" } } ================================================ FILE: src/main/resources/assets/mca/models/item/baby_girl.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/baby_girl" } } ================================================ FILE: src/main/resources/assets/mca/models/item/book_death.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/book_death" } } ================================================ FILE: src/main/resources/assets/mca/models/item/book_family.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/book_family" } } ================================================ FILE: src/main/resources/assets/mca/models/item/book_infection.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/book_infection" } } ================================================ FILE: src/main/resources/assets/mca/models/item/book_romance.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/book_romance" } } ================================================ FILE: src/main/resources/assets/mca/models/item/book_rose_gold.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/book_rose_gold" } } ================================================ FILE: src/main/resources/assets/mca/models/item/egg_female.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/egg_female" } } ================================================ FILE: src/main/resources/assets/mca/models/item/egg_male.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/egg_male" } } ================================================ FILE: src/main/resources/assets/mca/models/item/engagement_ring.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/engagement_ring" } } ================================================ FILE: src/main/resources/assets/mca/models/item/engagement_ring_rg.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/engagement_ring_rg" } } ================================================ FILE: src/main/resources/assets/mca/models/item/gold_dust.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/gold_dust" } } ================================================ FILE: src/main/resources/assets/mca/models/item/matchmakers_ring.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/matchmakers_ring" } } ================================================ FILE: src/main/resources/assets/mca/models/item/rose_gold_block.json ================================================ { "parent": "mca:block/rose_gold_block", "display": { "thirdperson": { "rotation": [ 10, -45, 170 ], "translation": [ 0, 1.5, -2.75 ], "scale": [ 0.375, 0.375, 0.375 ] } } } ================================================ FILE: src/main/resources/assets/mca/models/item/rose_gold_dust.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/rose_gold_dust" } } ================================================ FILE: src/main/resources/assets/mca/models/item/rose_gold_ingot.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/rose_gold_ingot" } } ================================================ FILE: src/main/resources/assets/mca/models/item/staff_of_life.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/staff_of_life" } } ================================================ FILE: src/main/resources/assets/mca/models/item/villager_editor.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/villager_editor" } } ================================================ FILE: src/main/resources/assets/mca/models/item/wedding_ring.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/wedding_ring" } } ================================================ FILE: src/main/resources/assets/mca/models/item/wedding_ring_rg.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/wedding_ring_rg" } } ================================================ FILE: src/main/resources/assets/mca/models/item/whistle.json ================================================ { "parent": "item/generated", "textures": { "layer0": "mca:items/whistle" } } ================================================ FILE: src/main/resources/assets/mca/recipes/engagement_ring.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GDG", "G G", "GGG" ], "key": { "G": [ { "item": "minecraft:gold_ingot" } ], "D": [ { "item": "minecraft:diamond" } ] }, "result": { "item": "mca:engagement_ring", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/engagement_ring_rg.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GDG", "G G", "GGG" ], "key": { "G": [ { "item": "mca:rose_gold_ingot" } ], "D": [ { "item": "minecraft:diamond" } ] }, "result": { "item": "mca:engagement_ring_rg", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/gold_dust.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "mca:rose_gold_dust" }, { "item": "minecraft:water_bucket" } ], "result": { "item": "mca:gold_dust", "count": 6 } } ================================================ FILE: src/main/resources/assets/mca/recipes/gold_nugget_from_dust.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GGG", "GGG", "GGG" ], "key": { "G": [ { "item": "mca:gold_dust" } ] }, "result": { "item": "minecraft:gold_nugget", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/matchmakers_ring.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "III", "I I", "III" ], "key": { "I": [ { "item": "minecraft:iron_ingot" } ] }, "result": { "item": "mca:matchmakers_ring", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/rose_gold_block.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "III", "III", "III" ], "key": { "I": [ { "item": "mca:rose_gold_ingot" } ] }, "result": { "item": "mca:rose_gold_block", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/rose_gold_dust_from_ingot.json ================================================ { "type": "minecraft:crafting_shapeless", "ingredients": [ { "item": "mca:rose_gold_ingot" } ], "result": { "item": "mca:rose_gold_dust", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/rose_gold_ingot_from_dust.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GGG", "GGG", "GGG" ], "key": { "G": [ { "item": "mca:rose_gold_dust" } ] }, "result": { "item": "mca:rose_gold_ingot", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/wedding_ring.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GGG", "G G", "GGG" ], "key": { "G": [ { "item": "minecraft:gold_ingot" } ] }, "result": { "item": "mca:wedding_ring", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/wedding_ring_rg.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ "GGG", "G G", "GGG" ], "key": { "G": [ { "item": "mca:rose_gold_ingot" } ] }, "result": { "item": "mca:wedding_ring_rg", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/recipes/whistle.json ================================================ { "type": "minecraft:crafting_shaped", "pattern": [ " W#", "###" ], "key": { "#": [ { "item": "minecraft:iron_ingot", "data": 0 } ], "W": [ { "item": "minecraft:planks", "data": 0 }, { "item": "minecraft:planks", "data": 1 }, { "item": "minecraft:planks", "data": 2 }, { "item": "minecraft:planks", "data": 3 }, { "item": "minecraft:planks", "data": 4 }, { "item": "minecraft:planks", "data": 5 } ] }, "result": { "item": "mca:whistle", "count": 1 } } ================================================ FILE: src/main/resources/assets/mca/sounds.json ================================================ { "reaper.scythe.out": { "category": "hostile", "subtitle": "Draws scythe", "sounds": [ "mca:reaper-scythe-out" ] }, "reaper.scythe.swing": { "category": "hostile", "subtitle": "Swings scythe", "sounds": [ "mca:reaper-scythe-swing" ] }, "reaper.idle": { "category": "hostile", "subtitle": "Evil laughter", "sounds": [ "mca:reaper-idle" ] }, "reaper.death": { "category": "hostile", "subtitle": "Reaper death", "sounds": [ "mca:reaper-death" ] }, "reaper.block": { "category": "hostile", "subtitle": "Blocked attack", "sounds": [ "mca:reaper-block" ] }, "reaper.summon": { "category": "hostile", "subtitle": "Evil laughter", "sounds": [ "mca:reaper-summon" ] } } ================================================ FILE: src/main/resources/mcmod.info ================================================ [ { "modid": "mca", "name": "Minecraft Comes Alive", "description": "Replaces villagers with humans, adds marriage, children, and more!", "version": "${version}", "mcversion": "${mcversion}", "url": "https://minecraftcomesalive.com/", "updateUrl": "", "authorList": ["WildBamaBoy", "SheWolfDeadly"], "credits": "Mezzodrinker, The_Nanobots, numerous others.", "logoFile": "mca.png", "screenshots": [], "dependencies": [] } ] ================================================ FILE: src/main/resources/pack.mcmeta ================================================ { "pack": { "description": "Minecraft Comes Alive resources", "pack_format": 3 } }