Compare commits

..

No commits in common. "master" and "1.0.27X4914" have entirely different histories.

5207 changed files with 398078 additions and 565117 deletions

View File

@ -1,16 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = crlf
indent_style = tab
indent_size = tab
insert_final_newline = true
trim_trailing_whitespace = true
max_line_length = off
[{*.info,*.json,*.mcmeta,*.md,*.cfg,*.yml,*.toml}]
tab_width = 2
[{*.info,*.mcmeta,*.cfg}]
end_of_line = lf

View File

@ -1,62 +0,0 @@
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle
# Yes this is a mostly untouched Github actions template
name: Java CI with Gradle
on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Set up JDK 8
uses: actions/setup-java@v4
with:
java-version: '8'
distribution: 'temurin' # Temurin because it's default :P
# Calculate days since 10/10/10
- name: Calculate days since 10/10/10
id: calculate_days
run: |
start_date="2010-10-10"
current_date=$(date +%Y-%m-%d)
days_since=$(( ($(date -d "$current_date" +%s) - $(date -d "$start_date" +%s)) / 86400 ))
echo "days=$days_since" >> $GITHUB_OUTPUT
# Update version files with proper sed syntax
- name: Update version files
run: |
days=${{ steps.calculate_days.outputs.days }}
# Use proper sed syntax for Linux runners
sed -i "s/public static final String VERSION = \".*\";/public static final String VERSION = \"1.0.27 BETA ($days)\";/" src/main/java/com/hbm/lib/RefStrings.java
sed -i "s/mod_build_number=.*/mod_build_number=$days/" gradle.properties
# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
- name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0
- name: Build with Gradle Wrapper
run: ./gradlew build
- name: Upload a Build Artifact
uses: actions/upload-artifact@v4.6.0
with:
# A file, directory or wildcard pattern that describes what to upload
path: ./build/libs

33
.gitignore vendored
View File

@ -1,28 +1,25 @@
# eclipse
/eclipse
/bin
/*.launch
/.settings
/.metadata
/.classpath
/.project
eclipse
bin
*.launch
.settings
.metadata
.classpath
.project
# idea
/out
/*.ipr
/*.iws
/*.iml
/.idea
out
*.ipr
*.iws
*.iml
.idea
# gradle
/build
/.gradle
# vscode
/.vscode
build
.gradle
# other
/run
run
# CurseForge configuration
/curseforge.properties

View File

@ -13,8 +13,6 @@ Things you should also avoid include:
* duplicate util functions (just use what we have, man)
* unused or half finished util functions (for obvious reasons)
* half finished or obviously broken features (à la "bob will fix it, i'm sure of it", please don't do that)
* updating the changelog (you're guaranteed to cause a merge conflict with that)
* any use of `I18n`, use `I18nUtil` instead
## Test your code
@ -22,9 +20,6 @@ This should go without saying, but please don't PR code that was never actually
**Addendum:** Because apparently some people think that testing is somehow optional, it is now **mandatory** to test the code both on a client and on a server. If the PR contains compat code, the game has to work **with and without** the mod that the compat is for.
## No refactor PRs
Your refactors suck ass and usually something ends up breaking.
## Communication
If you're planning on adding some new thing or doing a grand change, it's best to ask whether that's a good idea before spending 50 hours on a project that won't end up getting merged, due to issues that could have been entirely avoidable with communication.
@ -35,9 +30,11 @@ This ties together with the previous point - there's no guarantees that your PR
## I want to help but don't know where to start
If you want to help the project, consider getting involved with the [wiki](https://nucleartech.wiki/) first. Writing an article is the easiest and quickest way of helping, and requires no programming knowledge. If you do know Java and want to help, consider these places first:
If you want to help the project, consider getting involved with the [wiki](ntm.fandom.com) first. Writing an article is the easiest and quickest way of helping, and requires no programming knowledge. If you do know Java and want to help, consider these places first:
* Localization, i.e. translations in different language are always accepted.
* `IConfigurableMachine`, an interface that allows machines to be added to the `hbmMachines.json` config, is still not used by many machines.
* F1 Presentations, also known as "Stare" or "Jar Presentations", is a neat system of creating a short movie explaining functionality. All the relevant code can be found in `com.hbm.wiaj`.
* Some guns still use the old "bow-style" systems and not `ItemGunBase`.
* Many guns don't have any animations whatsoever, just adding a minor recoil would already improve them by a lot.
* Adding tooltips to more machines, explaining some of the basics.

View File

@ -2,19 +2,14 @@
[NTM on Modrinth](https://modrinth.com/mod/ntm)
[NTM on CurseForge](https://www.curseforge.com/minecraft/mc-mods/hbms-nuclear-tech-mod)
[Official NTM Wiki](https://nucleartech.wiki/wiki/Main_Page)
[Bobcat's Blog (the blag)](https://hbmmods.github.io/), you can find lengthy yapping, upcoming features and some secrets here.
[NTM on CurseForge](https://minecraft.curseforge.com/projects/hbms-nuclear-tech-mod?gameCategorySlug=mc-mods&projectID=235439)
**This is for 1.7.10!** For 1.12, check out these projects:
* NTM Community Edition (WarFactory): https://github.com/MisterNorwood/Hbm-s-Nuclear-Tech-CE
* NTM Extended Edition (Alcater): https://github.com/Alcatergit/Hbm-s-Nuclear-Tech-GIT/releases
* NTM Reloaded: https://github.com/TheOriginalGolem/Hbm-s-Nuclear-Tech-GIT/releases
* NTM Extended Edition (Alcater): https://github.com/Alcatergit/Hbm-s-Nuclear-Tech-GIT/releases
For 1.18, try Martin's remake: https://codeberg.org/MartinTheDragon/Nuclear-Tech-Mod-Remake/releases
For 1.18, try Martin's remake: https://github.com/MartinTheDragon/Nuclear-Tech-Mod-Remake/releases
## Downloading pre-compiled versions from GitHub
@ -25,7 +20,7 @@ Simply navigate to "Releases" on the right side of the page, download links for
Tired of waiting until the next version comes out? Here is a tutorial on how to compile the very newest version yourself:
Please note that these installation instructions are assuming you're running Microsoft Windows operating system. Linux users should know what to do by looking at the same guide.
1. Make sure you have JDK8 installed. If not, download it from [adoptium.net](https://adoptium.net/temurin/releases?version=8)
1. Make sure you have JDK8 installed. If not, download it from [adoptium.net](https://adoptium.net/?variant=openjdk8&jvmVariant=hotspot)
2. If you don't have git installed, download&install it from [here](https://git-scm.com/downloads).
3. Open up "Git Bash":
* Press Windows Button, type "Git Bash" and press ENTER
@ -96,29 +91,9 @@ If you want to make some changes to the mod, follow this guide:
* Click **Add Standard VM**; in the JRE home, navigate to the directory where the JDK is installed, then click finish and select it.
10. Code!
## Contributing animations
Weapon animations in NTM are stored in JSON files, which are used alongside OBJ models to produce high quality animations with reasonable filesizes. Import/Export Blender addons are available for versions 2.79, 3.2, and 4.0 in `tools`, and they should function reasonably well in newer versions as well. See the comments in the header of the export scripts for usage instructions.
## Compatibility notice
NTM has certain behaviors intended to fix vanilla code or to increase compatibility in certain cases where it otherwise would not be possible. These behaviors have the potential of not playing well with other mods, and while no such cases are currently known, here's a list of them.
### Thermos
Thermos servers (along with its forks such as Crucible) have a "performance" feature that causes all tile entity ticking to slow down if there's no player present in the same chunk. For obvious reasons, this will heavily impact machines and cause phantom issues that, not having knowledge of this "performance" feature, are near impossible to diagnose. By default, NTM will crash on servers running the Thermos base code and print a lengthy message informing server owners about this "performance" feature as well as how to fix the issues it causes. The error message is printed in plain English on the top of the crash log, failure to read (as well as understand) it will leave the server inoperable.
### Shaders
Shaders (loaded by either Optifine, Iris or otherwise) will in all likelihood break when a gun is held. This is because guns need to skip vanilla's first person item setup for the rendering, however shaders apparently use the setup step for setting certain GL states, and skipping that will break rendering. [Shader Fixer](https://modrinth.com/mod/shader-fixer) is a mod with various fixes, among which is explicit compatibility for NTM's guns.
### Optifine
One of the most common "performance" mods on 1.7.10, Optifine, achieves an increase in performance by breaking small things in spots that are usually hard to notice, although this can cause severe issues with NTM. A short list of problems, along with some solutions, follows:
* Get rid of Optifine and use one of the many [other, less intrusive performance mods](https://gist.github.com/makamys/7cb74cd71d93a4332d2891db2624e17c).
* Blocks with connected textures may become invisible. This can be fixed by toggling triangulation (I do not know what or where this setting is, I just have been told that it exists and that it can fix the problem) or multicore chunk rendering (same here).
* Entity "optimization" has a tendency to break chunkloading, this is especially noticeable with missiles which rely heavily on chunkloading to work, causing them to freeze mid-air. It's unclear what setting might fix this, and analysis of Optifine's source code (or rather, lack thereof) has not proven useful either.
### Angelica
In older versions, Angelica caused issues regarding model rendering, often times making 3D models transparent. Ever since the switch to VBOs, models work fine. Another issue was blocks with connected textures not rendering at all, but this too was fixed, meaning as of time of writing there are no major incompatibilities known with Angelica. However there a few minor issues that persist, but those can be fixed:
* Often times when making a new world, all items appear as white squares. Somehow, scrolling though the NEI pages fixes this permanently
* Reeds will render weirdly, this is an incompatibility with the "Compact Vertex Format" feature. Disabling it will make reeds look normal. Alternatively, reed rendering can be disabled by using `/ntmclient set RENDER_REEDS false`, which works around the issue by not rendering the underwater portion of reeds at all.
### Skybox chainloader
NTM adds a few small things to the skybox using a custom skybox renderer. Minecraft can only have a single skybox renderer loaded, so setting the skybox to the NTM custom one would break compatibility with other mods' skyboxes. To mend this, NTM employs a **chainloader**. This chainloader will detect if a different skybox is loaded, save a reference to that skybox and then use NTM's skybox, which when used will also make sure to run the previous modded skybox renderer. In the event that NTM's skybox were to cause trouble, it can be disabled with the config option `1.31_enableSkyboxes`.
@ -131,14 +106,5 @@ An often overlooked aspect of Minecraft is its stats, the game keeps track of ho
### Keybind overlap
An often annoying aspect of modded Minecraft is its keybinds. Even though multiple binds can be assigned the same key, all but one will show up as "conflicting" and only the non-conflicting one will work. Which one this is is usually arbitrary, and there is no reason to have such limitation. Often times keybinds are only applicable in certain scenarios, and a commonly found degree of overlap is within reason. Therefore, NTM will run its own key handling code which allows conflicting keybinds to work. If there should be any issues with this behavior, it can be disabled with the config option `1.34_enableKeybindOverlap`.
### Render distance capping
There is a common crash caused by Minecraft's render distance slider going out of bounds, this usually happens when uninstalling a mod that extends the render distance (like Optifine) or when downgrading the Minecraft version (newer versions have higher render distance caps). To prevent crashes, the mod will attempt to decrease the render distance if it's above 16 unless Optifine is installed. If this behavior is not desired (for example, because another mod that allows higher render distance is being used), it can be disabled with the config option `1.25_enableRenderDistCheck`.
### Log spam caused by ComparableStack
In some modpacks (exact mods needed to replicate this are unknown), it's possible that invalid registered items may cause problems for NEI handlers. To prevent crashes, the ComparableStack class used to represent stacks will default to a safe registered item, and print a log message. In certain situations, this may cause dozens of errors to be printed at once, potentially even lagging the game. If that happens, the log message (but not the error handling) can be disabled with the config option `1.28_enableSilentCompStackErrors`.
### Sound system limit
By default, the sound system only allows a limited amount of sounds to run at once (28 regular sounds and 4 streaming sounds), this causes issues when there's many machines running at once, since their looped sounds will constantly interrupt each other, causing them to immediately restart, which in some isolated cases has proven to cause massive lagspikes. To prevent this, NTM will increase the sound limit to 1000 regular sounds and 50 streaming sounds, this can be disabled with the config option `1.39_enableSoundExtension`.
# License
This software is licensed under the GNU Lesser General Public License version 3. In short: This software is free, you may run the software freely, create modified versions, distribute this software and distribute modified versions, as long as the modified software too has a free software license (with an exception for linking to this software, as stated by the "Lesser" part of the LGPL, where this may not be required). You win this round, Stallman. The full license can be found in the `LICENSE` and `LICENSE.LESSER` files.

View File

@ -6,7 +6,6 @@ import java.nio.file.StandardCopyOption
buildscript {
repositories {
maven { url = 'https://maven.ntmr.dev/proxy/' }
maven { url = 'https://maven.minecraftforge.net/' }
maven { url = 'https://plugins.gradle.org/m2' }
mavenCentral()
@ -68,34 +67,14 @@ eclipse.classpath.file.whenMerged { cp ->
}
repositories {
maven {
name = 'Blerg'
url = 'https://maven.ntmr.dev/proxy/'
}
maven {
name = 'ModMaven'
url = 'https://modmaven.dev'
}
maven {
name = "gt"
url = "https://gregtech.mechaenetia.com/"
}
//maven {
// name = "CurseForge"
// url = "https://minecraft.curseforge.com/api/maven/"
//}
maven {
name = "Jitpack"
url = "https://jitpack.io"
}
maven {
name = "CurseMaven"
url = "https://cursemaven.com"
}
maven {
name = "OpenComputers"
url = "https://maven.cil.li/"
}
}
dependencies {
@ -108,11 +87,8 @@ dependencies {
implementation 'codechicken:NotEnoughItems:1.7.10-1.0.3.74:dev'
compileOnly 'codechicken:NotEnoughItems:1.7.10-1.0.3.74:src'
compileOnly "inventorytweaks:InventoryTweaks:1.59-dev:deobf"
//compileOnly 'inventory-tweaks:InventoryTweaks:1.62+beta.84:api'
implementation "li.cil.oc:OpenComputers:MC1.7.10-1.5.+:api"
compileOnly "com.github.GTNewHorizons:Applied-Energistics-2-Unofficial:rv3-beta.56-GTNH:dev"
}
processResources {

View File

@ -1,27 +1,66 @@
## Changed
* Updated russian localization
* Rad absorbers now use metadata, existing blocks will be converted automatically
* Fissure bombs that go off in crater biomes now create fissures with metadata 1 which creates radioactive volcanic lava
* If a crater biome is created on top of an existing fissure, it will keep producing normal volcanic lava
* Simplified the battery socket's client packets, reducing CPU load
* Muzzle flashes on guns now work in third person mode, including on other players and on NPCs, making it more apparent when you're being fired at
* This includes non-standard special effects like the .44 gap flash and the .35-800 ejector plume
* Removed the old unused satelite deco blocks, freeing up 6 block IDs
* Crucibles that smelt metal with no template set will no place the metal in the recipe stack instead of the waste stack, this should make it easier to get a recipe to work in the many, many cases where people add the template after smelting the material
* Battery sockets and the FENSU now support the copy tool
* Removed unused displaylist support from the model loader
* DLs have been long phased out in favor of VBOs anyway
* Rebranded canned horse slime
* Now with extra bone marrow
* Updated the deuterium tower's model
* Increased the energy requirement for welding osmiridium
## Added
* More axes
* Bismuth, volcanic, chlorophyte and mese tool materials now have axes
* Axes also double as offensive weapons, being a lot more powerful than their pickaxe counterparts
* Drainage pipe
* Spills fluid, allowing to void up to 1.000mB per tick
* Might slightly alter the landscape, depending on whether the fluid was poisonous
* Viscous, flammable liquids cause oil spill blocks to appear
* Not all liquids have the appropriate pollution stats yet, the system is still subject to change
# Fixed
* Potentially fixed yet another issue regarding crates
* Fixed battery socket `fillpercent` RoR function always assuming a max power of 1
* Fixed issue where multiblock ports would generate many OpenComputers component entries
* Fixed RBMK automatic control rods having incorrect settings when using the copy tool
* Fixed battery sockets producing junk debug data in the logs
* Fixed an issue where the charging station would crash when trying to charge certain items
* Fixed the DFC's core component not dropping its contents when mined
* Fixed audio problems with guns
## Changed
* After three quarters of a decade, three separate models, countless rebalances and hours of senseless yapping, the industrial generator has finally met its end. Suddenly, yet not unsurprisingly, on this here day the industrial generator has closed its eyes for the final time. It was a long and eventful journey, but as with all things in life, it too had to come to an end.
* And this is why we can't ever have anything nice
* Rebalanced glyphids
* We'll see how it goes
* Still prone to changes, there's still a few inconsistencies and some behavior has barely been tested it all, but I have consulted the almighty spreadsheet and it said "yeah it ok"
* Did some spring cleaning
* Removed cloud residue (looked horrible, allowed for weird dupes and made no sense overall)
* Bottlecap blocks now use a single block ID and metadata instead of using one ID per type. This change however will delete all existing bottlecap blocks in the world
* Removed the config option for silos (the option no longer works anyway since the new silos use the structure component system)
* Finally removed the deaerator and the large shredder
* Removed some of the ancient test blocks that haven't been needed in about 8 years
* Removed all the siege blocks, since siege mode will never be finished anyway
* Removed reinforced niter
* Removed a few other minor things that won't be mentioned because nobody's gonna even notice their absence anyway
* Retextured the laser detonator to look more like the old detonator, but keeping the 3D model
* Bedrock ores can now be customized in creative mode. Using a drillbit sets the tier, a fluid container sets the borefluid requirement and any other item sets the resource.
* The texture used is random, and the color applied is based on the auto detect system. The system doesn't work with layered items, so the resulting color won't be the same as naturally generated bedrock ore. The bedrock ore item in particular will always result in a white ore, no matter the type
* The polluting fluid trait is now recognized by machines, which means that pollution amounts now depend on the fluid used, not the machine
* This means that flare stacks are now significantly less polluting, assuming natural gas is burned
* Flare stacks and barrels now also respect the spilling tag, which means that simply venting the gas may cause poison pollution
* Hydrogen doesn't have the polluting tag, so hydrogen burning generators won't create soot anymore
* Compressing blood no longer creates oil, rather it makes heavy oil (250mB)
* Tier 2 pickaxes (bismuth and up) now use the large item renderer
* Added the metal block material to the sellafite conversion list of nuclear explosions
* Changed the mechanics for schottky particle diodes
* Instead of randomizing directions, schottky diodes will now split particles into "virtual particles" which take mutliple paths at once
* The particles will collapse as soon as the first virtual particle with a valid outcome reaches the end
* This change allows branching accelerators to be made, where the particle will always take the shortest path necessary to complete the operation. In essence, it allows a single accelerator to do any recipe, without requiring to power the entire accelerator, as only the path of the finishing particle will use up energy.
* The particle accelerator as well as the schottky particle diodes now have presentations explaining how they work
* Loot pools are now configurable. Loot is divided into different categories, and structures may generate things from certain categories.
* The config currently includes all items spawned in dungeon chests/crates/safes/lockers, excluding black book spawns, but also including the loot pool for red room pedestals
* Also added satellites as configurable loot pools. Yay!
* Pylons and wire connectors now use a texture instead of a solid colored wire
* The cable model has been simplified, being only a single face instead of three faces stuck inside each other at weird angles
* Cables now sag slightly more at long ranges
* There are now configs for toggling the startup message as well as the guidebook
* Cybercrab spawners will only start spawning as soon as a player is within 25 blocks of the spawner
* Improved inventory shift-clicking for the FEL, assembler, chemplant, large mining drill, gas centrifuge, shredder and turbofan
* Updated chinese localization
## Fixed
* WarTec should now be compatible again
* Fixed the "Hold shift for more info" line appearing on fluid info when shift is held, and disappearing otherwise
* Fixed smokestacks being able to void any fluid under certain conditions
* Fixed the hydrotreater only using half as much crude oil per operation as it should
* Fixed the old launchpad printing the wrong message when successfully launched via detonator
* Oil spills should no longer save, fixing an issue where chunkloaded derricks would constantly spill oil entities into unloaded chunks, causing them to get stuck
* Fixed schrabidium conversion happening outside the main crater instead of inside
* Fixed wood burning generator creating smoke even if no power is being generated
* Fixed one of the woodburner's ports being offset in certain orientations
* Fixed fog caching causing weird behavior with the sky color change in response to crater biomes (or lack thereof)
* Fixed "F1 for help" keybind not working on non-standard inventories such as the NEI item list
* Fixed pylon wire rendering having incorrect corrdinates for brightness checks
* Fixed dupe caused by shift clicking certain slots in the fusion reactor
* Fixed snowglobe rendering lighting setup leak causing blocks rendered after them in inventory to not have correct lighting

View File

@ -1,80 +1,21 @@
mod_version=1.0.27
# Empty build number makes a release type
mod_build_number=5572
credits=HbMinecraft,\
\ rodolphito (explosion algorithms),\
\ grangerave (explosion algorithms),\
\ Hoboy (textures, models),\
\ Drillgon200 (effects, models),\
\ MartinTheDragon (calculator, chunk-based fallout, bendable cranes, pipe improvements, PWR sounds),\
\ Alcater (GUI textures),\
\ MellowArpeggiation (new animation system, turbine sounds, sound fixes, industrial lights, conveyor wand, NBT structures, MSU displays),\
\ Pheo (textures, various machines, models, weapons),\
\ Vær (gas centrifuges, better worldgen, ZIRNOX, CP-1 parts, starter guide, new cyclotron, weapon animations),\
\ UFFR (RTG pellets, guns, casings, euphemium capacitor, nucleartech.wiki),\
\ LePeep (coilgun model, BDCL QC),\
\ Adam29 (liquid petroleum, ethanol, electric furnace),\
\ Pvndols (thorium fuel recipe, gas turbine),\
\ JamesH2 (blood mechanics, nitric acid, particle emitter),\
\ Lazzzycat (structures, mob gear),\
\ PastaBaguette (coal horse decal),\
\ Doctor17 (russian localization)),\
\ Pashtet (russian localization),\
\ 7H40 (russian localization),\
\ RayzerHan (russian localization),\
\ Bismarck (chinese localization),\
\ Creeper-banner (chinese localization),\
\ 5467864 (chinese localization),\
\ eeeeee0a (chinese localization),\
\ hz0909adc (chinese localization),\
\ LSKLW (chinese localization),\
\ R-Kaenbyou (chinese localization),\
\ scp-000000000 (chinese localization),\
\ UnnameTokiko (chinese localization),\
\ Herobrine 457985 (chinese localization),\
\ xxwinhere (chinese localization),\
\ Nycticoraxnightheron (chinese localization),\
\ NarekoMichigami810 (chinese localization),\
\ Maksymisio (polish localization)\
\ el3ctro4ndre (italian localization),\
\ Goaty1208 (italian localization),\
\ Pu-238 (Tom impact effects),\
\ Frooz (gun models),\
\ VT-6/24 (models, textures),\
\ Nos (models),\
\ WushiThe (models),\
\ Minecreep (models),\
\ ackbarcrowbars (models),\
\ haru315 (spiral point algorithm),\
\ mlbv (threaded MK5),\
\ 70k (textures, glyphid AI, strand caster, electrolyzer changes, cryolite),\
\ instantnootles (concept artist),\
\ Sten89 (models),\
\ Pixelguru26 (textures),\
\ TheBlueHat (textures),\
\ Burningwater202 (laminate glass),\
\ TehTemmie (reacher radiation function),\
\ Silly541 (config for safe ME drives),\
\ Voxelstice (OpenComputers integration, turbine spinup),\
\ BallOfEnergy1 (OpenComputers integration, RBMK and packet optimization, crate backpacks),\
\ PewPewCricket (OpenComputers integration),\
\ kelllllen (OpenComputers integration),\
\ sdddddf80 (recipe configs, chinese localization, custom machine holograms),\
\ Abel1502 (abilities GUI, optimization, crate upgrade recipes, strand caster improvements, varous tweaks),\
\ Darek505 (armor rendering compatibility fix),\
\ ranch21 (improved HUD gauges),\
\ SuperCraftAlex (tooltips)\
\ Ice-Arrow (research reactor tweaks),\
\ 245tt (anvil GUI improvements),\
\ KoblizekXD (doors),\
\ FOlkvangrField (custom machine parts),\
\ RosaTryp (centrifuge config),\
\ Toshayo (satellite loot system, project settings, gradle curse task, OpenComputers integration, fluid counter valve),\
\ Dash (PA particle serialization fix),\
\ archiecarrot123 (armor rendering compatibility fix),\
\ mikkerlo (mining laser & builder's jetpack improvements),\
\ icomet (refactoring),\
\ martemen (project settings),\
\ OvermindDL1 (project settings),\
\ impbk2002 (project settings)\
mod_version=1.0.27
# Empty build number makes a release type
mod_build_number=4914
credits=HbMinecraft, rodolphito (explosion algorithms), grangerave (explosion algorithms),\
\ Hoboy (textures, models), Doctor17 (russian localization), Drillgon200 (effects, models,\
\ porting), UFFR (RTGs, guns, casings, euphemium capacitor), Pu-238 (Tom impact effects), Bismarck\
\ (chinese localization), Frooz (models), Minecreep (models), VT-6/24 (models, textures), Pheo (textures,\
\ various machines, models, weapons), Vær (gas centrifuges, better worldgen, ZIRNOX, CP-1 parts, starter guide),\
\ Adam29 (liquid petroleum, ethanol, electric furnace), Pashtet (russian localization), MartinTheDragon\
\ (calculator, chunk-based fallout, bendable cranes, pipe improvements), haru315 (spiral point algorithm),\
\ Sten89 (models), Pixelguru26 (textures), TheBlueHat (textures), Alcater (GUI textures, porting), impbk2002\
\ (project settings), Nos (models), Burningwater202 (laminate glass), OvermindDL1 (project settings), TehTemmie\
\ (reacher radiation function), Toshayo (satellite loot system, project settings, gradle curse task), Silly541\
\ (config for safe ME drives), Voxelstice (OpenComputers integration, turbine spinup), BallOfEnergy1\
\ (OpenComputers integration), martemen (project settings), Pvndols (thorium fuel recipe, gas turbine),\
\ JamesH2 (blood mechanics, nitric acid, particle emitter), sdddddf80 (recipe configs, chinese localization,\
\ custom machine holograms, I18n improvements), SuperCraftAlex (tooltips) LePeep (coilgun model, BDCL QC),\
\ 70k (textures, glyphid AI, strand caster), Maksymisio (polish localization) Ice-Arrow (research reactor tweaks),\
\ 245tt (anvil GUI improvements), MellowArpeggiation (new animation system, turbine sounds, sound fixes,\
\ industrial lights, better particle diodes), FOlkvangrField (custom machine parts)

BIN
ntm-animator.blend Normal file

Binary file not shown.

View File

@ -3,7 +3,6 @@ package api.hbm.block;
import net.minecraft.item.ItemStack;
import net.minecraft.world.World;
@Deprecated
public interface IDrillInteraction {
/**

View File

@ -1,15 +0,0 @@
package api.hbm.block;
import com.hbm.entity.item.EntityTNTPrimedBase;
import net.minecraft.world.World;
public interface IFuckingExplode {
// Anything that can be detonated by another explosion should implement this and spawn an EntityTNTPrimedBase when hit by an explosion
// This prevents chained explosions causing a stack overflow
// Note that the block can still safely immediately explode, as long as the source isn't another explosion
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity);
}

View File

@ -1,6 +1,5 @@
package api.hbm.block;
@Deprecated
public interface IMiningDrill {
/**

View File

@ -1,4 +1,4 @@
package api.hbm.energymk2;
package api.hbm.energy;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
@ -10,9 +10,9 @@ public interface IBatteryItem {
public void setCharge(ItemStack stack, long i);
public void dischargeBattery(ItemStack stack, long i);
public long getCharge(ItemStack stack);
public long getMaxCharge(ItemStack stack);
public long getChargeRate(ItemStack stack);
public long getDischargeRate(ItemStack stack);
public long getMaxCharge();
public long getChargeRate();
public long getDischargeRate();
/** Returns a string for the NBT tag name of the long storing power */
public default String getChargeTagName() {

View File

@ -0,0 +1,160 @@
package api.hbm.energy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
/**
* For compatible cables with no buffer, using the IPowertNet. You can make your own cables with IEnergyConnector as well, but they won't join their power network.
* @author hbm
*/
public interface IEnergyConductor extends IEnergyConnector {
public IPowerNet getPowerNet();
public void setPowerNet(IPowerNet network);
/**
* A unique identifier for every conductor tile. Used to prevent duplicates when loading previously persistent unloaded tiles.
* @return
*/
public default int getIdentity() {
return getIdentityFromTile((TileEntity) this);
}
public static int getIdentityFromTile(TileEntity te) {
return getIdentityFromPos(te.xCoord, te.yCoord, te.zCoord);
}
public static int getIdentityFromPos(int x, int y, int z) {
final int prime = 27644437; // must be this large to minimize localized collisions
int result = 1;
result = prime * result + x;
result = prime * result + y;
result = prime * result + z;
return result;
}
/**
* Whether the link should be part of reeval when the network is changed.
* I.e. if this link should join any of the new networks (FALSE for switches that are turned off for example)
* @return
*/
public default boolean canReevaluate() {
return !((TileEntity) this).isInvalid();
}
/**
* When a link leaves the network, the net has to manually calculate the resulting networks.
* Each link has to decide what other links will join the same net.
* @param copy
*/
public default void reevaluate(HashMap<Integer, IEnergyConductor> copy, HashMap<Integer, Integer> proxies) {
for(int[] pos : getConnectionPoints()) {
int newX = pos[0];
int newY = pos[1];
int newZ = pos[2];
int id = IEnergyConductor.getIdentityFromPos(newX, newY, newZ);
IEnergyConductor neighbor = copy.get(id);
if(neighbor == null) {
Integer newId = proxies.get(id);
if(newId != null) {
neighbor = copy.get(newId);
}
}
if(neighbor != null && this.canReevaluate() && neighbor.canReevaluate()) {
if(neighbor.getPowerNet() != null) {
//neighbor net and no self net
if(this.getPowerNet() == null) {
neighbor.getPowerNet().joinLink(this);
//neighbor net and self net
} else {
this.getPowerNet().joinNetworks(neighbor.getPowerNet());
}
//bidirectional re-eval, experimental and technically optional, only useful as a fallback
} /*else {
//no neighbor net and no self net
if(this.getPowerNet() == null) {
this.setPowerNet(new PowerNet().joinLink(this));
neighbor.setPowerNet(this.getPowerNet().joinLink(neighbor));
//no neighbor net and self net
} else {
neighbor.setPowerNet(this.getPowerNet().joinLink(neighbor));
}
}*/
//extensive debugging has shown that bidirectional re-eval is complete shit
}
}
}
/**
* Creates a list of positions for the re-eval process. In short - what positions should be considered as connected.
* Also used by pylons to quickly figure out what positions to connect to.
* DEFAULT: Connects to all six neighboring blocks.
* @return
*/
public default List<int[]> getConnectionPoints() {
List<int[]> pos = new ArrayList();
TileEntity tile = (TileEntity) this;
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
int newX = tile.xCoord + dir.offsetX;
int newY = tile.yCoord + dir.offsetY;
int newZ = tile.zCoord + dir.offsetZ;
pos.add(new int[] {newX, newY, newZ});
}
return pos;
}
/**
* Since isLoaded is only currently used for weeding out unwanted subscribers, and cables shouldn't (although technically can) be
* subscribers, we just default to true because I don't feel like wasting time implementing things that we don't actually need.
* Perhaps this indicates a minor flaw in the new API, but I physically lack the ability to worry about it.
*/
@Override
public default boolean isLoaded() {
return true;
}
//TODO: check if this standard implementation doesn't break anything (it shouldn't but right now it's a bit redundant) also: remove duplicate implementations
@Override
public default long transferPower(long power) {
if(this.getPowerNet() == null)
return power;
return this.getPowerNet().transferPower(power);
}
/**
* Returns whether the conductor has mutliblock proxies which need to be taken into consideration for re-eval.
* @return
*/
public default boolean hasProxies() {
return false;
}
/**
* Returns the identities (position-based) of proxies which resolve into the conductor's own identity.
* @return
*/
public default List<Integer> getProxies() {
return new ArrayList();
}
}

View File

@ -0,0 +1,128 @@
package api.hbm.energy;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
import com.hbm.util.CompatEnergyControl;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Vec3;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/**
* For anything that connects to power and can be transferred power to, the bottom-level interface.
* This is mean for TILE ENTITIES
* @author hbm
*/
public interface IEnergyConnector extends ILoadedTile {
/**
* Returns the amount of power that remains in the source after transfer
* @param power
* @return
*/
public long transferPower(long power);
/**
* Whether the given side can be connected to
* dir refers to the side of this block, not the connecting block doing the check
* @param dir
* @return
*/
public default boolean canConnect(ForgeDirection dir) {
return dir != ForgeDirection.UNKNOWN;
}
/**
* The current power of either the machine or an entire network
* @return
*/
public long getPower();
/**
* The capacity of either the machine or an entire network
* @return
*/
public long getMaxPower();
public default long getTransferWeight() {
return Math.max(getMaxPower() - getPower(), 0);
}
/**
* Basic implementation of subscribing to a nearby power grid
* @param world
* @param x
* @param y
* @param z
*/
public default void trySubscribe(World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = world.getTileEntity(x, y, z);
boolean red = false;
if(te instanceof IEnergyConductor) {
IEnergyConductor con = (IEnergyConductor) te;
if(!con.canConnect(dir.getOpposite()))
return;
if(con.getPowerNet() != null && !con.getPowerNet().isSubscribed(this))
con.getPowerNet().subscribe(this);
if(con.getPowerNet() != null)
red = true;
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "power");
double posX = x + 0.5 + dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 + dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 + dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", -dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", -dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", -dir.offsetZ * (red ? 0.025 : 0.1));
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public default void tryUnsubscribe(World world, int x, int y, int z) {
TileEntity te = world.getTileEntity(x, y, z);
if(te instanceof IEnergyConductor) {
IEnergyConductor con = (IEnergyConductor) te;
if(con.getPowerNet() != null && con.getPowerNet().isSubscribed(this))
con.getPowerNet().unsubscribe(this);
}
}
public static final boolean particleDebug = false;
public default Vec3 getDebugParticlePos() {
TileEntity te = (TileEntity) this;
Vec3 vec = Vec3.createVectorHelper(te.xCoord + 0.5, te.yCoord + 1, te.zCoord + 0.5);
return vec;
}
/** Shortcut for adding energy data to tiles that implement IInfoProviderEC, should NOT be used externally for compat! Use IInfoProviderEC.provideInfo() instead! */
public default void provideInfoForEC(NBTTagCompound data) {
data.setLong(CompatEnergyControl.L_ENERGY_HE, this.getPower());
data.setLong(CompatEnergyControl.L_CAPACITY_HE, this.getMaxPower());
}
public default ConnectionPriority getPriority() {
return ConnectionPriority.NORMAL;
}
public enum ConnectionPriority {
LOW,
NORMAL,
HIGH
}
}

View File

@ -1,4 +1,4 @@
package api.hbm.energymk2;
package api.hbm.energy;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;

View File

@ -0,0 +1,19 @@
package api.hbm.energy;
public interface IEnergyGenerator extends IEnergyUser {
/**
* Standard implementation for machines that can only send energy but never receive it.
* @param power
*/
@Override
public default long transferPower(long power) {
return power;
}
/* should stop making non-receivers from interfering by applying their weight which doesn't even matter */
@Override
public default long getTransferWeight() {
return 0;
}
}

View File

@ -0,0 +1,114 @@
package api.hbm.energy;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/**
* For machines and things that have an energy buffer and are affected by EMPs
* @author hbm
*/
public interface IEnergyUser extends IEnergyConnector {
/**
* Not to be used for actual energy transfer, rather special external things like EMPs and sync packets
*/
public void setPower(long power);
/**
* Standard implementation for power transfer.
* Turns out you can override interfaces to provide a default implementation. Neat.
* @param long power
*/
@Override
public default long transferPower(long power) {
if(this.getPower() + power > this.getMaxPower()) {
long overshoot = this.getPower() + power - this.getMaxPower();
this.setPower(this.getMaxPower());
return overshoot;
}
if(this.getPower() + power < 0) return 0; //safeguard for negative energy or overflows
this.setPower(this.getPower() + power);
return 0;
}
/**
* Standard implementation of sending power
* @param world
* @param x
* @param y
* @param z
* @param dir
*/
public default void sendPower(World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = world.getTileEntity(x, y, z);
boolean wasSubscribed = false;
boolean red = false;
// first we make sure we're not subscribed to the network that we'll be supplying
if(te instanceof IEnergyConductor) {
IEnergyConductor con = (IEnergyConductor) te;
if(con.canConnect(dir.getOpposite()) && con.getPowerNet() != null && con.getPowerNet().isSubscribed(this)) {
con.getPowerNet().unsubscribe(this);
wasSubscribed = true;
}
}
//then we add energy
if(te instanceof IEnergyConnector) {
IEnergyConnector con = (IEnergyConnector) te;
if(con.canConnect(dir.getOpposite())) {
long oldPower = this.getPower();
long transfer = oldPower - con.transferPower(oldPower);
this.setPower(oldPower - transfer);
red = true;
}
}
//then we subscribe if possible
if(wasSubscribed && te instanceof IEnergyConductor) {
IEnergyConductor con = (IEnergyConductor) te;
if(con.getPowerNet() != null && !con.getPowerNet().isSubscribed(this)) {
con.getPowerNet().subscribe(this);
}
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "power");
double posX = x + 0.5 - dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 - dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 - dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", dir.offsetZ * (red ? 0.025 : 0.1));
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public default void updateStandardConnections(World world, TileEntity te) {
updateStandardConnections(world, te.xCoord, te.yCoord, te.zCoord);
}
public default void updateStandardConnections(World world, int x, int y, int z) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
this.trySubscribe(world, x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ, dir);
}
}
}

View File

@ -0,0 +1,6 @@
package api.hbm.energy;
public interface ILoadedTile {
public boolean isLoaded();
}

View File

@ -0,0 +1,37 @@
package api.hbm.energy;
import java.math.BigInteger;
import java.util.List;
/**
* Not mandatory to use, but making your cables IPowerNet-compliant will allow them to connect to NTM cables.
* Cables will still work without it as long as they implement IEnergyConductor (or even IEnergyConnector) + self-built network code
* @author hbm
*/
public interface IPowerNet {
public void joinNetworks(IPowerNet network);
public IPowerNet joinLink(IEnergyConductor conductor);
public void leaveLink(IEnergyConductor conductor);
public void subscribe(IEnergyConnector connector);
public void unsubscribe(IEnergyConnector connector);
public boolean isSubscribed(IEnergyConnector connector);
public void destroy();
/**
* When a link is removed, instead of destroying the network, causing it to be recreated from currently loaded conductors,
* we re-evaluate it, creating new nets based on the previous links.
*/
public void reevaluate();
public boolean isValid();
public List<IEnergyConductor> getLinks();
public List<IEnergyConnector> getSubscribers();
public long transferPower(long power);
public BigInteger getTotalTransfer();
}

View File

@ -0,0 +1,257 @@
package api.hbm.energy;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.hbm.config.GeneralConfig;
import api.hbm.energy.IEnergyConnector.ConnectionPriority;
import net.minecraft.tileentity.TileEntity;
/**
* Basic IPowerNet implementation. The behavior of this demo might change inbetween releases, but the API remains the same.
* For more consistency please implement your own IPowerNet.
* @author hbm
*/
public class PowerNet implements IPowerNet {
private boolean valid = true;
private HashMap<Integer, IEnergyConductor> links = new HashMap();
private HashMap<Integer, Integer> proxies = new HashMap();
private List<IEnergyConnector> subscribers = new ArrayList();
public static List<PowerNet> trackingInstances = null;
protected BigInteger totalTransfer = BigInteger.ZERO;
@Override
public void joinNetworks(IPowerNet network) {
if(network == this)
return; //wtf?!
for(IEnergyConductor conductor : network.getLinks()) {
joinLink(conductor);
}
network.getLinks().clear();
for(IEnergyConnector connector : network.getSubscribers()) {
this.subscribe(connector);
}
network.destroy();
}
@Override
public IPowerNet joinLink(IEnergyConductor conductor) {
if(conductor.getPowerNet() != null)
conductor.getPowerNet().leaveLink(conductor);
conductor.setPowerNet(this);
int identity = conductor.getIdentity();
this.links.put(identity, conductor);
if(conductor.hasProxies()) {
for(Integer i : conductor.getProxies()) {
this.proxies.put(i, identity);
}
}
return this;
}
@Override
public void leaveLink(IEnergyConductor conductor) {
conductor.setPowerNet(null);
int identity = conductor.getIdentity();
this.links.remove(identity);
if(conductor.hasProxies()) {
for(Integer i : conductor.getProxies()) {
this.proxies.remove(i);
}
}
}
@Override
public void subscribe(IEnergyConnector connector) {
this.subscribers.add(connector);
}
@Override
public void unsubscribe(IEnergyConnector connector) {
this.subscribers.remove(connector);
}
@Override
public boolean isSubscribed(IEnergyConnector connector) {
return this.subscribers.contains(connector);
}
@Override
public List<IEnergyConductor> getLinks() {
List<IEnergyConductor> linkList = new ArrayList();
linkList.addAll(this.links.values());
return linkList;
}
public HashMap<Integer, Integer> getProxies() {
HashMap<Integer, Integer> proxyCopy = new HashMap(proxies);
return proxyCopy;
}
@Override
public List<IEnergyConnector> getSubscribers() {
return this.subscribers;
}
@Override
public void destroy() {
this.valid = false;
this.subscribers.clear();
for(IEnergyConductor link : this.links.values()) {
link.setPowerNet(null);
}
this.links.clear();
}
@Override
public boolean isValid() {
return this.valid;
}
@Override
public BigInteger getTotalTransfer() {
return this.totalTransfer;
}
public long lastCleanup = System.currentTimeMillis();
@Override
public long transferPower(long power) {
/*if(lastCleanup + 45 < System.currentTimeMillis()) {
cleanup(this.subscribers);
lastCleanup = System.currentTimeMillis();
}*/
List<PowerNet> cache = new ArrayList();
if(trackingInstances != null && !trackingInstances.isEmpty()) {
cache.addAll(trackingInstances);
}
trackingInstances = new ArrayList();
trackingInstances.add(this);
long result = fairTransfer(this.subscribers, power);
trackingInstances.addAll(cache);
return result;
}
public static void cleanup(List<IEnergyConnector> subscribers) {
subscribers.removeIf(x ->
x == null || !(x instanceof TileEntity) || ((TileEntity)x).isInvalid() || !x.isLoaded()
);
}
public static long fairTransfer(List<IEnergyConnector> subscribers, long power) {
if(power <= 0) return 0;
if(subscribers.isEmpty())
return power;
cleanup(subscribers);
ConnectionPriority[] priorities = new ConnectionPriority[] {ConnectionPriority.HIGH, ConnectionPriority.NORMAL, ConnectionPriority.LOW};
long totalTransfer = 0;
for(ConnectionPriority p : priorities) {
List<IEnergyConnector> subList = new ArrayList();
subscribers.forEach(x -> {
if(x.getPriority() == p) {
subList.add(x);
}
});
if(subList.isEmpty())
continue;
List<Long> weight = new ArrayList();
long totalReq = 0;
for(IEnergyConnector con : subList) {
long req = con.getTransferWeight();
weight.add(req);
totalReq += req;
}
if(totalReq == 0)
continue;
long totalGiven = 0;
for(int i = 0; i < subList.size(); i++) {
IEnergyConnector con = subList.get(i);
long req = weight.get(i);
double fraction = (double)req / (double)totalReq;
long given = (long) Math.floor(fraction * power);
totalGiven += (given - con.transferPower(given));
if(con instanceof TileEntity) {
TileEntity tile = (TileEntity) con;
tile.getWorldObj().markTileEntityChunkModified(tile.xCoord, tile.yCoord, tile.zCoord, tile);
}
}
power -= totalGiven;
totalTransfer += totalGiven;
}
if(trackingInstances != null) {
for(int i = 0; i < trackingInstances.size(); i++) {
PowerNet net = trackingInstances.get(i);
net.totalTransfer = net.totalTransfer.add(BigInteger.valueOf(totalTransfer));
}
trackingInstances.clear();
}
return power;
}
@Override
public void reevaluate() {
if(!GeneralConfig.enableReEval) {
this.destroy();
return;
}
HashMap<Integer, IEnergyConductor> copy = new HashMap(links);
HashMap<Integer, Integer> proxyCopy = new HashMap(proxies);
for(IEnergyConductor link : copy.values()) {
this.leaveLink(link);
}
for(IEnergyConductor link : copy.values()) {
link.setPowerNet(null);
link.reevaluate(copy, proxyCopy);
if(link.getPowerNet() == null) {
link.setPowerNet(new PowerNet().joinLink(link));
}
}
}
}

View File

@ -1,23 +0,0 @@
package api.hbm.energymk2;
import com.hbm.lib.Library;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
import api.hbm.energymk2.Nodespace.PowerNode;
import net.minecraft.tileentity.TileEntity;
public interface IEnergyConductorMK2 extends IEnergyConnectorMK2 {
public default PowerNode createNode() {
TileEntity tile = (TileEntity) this;
return new PowerNode(new BlockPos(tile.xCoord, tile.yCoord, tile.zCoord)).setConnections(
new DirPos(tile.xCoord + 1, tile.yCoord, tile.zCoord, Library.POS_X),
new DirPos(tile.xCoord - 1, tile.yCoord, tile.zCoord, Library.NEG_X),
new DirPos(tile.xCoord, tile.yCoord + 1, tile.zCoord, Library.POS_Y),
new DirPos(tile.xCoord, tile.yCoord - 1, tile.zCoord, Library.NEG_Y),
new DirPos(tile.xCoord, tile.yCoord, tile.zCoord + 1, Library.POS_Z),
new DirPos(tile.xCoord, tile.yCoord, tile.zCoord - 1, Library.NEG_Z)
);
}
}

View File

@ -1,16 +0,0 @@
package api.hbm.energymk2;
import net.minecraftforge.common.util.ForgeDirection;
public interface IEnergyConnectorMK2 {
/**
* Whether the given side can be connected to
* dir refers to the side of this block, not the connecting block doing the check
* @param dir
* @return
*/
public default boolean canConnect(ForgeDirection dir) {
return dir != ForgeDirection.UNKNOWN;
}
}

View File

@ -1,29 +0,0 @@
package api.hbm.energymk2;
import com.hbm.util.CompatEnergyControl;
import api.hbm.tile.ILoadedTile;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.Vec3;
/** DO NOT USE DIRECTLY! This is simply the common ancestor to providers and receivers, because all this behavior has to be excluded from conductors! */
public interface IEnergyHandlerMK2 extends IEnergyConnectorMK2, ILoadedTile {
public long getPower();
public void setPower(long power);
public long getMaxPower();
public static final boolean particleDebug = false;
public default Vec3 getDebugParticlePosMK2() {
TileEntity te = (TileEntity) this;
Vec3 vec = Vec3.createVectorHelper(te.xCoord + 0.5, te.yCoord + 1, te.zCoord + 0.5);
return vec;
}
public default void provideInfoForECMK2(NBTTagCompound data) {
data.setLong(CompatEnergyControl.L_ENERGY_HE, this.getPower());
data.setLong(CompatEnergyControl.L_CAPACITY_HE, this.getMaxPower());
}
}

View File

@ -1,67 +0,0 @@
package api.hbm.energymk2;
import com.hbm.handler.threading.PacketThreading;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import api.hbm.energymk2.Nodespace.PowerNode;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/** If it sends energy, use this */
public interface IEnergyProviderMK2 extends IEnergyHandlerMK2 {
/** Uses up available power, default implementation has no sanity checking, make sure that the requested power is lequal to the current power */
public default void usePower(long power) {
this.setPower(this.getPower() - power);
}
public default long getProviderSpeed() {
return this.getMaxPower();
}
public default void tryProvide(World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = TileAccessCache.getTileOrCache(world, x, y, z);
boolean red = false;
if(te instanceof IEnergyConductorMK2) {
IEnergyConductorMK2 con = (IEnergyConductorMK2) te;
if(con.canConnect(dir.getOpposite())) {
PowerNode node = Nodespace.getNode(world, x, y, z);
if(node != null && node.net != null) {
node.net.addProvider(this);
red = true;
}
}
}
if(te instanceof IEnergyReceiverMK2 && te != this) {
IEnergyReceiverMK2 rec = (IEnergyReceiverMK2) te;
if(rec.canConnect(dir.getOpposite()) && rec.allowDirectProvision()) {
long provides = Math.min(this.getPower(), this.getProviderSpeed());
long receives = Math.min(rec.getMaxPower() - rec.getPower(), rec.getReceiverSpeed());
long toTransfer = Math.min(provides, receives);
toTransfer -= rec.transferPower(toTransfer);
this.usePower(toTransfer);
}
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "power");
double posX = x + 0.5 - dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 - dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 - dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", dir.offsetZ * (red ? 0.025 : 0.1));
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
}

View File

@ -1,95 +0,0 @@
package api.hbm.energymk2;
import com.hbm.handler.threading.PacketThreading;
import com.hbm.interfaces.NotableComments;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import com.hbm.util.fauxpointtwelve.DirPos;
import api.hbm.energymk2.Nodespace.PowerNode;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/** If it receives energy, use this */
@NotableComments
public interface IEnergyReceiverMK2 extends IEnergyHandlerMK2 {
public default long transferPower(long power) {
if(power + this.getPower() <= this.getMaxPower()) {
this.setPower(power + this.getPower());
return 0;
}
long capacity = this.getMaxPower() - this.getPower();
long overshoot = power - capacity;
this.setPower(this.getMaxPower());
return overshoot;
}
public default long getReceiverSpeed() {
return this.getMaxPower();
}
/** Whether a provider can provide power by touching the block (i.e. via proxies), bypassing the need for a network entirely */
public default boolean allowDirectProvision() { return true; }
public default void trySubscribe(World world, DirPos pos) { trySubscribe(world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void trySubscribe(World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = TileAccessCache.getTileOrCache(world, x, y, z);
boolean red = false;
if(te instanceof IEnergyConductorMK2) {
IEnergyConductorMK2 con = (IEnergyConductorMK2) te;
if(!con.canConnect(dir.getOpposite())) return;
PowerNode node = Nodespace.getNode(world, x, y, z);
if(node != null && node.net != null) {
node.net.addReceiver(this);
red = true;
}
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "power");
double posX = x + 0.5 + dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 + dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 + dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", -dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", -dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", -dir.offsetZ * (red ? 0.025 : 0.1));
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public default void tryUnsubscribe(World world, int x, int y, int z) {
TileEntity te = world.getTileEntity(x, y, z);
if(te instanceof IEnergyConductorMK2) {
IEnergyConductorMK2 con = (IEnergyConductorMK2) te;
PowerNode node = con.createNode();
if(node != null && node.net != null) {
node.net.removeReceiver(this);
}
}
}
public enum ConnectionPriority {
LOWEST,
LOW,
NORMAL,
HIGH,
HIGHEST
}
public default ConnectionPriority getPriority() {
return ConnectionPriority.NORMAL;
}
}

View File

@ -1,62 +0,0 @@
package api.hbm.energymk2;
import com.hbm.interfaces.NotableComments;
import com.hbm.uninos.GenNode;
import com.hbm.uninos.UniNodespace;
import com.hbm.uninos.networkproviders.PowerNetProvider;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
import net.minecraft.world.World;
/**
* The dead fucking corpse of nodespace MK1.
* A fantastic proof of concept, but ultimately it was killed for being just not that versatile.
* This class is mostly just a compatibility husk that should allow uninodespace to slide into the mod with as much lubrication as it deserves.
*
* @author hbm
*/
@NotableComments
public class Nodespace {
public static final PowerNetProvider THE_POWER_PROVIDER = new PowerNetProvider();
@Deprecated public static PowerNode getNode(World world, int x, int y, int z) {
return (PowerNode) UniNodespace.getNode(world, x, y, z, THE_POWER_PROVIDER);
}
@Deprecated public static void createNode(World world, PowerNode node) {
UniNodespace.createNode(world, node);
}
@Deprecated public static void destroyNode(World world, int x, int y, int z) {
UniNodespace.destroyNode(world, x, y, z, THE_POWER_PROVIDER);
}
@NotableComments
public static class PowerNode extends GenNode<PowerNetMK2> {
/**
* Okay so here's the deal: The code has shit idiot brain fungus. I don't know why. I re-tested every part involved several times.
* I don't know why. But for some reason, during neighbor checks, on certain arbitrary fucking places, the joining operation just fails.
* Disallowing nodes to create new networks fixed the problem completely, which is hardly surprising since they wouldn't be able to make
* a new net anyway and they will re-check neighbors until a net is found, so the solution is tautological in nature. So I tried limiting
* creation of new networks. Didn't work. So what's there left to do? Hand out a mark to any node that has changed networks, and let those
* recently modified nodes do another re-check. This creates a second layer of redundant operations, and in theory doubles (in practice,
* it might be an extra 20% due to break-off section sizes) the amount of CPU time needed for re-building the networks after joining or
* breaking, but it seems to allow those parts to connect back to their neighbor nets as they are supposed to. I am not proud of this solution,
* this issue shouldn't exist to begin with and I am going fucking insane but it is what it is.
*/
public PowerNode(BlockPos... positions) {
super(THE_POWER_PROVIDER, positions);
this.positions = positions;
}
@Override
public PowerNode setConnections(DirPos... connections) {
super.setConnections(connections);
return this;
}
}
}

View File

@ -1,156 +0,0 @@
package api.hbm.energymk2;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import com.hbm.uninos.NodeNet;
import com.hbm.util.Tuple.Pair;
import java.util.Map.Entry;
import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority;
import api.hbm.energymk2.Nodespace.PowerNode;
/**
* Technically MK3 since it's now UNINOS compatible, although UNINOS was build out of 95% nodespace code
*
* @author hbm
*/
public class PowerNetMK2 extends NodeNet<IEnergyReceiverMK2, IEnergyProviderMK2, PowerNode> {
public long energyTracker = 0L;
protected static int timeout = 3_000;
@Override public void resetTrackers() { this.energyTracker = 0; }
@Override
public void update() {
if(providerEntries.isEmpty()) return;
if(receiverEntries.isEmpty()) return;
long timestamp = System.currentTimeMillis();
List<Pair<IEnergyProviderMK2, Long>> providers = new ArrayList();
long powerAvailable = 0;
// sum up available power
Iterator<Entry<IEnergyProviderMK2, Long>> provIt = providerEntries.entrySet().iterator();
while(provIt.hasNext()) {
Entry<IEnergyProviderMK2, Long> entry = provIt.next();
if(timestamp - entry.getValue() > timeout || isBadLink(entry.getKey())) { provIt.remove(); continue; }
long src = Math.min(entry.getKey().getPower(), entry.getKey().getProviderSpeed());
if(src > 0) {
providers.add(new Pair(entry.getKey(), src));
powerAvailable += src;
}
}
// sum up total demand, categorized by priority
List<Pair<IEnergyReceiverMK2, Long>>[] receivers = new ArrayList[ConnectionPriority.values().length];
for(int i = 0; i < receivers.length; i++) receivers[i] = new ArrayList();
long[] demand = new long[ConnectionPriority.values().length];
long totalDemand = 0;
Iterator<Entry<IEnergyReceiverMK2, Long>> recIt = receiverEntries.entrySet().iterator();
while(recIt.hasNext()) {
Entry<IEnergyReceiverMK2, Long> entry = recIt.next();
if(timestamp - entry.getValue() > timeout || isBadLink(entry.getKey())) { recIt.remove(); continue; }
long rec = Math.min(entry.getKey().getMaxPower() - entry.getKey().getPower(), entry.getKey().getReceiverSpeed());
if(rec > 0) {
int p = entry.getKey().getPriority().ordinal();
receivers[p].add(new Pair(entry.getKey(), rec));
demand[p] += rec;
totalDemand += rec;
}
}
long toTransfer = Math.min(powerAvailable, totalDemand);
long energyUsed = 0;
// add power to receivers, ordered by priority
for(int i = ConnectionPriority.values().length - 1; i >= 0; i--) {
List<Pair<IEnergyReceiverMK2, Long>> list = receivers[i];
long priorityDemand = demand[i];
for(Pair<IEnergyReceiverMK2, Long> entry : list) {
double weight = (double) entry.getValue() / (double) (priorityDemand);
long toSend = (long) Math.min(Math.max(toTransfer * weight, 0D), entry.getValue());
energyUsed += (toSend - entry.getKey().transferPower(toSend)); //leftovers are subtracted from the intended amount to use up
}
toTransfer -= energyUsed;
}
this.energyTracker += energyUsed;
long leftover = energyUsed;
// remove power from providers
for(Pair<IEnergyProviderMK2, Long> entry : providers) {
double weight = (double) entry.getValue() / (double) powerAvailable;
long toUse = (long) Math.max(energyUsed * weight, 0D);
entry.getKey().usePower(toUse);
leftover -= toUse;
}
// rounding error compensation, detects surplus that hasn't been used and removes it from random providers
int iterationsLeft = 100; // whiles without emergency brakes are a bad idea
while(iterationsLeft > 0 && leftover > 0 && providers.size() > 0) {
iterationsLeft--;
Pair<IEnergyProviderMK2, Long> selected = providers.get(rand.nextInt(providers.size()));
IEnergyProviderMK2 scapegoat = selected.getKey();
long toUse = Math.min(leftover, scapegoat.getPower());
scapegoat.usePower(toUse);
leftover -= toUse;
}
}
public long sendPowerDiode(long power) {
if(receiverEntries.isEmpty()) return power;
long timestamp = System.currentTimeMillis();
List<Pair<IEnergyReceiverMK2, Long>>[] receivers = new ArrayList[ConnectionPriority.values().length];
for(int i = 0; i < receivers.length; i++) receivers[i] = new ArrayList();
long[] demand = new long[ConnectionPriority.values().length];
long totalDemand = 0;
Iterator<Entry<IEnergyReceiverMK2, Long>> recIt = receiverEntries.entrySet().iterator();
while(recIt.hasNext()) {
Entry<IEnergyReceiverMK2, Long> entry = recIt.next();
if(timestamp - entry.getValue() > timeout) { recIt.remove(); continue; }
long rec = Math.min(entry.getKey().getMaxPower() - entry.getKey().getPower(), entry.getKey().getReceiverSpeed());
int p = entry.getKey().getPriority().ordinal();
receivers[p].add(new Pair(entry.getKey(), rec));
demand[p] += rec;
totalDemand += rec;
}
long toTransfer = Math.min(power, totalDemand);
long energyUsed = 0;
for(int i = ConnectionPriority.values().length - 1; i >= 0; i--) {
List<Pair<IEnergyReceiverMK2, Long>> list = receivers[i];
long priorityDemand = demand[i];
for(Pair<IEnergyReceiverMK2, Long> entry : list) {
double weight = (double) entry.getValue() / (double) (priorityDemand);
long toSend = (long) Math.max(toTransfer * weight, 0D);
energyUsed += (toSend - entry.getKey().transferPower(toSend)); //leftovers are subtracted from the intended amount to use up
}
toTransfer -= energyUsed;
}
this.energyTracker += energyUsed;
return power - energyUsed;
}
}

View File

@ -1,33 +0,0 @@
/**
*
*/
/**
* @author hbm
*
*/
package api.hbm.energymk2;
// i have snorted two lines of pure caffeine and taken one large paracetamol laced with even more caffine, let's fucking go
//most of the new classes are just copy pasted mashed up shit from yesteryear, what a productive segment that was
/*
before my caffine high ends entirely and i black out, here's the gist:
* diodes are handled like energy receiver and simply chain-load the power net they output into in a recursive function, this might be a bit laggy compared to the rest of the system, but it's still way less laggy than the old one
* instead of power nets being bound to tile entities directly, tiles spawn ethereal "nodes" similar to the drone waypoints which can be saved using world data, meaning that breaking cables will delete nodes, but unloading them will keep them alive in "node space" which is what's actually used to check for connections
* power nets may cache some positional info in order to limit the amount of nodes, this should prevent horrific freezes in the unlikely event that some retard makes a superflat world out of cables
* general energy transmission will work in a similar fashion as martin explained his, but somewhat simplified; the system will determine supply and demand and then split those evenly if possible, retrying within one operation is only necessary for minor restrictions like priority, any leftovers from rounding don't have to be re-tried because the next tick will already take care of that
* invest funds in more coal mare nudes
* battery "fair share" transfer will most likely no longer work, but that's not really as relevant these days considering there's capacitors and because batteries have transfer speed limits anyway
* most of the machine's functions will be repurposed, the "sendPower" method will no longer send power directly but register the machine to the network as a power source
* if all else fails and martin still hasn't surrendered his code, i will beg greg for his wisdom (but without loss or tiering because fuck that)
*
* | | ||
* ____|____
* |
* || | |_
*
* ...i said WITHOUT loss
*/

View File

@ -1,16 +0,0 @@
package api.hbm.entity;
import net.minecraft.util.DamageSource;
/**
* Allows custom entities to specify threshold and resistance values based on incoming damage, type and piercing values, along with whatever other internal stats
* the entity has (like glyphid armor). Obviously only works for our own custom entities implementing this, everything else will have to work with the less powerful
* (but still very useful) entity stats in the DamageResistanceHandler.
*
* @author hbm
*/
public interface IResistanceProvider {
public float[] getCurrentDTDR(DamageSource damage, float amount, float pierceDT, float pierce);
public void onDamageDealt(DamageSource damage, float amount);
}

View File

@ -1,4 +1,4 @@
package api.hbm.fluidmk2;
package api.hbm.fluid;
import com.hbm.inventory.fluid.FluidType;

View File

@ -0,0 +1,19 @@
package api.hbm.fluid;
import com.hbm.inventory.fluid.FluidType;
public interface IFluidConductor extends IFluidConnector {
public IPipeNet getPipeNet(FluidType type);
public void setPipeNet(FluidType type, IPipeNet network);
@Override
public default long transferFluid(FluidType type, int pressure, long amount) {
if(this.getPipeNet(type) == null)
return amount;
return this.getPipeNet(type).transferFluid(amount, pressure);
}
}

View File

@ -1,6 +1,92 @@
package api.hbm.fluid;
import api.hbm.fluidmk2.IFluidConnectorMK2;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
@Deprecated
public interface IFluidConnector extends IFluidConnectorMK2 { }
import api.hbm.energy.ILoadedTile;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public interface IFluidConnector extends ILoadedTile {
/**
* Returns the amount of fluid that remains
* @param power
* @return
*/
public long transferFluid(FluidType type, int pressure, long fluid);
/**
* Whether the given side can be connected to
* @param dir
* @return
*/
public default boolean canConnect(FluidType type, ForgeDirection dir) {
return dir != ForgeDirection.UNKNOWN;
}
/**
* Returns the amount of fluid that this machine is able to receive
* @param type
* @return
*/
public long getDemand(FluidType type, int pressure);
/**
* Basic implementation of subscribing to a nearby power grid
* @param world
* @param x
* @param y
* @param z
*/
public default void trySubscribe(FluidType type, World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = world.getTileEntity(x, y, z);
boolean red = false;
if(te instanceof IFluidConductor) {
IFluidConductor con = (IFluidConductor) te;
if(!con.canConnect(type, dir))
return;
if(con.getPipeNet(type) != null && !con.getPipeNet(type).isSubscribed(this))
con.getPipeNet(type).subscribe(this);
if(con.getPipeNet(type) != null)
red = true;
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "fluid");
data.setInteger("color", type.getColor());
double posX = x + 0.5 + dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 + dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 + dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", -dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", -dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", -dir.offsetZ * (red ? 0.025 : 0.1));
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public default void tryUnsubscribe(FluidType type, World world, int x, int y, int z) {
TileEntity te = world.getTileEntity(x, y, z);
if(te instanceof IFluidConductor) {
IFluidConductor con = (IFluidConductor) te;
if(con.getPipeNet(type) != null && con.getPipeNet(type).isSubscribed(this))
con.getPipeNet(type).unsubscribe(this);
}
}
public static final boolean particleDebug = false;
}

View File

@ -1,6 +1,12 @@
package api.hbm.fluid;
import api.hbm.fluidmk2.IFluidConnectorBlockMK2;
import com.hbm.inventory.fluid.FluidType;
@Deprecated
public interface IFluidConnectorBlock extends IFluidConnectorBlockMK2 { }
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
public interface IFluidConnectorBlock {
/** dir is the face that is connected to, the direction going outwards from the block */
public boolean canConnect(FluidType type, IBlockAccess world, int x, int y, int z, ForgeDirection dir);
}

View File

@ -1,35 +1,49 @@
package api.hbm.fluid;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.uninos.GenNode;
import com.hbm.uninos.UniNodespace;
import com.hbm.inventory.fluid.tank.FluidTank;
import api.hbm.fluidmk2.IFluidStandardReceiverMK2;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Uses default implementation to make the underlying interfaces easier to use for the most common fluid users.
* Only handles a single input tank of the same type.
* Uses standard FluidTanks which use int32.
* Don't use this as part of the API!
* @author hbm
*
*/
public interface IFluidStandardReceiver extends IFluidUser {
@Override
public default long transferFluid(FluidType type, int pressure, long amount) {
@Deprecated
public interface IFluidStandardReceiver extends IFluidStandardReceiverMK2 {
public default void subscribeToAllAround(FluidType type, TileEntity tile) {
subscribeToAllAround(type, tile.getWorldObj(), tile.xCoord, tile.yCoord, tile.zCoord);
}
public default void subscribeToAllAround(FluidType type, World world, int x, int y, int z) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
trySubscribe(type, world, x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ, dir);
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
tank.setFill(tank.getFill() + (int) amount);
if(tank.getFill() > tank.getMaxFill()) {
long overshoot = tank.getFill() - tank.getMaxFill();
tank.setFill(tank.getMaxFill());
return overshoot;
}
return 0;
}
}
return amount;
}
public default void tryUnsubscribe(FluidType type, World world, int x, int y, int z) {
GenNode node = UniNodespace.getNode(world, x, y, z, type.getNetworkProvider());
if(node != null && node.net != null) node.net.removeReceiver(this);
}
public FluidTank[] getReceivingTanks();
public default void unsubscribeToAllAround(FluidType type, TileEntity tile) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
tryUnsubscribe(type, tile.getWorldObj(), tile.xCoord + dir.offsetX, tile.yCoord + dir.offsetY, tile.zCoord + dir.offsetZ);
@Override
public default long getDemand(FluidType type, int pressure) {
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
return tank.getMaxFill() - tank.getFill();
}
}
return 0;
}
}

View File

@ -1,22 +1,50 @@
package api.hbm.fluid;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.inventory.fluid.tank.FluidTank;
import api.hbm.fluidmk2.IFluidStandardSenderMK2;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/**
* Uses default implementation to make the underlying interfaces easier to use for the most common fluid users.
* Only handles a single output tank of the same type.
* Uses standard FluidTanks which use int32.
* Don't use this as part of the API!
* @author hbm
*
*/
public interface IFluidStandardSender extends IFluidUser {
@Deprecated
public interface IFluidStandardSender extends IFluidStandardSenderMK2 {
public default void sendFluid(FluidTank tank, World world, int x, int y, int z, ForgeDirection dir) {
tryProvide(tank, world, x, y, z, dir);
public FluidTank[] getSendingTanks();
@Override
public default long getTotalFluidForSend(FluidType type, int pressure) {
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
return tank.getFill();
}
}
return 0;
}
public default void sendFluidToAll(FluidTank tank, TileEntity tile) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
tryProvide(tank, tile.getWorldObj(), tile.xCoord + dir.offsetX, tile.yCoord + dir.offsetY, tile.zCoord + dir.offsetZ, dir);
@Override
public default void removeFluidForTransfer(FluidType type, int pressure, long amount) {
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
tank.setFill(tank.getFill() - (int) amount);
return;
}
}
}
@Override
public default long transferFluid(FluidType type, int pressure, long fluid) {
return fluid;
}
@Override
public default long getDemand(FluidType type, int pressure) {
return 0;
}
}

View File

@ -1,4 +1,79 @@
package api.hbm.fluid;
@Deprecated
public interface IFluidStandardTransceiver extends IFluidStandardReceiver, IFluidStandardSender { }
import com.hbm.inventory.fluid.FluidType;
import com.hbm.inventory.fluid.tank.FluidTank;
/**
* transceiver [trăn-vər], noun
*
* 1. A transmitter and receiver housed together in a single unit and having some circuits in common, often for portable or mobile use.
* 2. A combined radio transmitter and receiver.
* 3. A device that performs transmitting and receiving functions, especially if using common components.
*
* The American Heritage® Dictionary of the English Language, 5th Edition.
*
* Only supports one tank per type (for in- and output separately)
*
* @author hbm
*
*/
public interface IFluidStandardTransceiver extends IFluidUser {
public FluidTank[] getSendingTanks();
public FluidTank[] getReceivingTanks();
@Override
public default long getTotalFluidForSend(FluidType type, int pressure) {
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
return tank.getFill();
}
}
return 0;
}
@Override
public default void removeFluidForTransfer(FluidType type, int pressure, long amount) {
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
tank.setFill(tank.getFill() - (int) amount);
return;
}
}
}
@Override
public default long getDemand(FluidType type, int pressure) {
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
return tank.getMaxFill() - tank.getFill();
}
}
return 0;
}
@Override
public default long transferFluid(FluidType type, int pressure, long amount) {
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
tank.setFill(tank.getFill() + (int) amount);
if(tank.getFill() > tank.getMaxFill()) {
long overshoot = tank.getFill() - tank.getMaxFill();
tank.setFill(tank.getMaxFill());
return overshoot;
}
return 0;
}
}
return amount;
}
}

View File

@ -0,0 +1,129 @@
package api.hbm.fluid;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.inventory.fluid.tank.FluidTank;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public interface IFluidUser extends IFluidConnector {
public default void sendFluid(FluidTank tank, World world, int x, int y, int z, ForgeDirection dir) {
sendFluid(tank.getTankType(), tank.getPressure(), world, x, y, z, dir);
}
public default void sendFluid(FluidType type, int pressure, World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = world.getTileEntity(x, y, z);
boolean wasSubscribed = false;
boolean red = false;
if(te instanceof IFluidConductor) {
IFluidConductor con = (IFluidConductor) te;
if(con.getPipeNet(type) != null && con.getPipeNet(type).isSubscribed(this)) {
con.getPipeNet(type).unsubscribe(this);
wasSubscribed = true;
}
}
if(te instanceof IFluidConnector) {
IFluidConnector con = (IFluidConnector) te;
if(con.canConnect(type, dir.getOpposite())) {
long toSend = this.getTotalFluidForSend(type, pressure);
if(toSend > 0) {
long transfer = toSend - con.transferFluid(type, pressure, toSend);
this.removeFluidForTransfer(type, pressure, transfer);
}
red = true;
}
}
if(wasSubscribed && te instanceof IFluidConductor) {
IFluidConductor con = (IFluidConductor) te;
if(con.getPipeNet(type) != null && !con.getPipeNet(type).isSubscribed(this)) {
con.getPipeNet(type).subscribe(this);
}
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "fluid");
data.setInteger("color", type.getColor());
double posX = x + 0.5 - dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 - dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 - dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", dir.offsetZ * (red ? 0.025 : 0.1));
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public static IPipeNet getPipeNet(World world, int x, int y, int z, FluidType type) {
TileEntity te = world.getTileEntity(x, y, z);
if(te instanceof IFluidConductor) {
IFluidConductor con = (IFluidConductor) te;
if(con.getPipeNet(type) != null) {
return con.getPipeNet(type);
}
}
return null;
}
/** Use more common conPos method instead */
@Deprecated public default void sendFluidToAll(FluidTank tank, TileEntity te) {
sendFluidToAll(tank.getTankType(), tank.getPressure(), te);
}
/** Use more common conPos method instead */
@Deprecated public default void sendFluidToAll(FluidType type, int pressure, TileEntity te) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
sendFluid(type, pressure, te.getWorldObj(), te.xCoord + dir.offsetX, te.yCoord + dir.offsetY, te.zCoord + dir.offsetZ, dir);
}
}
public default long getTotalFluidForSend(FluidType type, int pressure) { return 0; }
public default void removeFluidForTransfer(FluidType type, int pressure, long amount) { }
public default void subscribeToAllAround(FluidType type, TileEntity te) {
subscribeToAllAround(type, te.getWorldObj(), te.xCoord, te.yCoord, te.zCoord);
}
public default void subscribeToAllAround(FluidType type, World world, int x, int y, int z) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
this.trySubscribe(type, world, x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ, dir);
}
public default void unsubscribeToAllAround(FluidType type, TileEntity te) {
unsubscribeToAllAround(type, te.getWorldObj(), te.xCoord, te.yCoord, te.zCoord);
}
public default void unsubscribeToAllAround(FluidType type, World world, int x, int y, int z) {
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
this.tryUnsubscribe(type, world, x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ);
}
/**
* Returns all internal tanks of this tile. Not used by the fluid network, it should only be used for display purposes or edge cases that can't be solved otherwise.
* The array is either composed of the original tank or outright the original tank array, so changes done to this array will extend to the IFluidUser.
* @return
*/
public FluidTank[] getAllTanks();
}

View File

@ -0,0 +1,30 @@
package api.hbm.fluid;
import java.math.BigInteger;
import java.util.HashSet;
import java.util.List;
import com.hbm.inventory.fluid.FluidType;
public interface IPipeNet {
public void joinNetworks(IPipeNet network);
public List<IFluidConductor> getLinks();
public HashSet<IFluidConnector> getSubscribers();
public IPipeNet joinLink(IFluidConductor conductor);
public void leaveLink(IFluidConductor conductor);
public void subscribe(IFluidConnector connector);
public void unsubscribe(IFluidConnector connector);
public boolean isSubscribed(IFluidConnector connector);
public void destroy();
public boolean isValid();
public long transferFluid(long fill, int pressure);
public FluidType getType();
public BigInteger getTotalTransfer();
}

View File

@ -0,0 +1,206 @@
package api.hbm.fluid;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.TimeZone;
import com.hbm.inventory.fluid.FluidType;
import net.minecraft.tileentity.TileEntity;
public class PipeNet implements IPipeNet {
private boolean valid = true;
private FluidType type;
private List<IFluidConductor> links = new ArrayList();
private HashSet<IFluidConnector> subscribers = new HashSet();
public static List<PipeNet> trackingInstances = null;
protected BigInteger totalTransfer = BigInteger.ZERO;
public List<String> debug = new ArrayList();
public PipeNet(FluidType type) {
this.type = type;
}
@Override
public void joinNetworks(IPipeNet network) {
if(network == this)
return;
for(IFluidConductor conductor : network.getLinks()) {
conductor.setPipeNet(type, this);
this.getLinks().add(conductor);
}
network.getLinks().clear();
for(IFluidConnector connector : network.getSubscribers()) {
this.subscribe(connector);
}
network.destroy();
}
@Override
public List<IFluidConductor> getLinks() {
return links;
}
@Override
public HashSet<IFluidConnector> getSubscribers() {
return subscribers;
}
@Override
public IPipeNet joinLink(IFluidConductor conductor) {
if(conductor.getPipeNet(type) != null)
conductor.getPipeNet(type).leaveLink(conductor);
conductor.setPipeNet(type, this);
this.links.add(conductor);
return this;
}
@Override
public void leaveLink(IFluidConductor conductor) {
conductor.setPipeNet(type, null);
this.links.remove(conductor);
}
@Override
public void subscribe(IFluidConnector connector) {
this.subscribers.add(connector);
}
@Override
public void unsubscribe(IFluidConnector connector) {
this.subscribers.remove(connector);
}
@Override
public boolean isSubscribed(IFluidConnector connector) {
return this.subscribers.contains(connector);
}
@Override
public long transferFluid(long fill, int pressure) {
subscribers.removeIf(x ->
x == null || !(x instanceof TileEntity) || ((TileEntity)x).isInvalid() || !x.isLoaded()
);
if(this.subscribers.isEmpty())
return fill;
trackingInstances = new ArrayList();
trackingInstances.add(this);
List<IFluidConnector> subList = new ArrayList(subscribers);
return fairTransfer(subList, type, pressure, fill);
}
public static long fairTransfer(List<IFluidConnector> subList, FluidType type, int pressure, long fill) {
if(fill <= 0) return 0;
List<Long> weight = new ArrayList();
long totalReq = 0;
for(IFluidConnector con : subList) {
long req = con.getDemand(type, pressure);
weight.add(req);
totalReq += req;
}
if(totalReq == 0)
return fill;
long totalGiven = 0;
for(int i = 0; i < subList.size(); i++) {
IFluidConnector con = subList.get(i);
long req = weight.get(i);
double fraction = (double)req / (double)totalReq;
long given = (long) Math.floor(fraction * fill);
if(given > 0) {
totalGiven += (given - con.transferFluid(type, pressure, given));
if(con instanceof TileEntity) {
TileEntity tile = (TileEntity) con;
tile.getWorldObj().markTileEntityChunkModified(tile.xCoord, tile.yCoord, tile.zCoord, tile);
}
if(trackingInstances != null) {
for(int j = 0; j < trackingInstances.size(); j++) {
PipeNet net = trackingInstances.get(j);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss:SSS");
sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
log(net, sdf.format(new Date(System.currentTimeMillis())) + " Sending " + given + "mB to " + conToString(con));
}
}
}
}
if(trackingInstances != null) {
for(int i = 0; i < trackingInstances.size(); i++) {
PipeNet net = trackingInstances.get(i);
net.totalTransfer = net.totalTransfer.add(BigInteger.valueOf(totalGiven));
}
}
return fill - totalGiven;
}
@Override
public FluidType getType() {
return type;
}
@Override
public void destroy() {
this.valid = false;
this.subscribers.clear();
for(IFluidConductor con : this.links)
con.setPipeNet(type, null);
this.links.clear();
}
@Override
public boolean isValid() {
return this.valid;
}
@Override
public BigInteger getTotalTransfer() {
return this.totalTransfer;
}
public static void log(PipeNet net, String msg) {
net.debug.add(msg);
while(net.debug.size() > 50) {
net.debug.remove(0);
}
}
public static String conToString(IFluidConnector con) {
if(con instanceof TileEntity) {
TileEntity tile = (TileEntity) con;
return tile.getClass().getSimpleName() + " @ " + tile.xCoord + "/" + tile.yCoord + "/" + tile.zCoord;
}
return "" + con;
}
}

View File

@ -1,152 +0,0 @@
package api.hbm.fluidmk2;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map.Entry;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.uninos.NodeNet;
import com.hbm.util.Tuple.Pair;
import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority;
public class FluidNetMK2 extends NodeNet<IFluidReceiverMK2, IFluidProviderMK2, FluidNode> {
public long fluidTracker = 0L;
protected static int timeout = 3_000;
protected static long currentTime = 0;
protected FluidType type;
public FluidNetMK2(FluidType type) {
this.type = type;
for(int i = 0; i < IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1; i++) providers[i] = new ArrayList();
for(int i = 0; i < IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1; i++) for(int j = 0; j < ConnectionPriority.values().length; j++) receivers[i][j] = new ArrayList();
}
@Override public void resetTrackers() { this.fluidTracker = 0; }
@Override
public void update() {
if(providerEntries.isEmpty()) return;
if(receiverEntries.isEmpty()) return;
currentTime = System.currentTimeMillis();
setupFluidProviders();
setupFluidReceivers();
transferFluid();
cleanUp();
}
//this sucks ass, but it makes the code just a smidge more structured
public long[] fluidAvailable = new long[IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1];
public List<Pair<IFluidProviderMK2, Long>>[] providers = new ArrayList[IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1];
public long[][] fluidDemand = new long[IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1][ConnectionPriority.values().length];
public List<Pair<IFluidReceiverMK2, Long>>[][] receivers = new ArrayList[IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1][ConnectionPriority.values().length];
public long[] transfered = new long[IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1];
public void setupFluidProviders() {
Iterator<Entry<IFluidProviderMK2, Long>> iterator = providerEntries.entrySet().iterator();
while(iterator.hasNext()) {
Entry<IFluidProviderMK2, Long> entry = iterator.next();
if(currentTime - entry.getValue() > timeout || isBadLink(entry.getKey())) { iterator.remove(); continue; }
IFluidProviderMK2 provider = entry.getKey();
int[] pressureRange = provider.getProvidingPressureRange(type);
for(int p = pressureRange[0]; p <= pressureRange[1]; p++) {
long available = Math.min(provider.getFluidAvailable(type, p), provider.getProviderSpeed(type, p));
providers[p].add(new Pair(provider, available));
fluidAvailable[p] += available;
}
}
}
public void setupFluidReceivers() {
Iterator<Entry<IFluidReceiverMK2, Long>> iterator = receiverEntries.entrySet().iterator();
while(iterator.hasNext()) {
Entry<IFluidReceiverMK2, Long> entry = iterator.next();
if(currentTime - entry.getValue() > timeout || isBadLink(entry.getKey())) { iterator.remove(); continue; }
IFluidReceiverMK2 receiver = entry.getKey();
int[] pressureRange = receiver.getReceivingPressureRange(type);
for(int p = pressureRange[0]; p <= pressureRange[1]; p++) {
long required = Math.min(receiver.getDemand(type, p), receiver.getReceiverSpeed(type, p));
int priority = receiver.getFluidPriority().ordinal();
receivers[p][priority].add(new Pair(receiver, required));
fluidDemand[p][priority] += required;
}
}
}
public void transferFluid() {
long[] received = new long[IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1];
long[] notAccountedFor = new long[IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1];
for(int p = 0; p <= IFluidUserMK2.HIGHEST_VALID_PRESSURE; p++) { // if the pressure range were ever to increase, we might have to rethink this
long totalAvailable = fluidAvailable[p];
for(int i = ConnectionPriority.values().length - 1; i >= 0; i--) {
long toTransfer = Math.min(fluidDemand[p][i], totalAvailable);
if(toTransfer <= 0) continue;
long priorityDemand = fluidDemand[p][i];
for(Pair<IFluidReceiverMK2, Long> entry : receivers[p][i]) {
double weight = (double) entry.getValue() / (double) (priorityDemand);
long toSend = (long) Math.max(toTransfer * weight, 0D);
toSend -= entry.getKey().transferFluid(type, p, toSend);
received[p] += toSend;
fluidTracker += toSend;
}
totalAvailable -= received[p];
}
notAccountedFor[p] = received[p];
}
for(int p = 0; p <= IFluidUserMK2.HIGHEST_VALID_PRESSURE; p++) {
for(Pair<IFluidProviderMK2, Long> entry : providers[p]) {
double weight = (double) entry.getValue() / (double) fluidAvailable[p];
long toUse = (long) Math.max(received[p] * weight, 0D);
entry.getKey().useUpFluid(type, p, toUse);
notAccountedFor[p] -= toUse;
}
}
for(int p = 0; p <= IFluidUserMK2.HIGHEST_VALID_PRESSURE; p++) {
int iterationsLeft = 100;
while(iterationsLeft > 0 && notAccountedFor[p] > 0 && providers[p].size() > 0) {
iterationsLeft--;
Pair<IFluidProviderMK2, Long> selected = providers[p].get(rand.nextInt(providers[p].size()));
IFluidProviderMK2 scapegoat = selected.getKey();
long toUse = Math.min(notAccountedFor[p], scapegoat.getFluidAvailable(type, p));
scapegoat.useUpFluid(type, p, toUse);
notAccountedFor[p] -= toUse;
}
}
}
public void cleanUp() {
for(int i = 0; i < IFluidUserMK2.HIGHEST_VALID_PRESSURE + 1; i++) {
fluidAvailable[i] = 0;
providers[i].clear();
transfered[i] = 0;
for(int j = 0; j < ConnectionPriority.values().length; j++) {
fluidDemand[i][j] = 0;
receivers[i][j].clear();
}
}
}
}

View File

@ -1,19 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.uninos.GenNode;
import com.hbm.uninos.INetworkProvider;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
public class FluidNode extends GenNode<FluidNetMK2> {
public FluidNode(INetworkProvider<FluidNetMK2> provider, BlockPos... positions) {
super(provider, positions);
}
@Override
public FluidNode setConnections(DirPos... connections) {
super.setConnections(connections);
return this;
}
}

View File

@ -1,12 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.FluidType;
import net.minecraft.world.IBlockAccess;
import net.minecraftforge.common.util.ForgeDirection;
public interface IFluidConnectorBlockMK2 {
/** dir is the face that is connected to, the direction going outwards from the block */
public boolean canConnect(FluidType type, IBlockAccess world, int x, int y, int z, ForgeDirection dir);
}

View File

@ -1,17 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.FluidType;
import net.minecraftforge.common.util.ForgeDirection;
public interface IFluidConnectorMK2 {
/**
* Whether the given side can be connected to
* @param dir
* @return
*/
public default boolean canConnect(FluidType type, ForgeDirection dir) {
return dir != ForgeDirection.UNKNOWN;
}
}

View File

@ -1,27 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.lib.Library;
import com.hbm.util.fauxpointtwelve.BlockPos;
import com.hbm.util.fauxpointtwelve.DirPos;
import net.minecraft.tileentity.TileEntity;
/**
* IFluidConductorMK2 with added node creation method
* @author hbm
*/
public interface IFluidPipeMK2 extends IFluidConnectorMK2 {
public default FluidNode createNode(FluidType type) {
TileEntity tile = (TileEntity) this;
return new FluidNode(type.getNetworkProvider(), new BlockPos(tile.xCoord, tile.yCoord, tile.zCoord)).setConnections(
new DirPos(tile.xCoord + 1, tile.yCoord, tile.zCoord, Library.POS_X),
new DirPos(tile.xCoord - 1, tile.yCoord, tile.zCoord, Library.NEG_X),
new DirPos(tile.xCoord, tile.yCoord + 1, tile.zCoord, Library.POS_Y),
new DirPos(tile.xCoord, tile.yCoord - 1, tile.zCoord, Library.NEG_Y),
new DirPos(tile.xCoord, tile.yCoord, tile.zCoord + 1, Library.POS_Z),
new DirPos(tile.xCoord, tile.yCoord, tile.zCoord - 1, Library.NEG_Z)
);
}
}

View File

@ -1,12 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.FluidType;
public interface IFluidProviderMK2 extends IFluidUserMK2 {
public void useUpFluid(FluidType type, int pressure, long amount);
public default long getProviderSpeed(FluidType type, int pressure) { return 1_000_000_000; }
public long getFluidAvailable(FluidType type, int pressure);
public default int[] getProvidingPressureRange(FluidType type) { return DEFAULT_PRESSURE_RANGE; }
}

View File

@ -1,63 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.packet.PacketDispatcher;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import com.hbm.uninos.GenNode;
import com.hbm.uninos.UniNodespace;
import com.hbm.util.fauxpointtwelve.DirPos;
import api.hbm.energymk2.IEnergyReceiverMK2.ConnectionPriority;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public interface IFluidReceiverMK2 extends IFluidUserMK2 {
/** Sends fluid of the desired type and pressure to the receiver, returns the remainder */
public long transferFluid(FluidType type, int pressure, long amount);
public default long getReceiverSpeed(FluidType type, int pressure) { return 1_000_000_000; }
public long getDemand(FluidType type, int pressure);
public default int[] getReceivingPressureRange(FluidType type) { return DEFAULT_PRESSURE_RANGE; }
public default void trySubscribe(FluidType type, World world, DirPos pos) { trySubscribe(type, world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void trySubscribe(FluidType type, World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = TileAccessCache.getTileOrCache(world, x, y, z);
boolean red = false;
if(te instanceof IFluidConnectorMK2) {
IFluidConnectorMK2 con = (IFluidConnectorMK2) te;
if(!con.canConnect(type, dir.getOpposite())) return;
GenNode node = UniNodespace.getNode(world, x, y, z, type.getNetworkProvider());
if(node != null && node.net != null) {
node.net.addReceiver(this);
red = true;
}
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "fluid");
data.setInteger("color", type.getColor());
double posX = x + 0.5 + dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 + dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 + dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", -dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", -dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", -dir.offsetZ * (red ? 0.025 : 0.1));
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public default ConnectionPriority getFluidPriority() {
return ConnectionPriority.NORMAL;
}
}

View File

@ -1,9 +0,0 @@
package api.hbm.fluidmk2;
public interface IFluidRegisterListener {
/**
* Called when the fluid registry initializes all fluids. Use CompatFluidRegistry to create new instances of FluidType, which are automatically registered.
*/
public void onFluidsLoad();
}

View File

@ -1,68 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.inventory.fluid.tank.FluidTank;
/**
* IFluidReceiverMK2 with standard implementation for transfer and demand getter.
* @author hbm
*/
public interface IFluidStandardReceiverMK2 extends IFluidReceiverMK2 {
public FluidTank[] getReceivingTanks();
@Override
public default long getDemand(FluidType type, int pressure) {
long amount = 0;
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) amount += (tank.getMaxFill() - tank.getFill());
}
return amount;
}
@Override
public default long transferFluid(FluidType type, int pressure, long amount) {
int tanks = 0;
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) tanks++;
}
if(tanks > 1) {
int firstRound = (int) Math.floor((double) amount / (double) tanks);
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
int toAdd = Math.min(firstRound, tank.getMaxFill() - tank.getFill());
tank.setFill(tank.getFill() + toAdd);
amount -= toAdd;
}
}
}
if(amount > 0) for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
int toAdd = (int) Math.min(amount, tank.getMaxFill() - tank.getFill());
tank.setFill(tank.getFill() + toAdd);
amount -= toAdd;
}
}
return amount;
}
@Override
public default int[] getReceivingPressureRange(FluidType type) {
int lowest = HIGHEST_VALID_PRESSURE;
int highest = 0;
for(FluidTank tank : getReceivingTanks()) {
if(tank.getTankType() == type) {
if(tank.getPressure() < lowest) lowest = tank.getPressure();
if(tank.getPressure() > highest) highest = tank.getPressure();
}
}
return lowest <= highest ? new int[] {lowest, highest} : DEFAULT_PRESSURE_RANGE;
}
@Override
public default long getReceiverSpeed(FluidType type, int pressure) {
return 1_000_000_000;
}
}

View File

@ -1,129 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.tank.FluidTank;
import com.hbm.inventory.fluid.FluidType;
import com.hbm.packet.PacketDispatcher;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import com.hbm.uninos.GenNode;
import com.hbm.uninos.UniNodespace;
import com.hbm.util.fauxpointtwelve.DirPos;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
/**
* IFluidProviderMK2 with standard implementation for fluid provision and fluid removal.
* @author hbm
*/
public interface IFluidStandardSenderMK2 extends IFluidProviderMK2 {
public default void tryProvide(FluidTank tank, World world, DirPos pos) { tryProvide(tank.getTankType(), tank.getPressure(), world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void tryProvide(FluidType type, World world, DirPos pos) { tryProvide(type, 0, world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void tryProvide(FluidType type, int pressure, World world, DirPos pos) { tryProvide(type, pressure, world, pos.getX(), pos.getY(), pos.getZ(), pos.getDir()); }
public default void tryProvide(FluidTank tank, World world, int x, int y, int z, ForgeDirection dir) { tryProvide(tank.getTankType(), tank.getPressure(), world, x, y, z, dir); }
public default void tryProvide(FluidType type, World world, int x, int y, int z, ForgeDirection dir) { tryProvide(type, 0, world, x, y, z, dir); }
public default void tryProvide(FluidType type, int pressure, World world, int x, int y, int z, ForgeDirection dir) {
TileEntity te = TileAccessCache.getTileOrCache(world, x, y, z);
boolean red = false;
if(te instanceof IFluidConnectorMK2) {
IFluidConnectorMK2 con = (IFluidConnectorMK2) te;
if(con.canConnect(type, dir.getOpposite())) {
GenNode<FluidNetMK2> node = UniNodespace.getNode(world, x, y, z, type.getNetworkProvider());
if(node != null && node.net != null) {
node.net.addProvider(this);
red = true;
}
}
}
if(te != this && te instanceof IFluidReceiverMK2) {
IFluidReceiverMK2 rec = (IFluidReceiverMK2) te;
if(rec.canConnect(type, dir.getOpposite())) {
long provides = Math.min(this.getFluidAvailable(type, pressure), this.getProviderSpeed(type, pressure));
long receives = Math.min(rec.getDemand(type, pressure), rec.getReceiverSpeed(type, pressure));
long toTransfer = Math.min(provides, receives);
toTransfer -= rec.transferFluid(type, pressure, toTransfer);
this.useUpFluid(type, pressure, toTransfer);
}
}
if(particleDebug) {
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "network");
data.setString("mode", "fluid");
data.setInteger("color", type.getColor());
double posX = x + 0.5 - dir.offsetX * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posY = y + 0.5 - dir.offsetY * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
double posZ = z + 0.5 - dir.offsetZ * 0.5 + world.rand.nextDouble() * 0.5 - 0.25;
data.setDouble("mX", dir.offsetX * (red ? 0.025 : 0.1));
data.setDouble("mY", dir.offsetY * (red ? 0.025 : 0.1));
data.setDouble("mZ", dir.offsetZ * (red ? 0.025 : 0.1));
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, posX, posY, posZ), new TargetPoint(world.provider.dimensionId, posX, posY, posZ, 25));
}
}
public FluidTank[] getSendingTanks();
@Override
public default long getFluidAvailable(FluidType type, int pressure) {
long amount = 0;
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) amount += tank.getFill();
}
return amount;
}
@Override
public default void useUpFluid(FluidType type, int pressure, long amount) {
int tanks = 0;
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) tanks++;
}
if(tanks > 1) {
int firstRound = (int) Math.floor((double) amount / (double) tanks);
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
int toRem = Math.min(firstRound, tank.getFill());
tank.setFill(tank.getFill() - toRem);
amount -= toRem;
}
}
}
if(amount > 0) for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type && tank.getPressure() == pressure) {
int toRem = (int) Math.min(amount, tank.getFill());
tank.setFill(tank.getFill() - toRem);
amount -= toRem;
}
}
}
@Override
public default int[] getProvidingPressureRange(FluidType type) {
int lowest = HIGHEST_VALID_PRESSURE;
int highest = 0;
for(FluidTank tank : getSendingTanks()) {
if(tank.getTankType() == type) {
if(tank.getPressure() < lowest) lowest = tank.getPressure();
if(tank.getPressure() > highest) highest = tank.getPressure();
}
}
return lowest <= highest ? new int[] {lowest, highest} : DEFAULT_PRESSURE_RANGE;
}
@Override
public default long getProviderSpeed(FluidType type, int pressure) {
return 1_000_000_000;
}
}

View File

@ -1,5 +0,0 @@
package api.hbm.fluidmk2;
public interface IFluidStandardTransceiverMK2 extends IFluidStandardReceiverMK2, IFluidStandardSenderMK2 {
}

View File

@ -1,15 +0,0 @@
package api.hbm.fluidmk2;
import com.hbm.inventory.fluid.tank.FluidTank;
import api.hbm.tile.ILoadedTile;
public interface IFluidUserMK2 extends IFluidConnectorMK2, ILoadedTile {
public static final int HIGHEST_VALID_PRESSURE = 5;
public static final int[] DEFAULT_PRESSURE_RANGE = new int[] {0, 0};
public static final boolean particleDebug = false;
public FluidTank[] getAllTanks();
}

View File

@ -1,24 +0,0 @@
package api.hbm.fluidmk2;
/*
It's rather shrimple: the shiny new energy system using universal nodespace, but hit with a hammer until it works with fluids.
Has a few extra bits and pieces for handling, but the concept is basically the same.
Sounds good?
*/
/*
Quick explanation for implementing new fluids via addon:
Fluids are subject to /ntmreload so they get wiped and rebuilt using the init function in Fluids, which means that if fluids
are simply added externally during startup, they are removed permanently until the game restarts. Same concept as with recipes, really.
To fix this we need to make sure that externally registered fluids are re-registered during reload, for that purpose we have
IFluidRegisterListener, a simple interface with a small method that runs whenever the fluid list is reloaded. IFluidRegisterListeners
need to be registered with CompatExternal.registerFluidRegisterListener to be used, make sure to do this during PreInit.
Inside the IFluidRegisterListener, fluids can be added using CompatFluidRegistry.registerFluid, which will generate a Fluid instance
using the supplied arguments and automatically register it. Do note that like with custom fluids, fluids need numeric IDs assigned manually.
To prevent collisions with stock fluids when NTM updates, make sure to choose a high starting ID (e.g. 10,000).
The fluid created by registerFluid can have traits added to them, just like how NTM does it with its stock fluids.
*/

View File

@ -0,0 +1,17 @@
package api.hbm.item;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
public interface IButtonReceiver {
/**
* Called in ModEventHandlerClient for any keyboard input related to this item
* @param stack
* @param player
*/
@SideOnly(Side.CLIENT)
public void handleKeyboardInput(ItemStack stack, EntityPlayer player);
}

View File

@ -0,0 +1,20 @@
package api.hbm.item;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
public interface IClickReceiver {
/**
* Called in ModEventHandlerClient for any mouse input related to this item
* @param stack
* @param player
* @param button
* @param state
* @return true if the event should be canceled
*/
@SideOnly(Side.CLIENT)
public boolean handleMouseInput(ItemStack stack, EntityPlayer player, int button, boolean state);
}

View File

@ -1,13 +0,0 @@
package api.hbm.recipe;
public interface IRecipeRegisterListener {
/**
* Called during SerializableRecipe.initialize(), after the defaults are loaded but before the template is written.
* Due to the way the recipes are handled, calling it once is not enough, it has to be called once for every SerializableRecipe
* instance handled, therefore the load operation passes the type name of the recipe, so that the listeners know what type of recipe
* to register at that point. Note that the actual SerializableRecipe instance is irrelevant, since recipes are static anyway,
* and direct tampering with SerializableRecipes is not recommended.
*/
public void onRecipeLoad(String recipeClassName);
}

View File

@ -1,17 +0,0 @@
package api.hbm.recipe;
/*
Quick guide on how to make robust and safe recipe integration:
* Implement IRecipeRegisterListener, the resulting class will handle all recipes, and the onRecipeLoad method is called every time the SerializableRecipe system updates
* Register your IRecipeRegisterListener using CompatExternal.registerRecipeRegisterListener, this has to happen before the SerializableRecipe initializes, doing this during PreInit should be safe
* In your IRecipeRegisterListener, check the supplied recipe type string (which will be the class name of the SerializableRecipe currently being registered) and register your custom recipes accordingly using CompatRecipeRegistry
Explanation:
* Order of operations is important for the recipes to work, if recipes are loaded outside the scope of SerializableRecipe.initialize, they will not work correctly
* If recipes are registered before the init, they are deleted, if they are registered after the init, they will not be part of the config template file, and get deleted when running /ntmreload
* Machines change all the time, so the recipe classes should not be considered API, since the compat would break immediately if a machine is changed or removed
* CompatRecipeRegistry promises to never change its method signatures, and have solid sanity checking when recipes are registered, allowing it to make the bst of whatever data is thrown at it
* Using this dedicated registry class means that even if a machine is changed or removed, the recipes will continue to work to the best of its abilities
*/

View File

@ -1,9 +0,0 @@
package api.hbm.redstoneoverradio;
public interface IRORInfo {
public static String PREFIX_VALUE = "VAL:";
public static String PREFIX_FUNCTION = "FUN:";
public String[] getFunctionInfo();
}

View File

@ -1,41 +0,0 @@
package api.hbm.redstoneoverradio;
public interface IRORInteractive extends IRORInfo {
public static String NAME_SEPARATOR = "!";
public static String PARAM_SEPARATOR = ":";
public static String EX_NULL = "Exception: Null Command";
public static String EX_NAME = "Exception: Multiple Name Separators";
public static String EX_FORMAT = "Exception: Parameter in Invalid Format";
/** Runs a function on the ROR component, usually causing the component to change or do something. Returns are optional. */
public String runRORFunction(String name, String[] params);
/** Extracts the command name from a full command string */
public static String getCommand(String input) {
if(input == null || input.isEmpty()) throw new RORFunctionException(EX_NULL);
String[] parts = input.split(NAME_SEPARATOR);
if(parts.length <= 0 || parts.length > 2) throw new RORFunctionException(EX_NAME);
if(parts[0].isEmpty()) throw new RORFunctionException(EX_NULL);
return parts[0];
}
/** Extracts the param list from a full command string */
public static String[] getParams(String input) {
if(input == null || input.isEmpty()) throw new RORFunctionException(EX_NULL);
String[] parts = input.split(NAME_SEPARATOR);
if(parts.length <= 0 || parts.length > 2) throw new RORFunctionException(EX_NAME);
if(parts.length == 1) return new String[0];
String paramList = parts[1];
String[] params = paramList.split(PARAM_SEPARATOR);
return params;
}
public static int parseInt(String val, int min, int max) {
int result = 0;
try { result = Integer.parseInt(val); } catch(Exception x) { throw new RORFunctionException(EX_FORMAT); };
if(result < min || result > max) throw new RORFunctionException(EX_FORMAT);
return result;
}
}

View File

@ -1,7 +0,0 @@
package api.hbm.redstoneoverradio;
public interface IRORValueProvider extends IRORInfo {
/** Grabs the specified value from this ROR component, operations should not cause any changes with the component itself */
public String provideRORValue(String name);
}

View File

@ -1,8 +0,0 @@
package api.hbm.redstoneoverradio;
public class RORFunctionException extends RuntimeException {
public RORFunctionException(String message) {
super(message);
}
}

View File

@ -1,49 +0,0 @@
/**
* @author hbm
*
*/
package api.hbm.redstoneoverradio;
/*
__ __ __ _________ ________ __ __ __ __ ______ __
/_/| /_/\ /_/| /________/\ /_______/| /_/| /_/| /_/|_____ /_/| /_____/| /_/|
| || | \\ | || | ___ \ \ | ______|/ | |\_| || | |/_____| || |___ || | ||
| || | \ \\ | || | || \ \/ | ||___ | \/_/ |/ | ______ || /__| || | ||__
| || | |\ \\| || | || \ || | |/__/| \ // | |/_____| || | ___|/ | |/_/|
| || | ||\ \| || | || | || | ____|/ > </\ |____ ____|/_ | |/__/| | __|/
| || | || \ | || | ||___/ |/ | ||_____ / __ \/| /_____| |______/| |______|/ | ||
| || | || \ || | |/__/ / | |/____/| | /| \ || |________________|/ | ||
|__|/ |__|/ \__|/ |_________/ |________|/ |__|/ |__|/ |__|/
(not AN index, INDEX is just the codename)
(also no i did not use an ASCII font generator i spent like half an hour on this)
INDEX includes Redstone-over-Radio APIs for interacting with ROR torches in ways more complex than simple comparator output,
simply put, certain ROR torches may run functions on the ROR component or read more complex values. This means that with the ROR
system alone, one can make complex monitoring and logic systems controlling machines via redstone automation.
INDEX includes:
- IRORInfo, an interface that provides a list of all valid functions. This interface should never be implemented directly because
it is worthless on its own, rather it is extended by all other ROR API interfaces
- IRORValueProvider, a simple interface that returns values based on names, serving as a simple getter. Get operations should never
cause changes within the ROR component, and should be kept simple
- IRORInteractive, an interface providing functions equivalent to java, usually performing a state change within the component and
optionally returning a value
On the implementation side we can expect:
- ROR readers, torches which have a list of named values which are read, as well as frequencies on which these values are broadcasted
- ROR controllers, torches which have one frequency and can receive commands with parameters which will be executed on the component
- ROR programmers, torches which have a list of frequencies and return frequencies which can receive commands with parameters and
then send the return value on the return frequency
- ROR logic receivers, torches which can turn signals into redstone based on various factors like arithmetic comparison and string
operators like matches, matches not and substring (thanks to vær for taking care of that)
ROR programmers can indeed do everything that the readers and controllers can, but their added complexity requires more GUI elements
which are more time-consuming to set up and limits the amount of command channels available, hence why readers and controllers exist
when only a simple solution is required
Addendum: While the RTTY system can support any arbitrary object as a signal, INDEX will strictly use strings, since that simplifies
things regarding serialization and saving signals to NBT. Counters already use a parse to int32 function, so this still checks out.
*/

View File

@ -1,55 +0,0 @@
package api.hbm.tile;
import java.util.HashMap;
import java.util.Map;
import com.hbm.util.Compat;
import com.hbm.util.Tuple.Quartet;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
/** For anything that should be removed off networks when considered unloaded, only affects providers and receivers, not links. Must not necessarily be a tile. */
public interface ILoadedTile {
public boolean isLoaded();
// should we gunk this into the API? no, but i don't care
public static class TileAccessCache {
public static Map<Quartet, TileAccessCache> cache = new HashMap();
public static int NULL_CACHE = 20;
public static int NONNULL_CACHE = 60;
public TileEntity tile;
public long expiresOn;
public TileAccessCache(TileEntity tile, long expiresOn) {
this.tile = tile;
this.expiresOn = expiresOn;
}
public boolean hasExpired(long worldTime) {
if(tile != null && tile.isInvalid()) return true;
if(worldTime >= expiresOn) return true;
if(tile instanceof ILoadedTile && !((ILoadedTile) tile).isLoaded()) return true;
return false;
}
public static Quartet publicCumRag = new Quartet(0, 0, 0, 0);
public static TileEntity getTileOrCache(World world, int x, int y, int z) {
publicCumRag.mangle(x, y, z, world.provider.dimensionId);
TileAccessCache cache = TileAccessCache.cache.get(publicCumRag);
if(cache == null || cache.hasExpired(world.getTotalWorldTime())) {
TileEntity tile = Compat.getTileStandard(world, x, y, z);
cache = new TileAccessCache(tile, world.getTotalWorldTime() + (tile == null ? NULL_CACHE : NONNULL_CACHE));
TileAccessCache.cache.put(publicCumRag.clone(), cache);
return tile;
} else {
return cache.tile;
}
}
}
}

View File

@ -1,18 +1,17 @@
package com.hbm.blocks;
import com.hbm.lib.RefStrings;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EnumCreatureType;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.item.ItemStack;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
public class BlockBase extends Block {
private boolean beaconable = false;
private boolean canSpawn = true;
public BlockBase() {
super(Material.rock);
@ -21,14 +20,14 @@ public class BlockBase extends Block {
public BlockBase(Material material) {
super(material);
}
@Override
public Block setBlockName(String name) {
super.setBlockName(name);
this.setBlockTextureName(RefStrings.MODID + ":" + name);
return this;
}
/**
* Daisychainable setter for making the block a beacon base block
* @return
@ -38,21 +37,11 @@ public class BlockBase extends Block {
return this;
}
public BlockBase noMobSpawn() {
this.canSpawn = false;
return this;
}
@Override
public boolean canCreatureSpawn(EnumCreatureType type, IBlockAccess world, int x, int y, int z) {
return this.canSpawn ? super.canCreatureSpawn(type, world, x, y, z) : false;
}
@Override
public boolean isBeaconBase(IBlockAccess worldObj, int x, int y, int z, int beaconX, int beaconY, int beaconZ) {
return this.beaconable;
}
/**
* Sets the block to air and drops it
* @param world
@ -61,7 +50,7 @@ public class BlockBase extends Block {
* @param z
*/
public void dismantle(World world, int x, int y, int z) {
world.setBlockToAir(x, y, z);
ItemStack itemstack = new ItemStack(this, 1);

View File

@ -1,11 +1,13 @@
package com.hbm.blocks;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.hbm.handler.MultiblockHandlerXR;
import com.hbm.handler.ThreeInts;
import com.hbm.interfaces.ICopiable;
import com.hbm.main.MainRegistry;
import com.hbm.tileentity.IPersistentNBT;
import com.hbm.world.gen.nbt.INBTBlockTransformable;
import cpw.mods.fml.common.network.internal.FMLNetworkHandler;
import cpw.mods.fml.relauncher.Side;
@ -13,7 +15,6 @@ import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.RenderGlobal;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityItem;
@ -26,18 +27,12 @@ import net.minecraft.stats.StatList;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.MathHelper;
import net.minecraft.util.MovingObjectPosition;
import net.minecraft.util.Vec3;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import net.minecraftforge.common.util.ForgeDirection;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight, ICopiable, INBTBlockTransformable {
public abstract class BlockDummyable extends BlockContainer implements ICustomBlockHighlight {
public BlockDummyable(Material mat) {
super(mat);
@ -54,7 +49,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
public static final int offset = 10;
// meta offset from dummy to extra rotation
public static final int extra = 6;
/*
* An extra integer that can be set before block set operations (such as makeExtra) and intercepted in createNewTileEntity.
* This way we can inelegantly add variation to the tiles created even if the metadata would be the same.
@ -64,11 +59,11 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
public static int overrideTileMeta = 0;
public static boolean safeRem = false;
public static void setOverride(int i) {
overrideTileMeta = i;
}
public static void resetOverride() {
overrideTileMeta = 0;
}
@ -77,20 +72,27 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
super.onNeighborBlockChange(world, x, y, z, block);
if(safeRem)
if(world.isRemote || safeRem)
return;
destroyIfOrphan(world, x, y, z);
int metadata = world.getBlockMetadata(x, y, z);
// if it's an extra, remove the extra-ness
if(metadata >= extra)
metadata -= extra;
ForgeDirection dir = ForgeDirection.getOrientation(metadata).getOpposite();
Block b = world.getBlock(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ);
if(b != this) {
world.setBlockToAir(x, y, z);
}
}
public void updateTick(World world, int x, int y, int z, Random rand) {
super.updateTick(world, x, y, z, rand);
destroyIfOrphan(world, x, y, z);
}
private void destroyIfOrphan(World world, int x, int y, int z) {
if(world.isRemote)
return;
@ -103,32 +105,10 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
ForgeDirection dir = ForgeDirection.getOrientation(metadata).getOpposite();
Block b = world.getBlock(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ);
// An extra precaution against multiblocks on chunk borders being erroneously deleted.
// Technically, this might be used to persist ghost dummy blocks by manipulating
// loaded chunks and block destruction, but this gives no benefit to the player,
// cannot be done accidentally, and is definitely preferable to multiblocks
// just vanishing when their chunks are unloaded in an unlucky way.
if(b != this && world.checkChunksExist(x - 1, y - 1, z - 1, x + 1, y + 1, z + 1)) {
if (isLegacyMonoblock(world, x, y, z)) {
fixLegacyMonoblock(world, x, y, z);
} else {
world.setBlockToAir(x, y, z);
}
if(b != this) {
world.setBlockToAir(x, y, z);
}
}
// Override this when turning a single block into a pseudo-multiblock.
// If this returns true, instead of being deleted as an orphan, the block
// will be promoted to a core of a dummyable, however without any dummies.
// This is only called if the block is presumed an orphan, so you don't
// need to check that here.
protected boolean isLegacyMonoblock(World world, int x, int y, int z) {
return false;
}
protected void fixLegacyMonoblock(World world, int x, int y, int z) {
// Promote to a lone core block with the same effective rotation as before the change
world.setBlockMetadataWithNotify(x, y, z, offset + world.getBlockMetadata(x, y, z), 3);
}
public int[] findCore(World world, int x, int y, int z) {
@ -136,7 +116,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
return findCoreRec(world, x, y, z);
}
List<ThreeInts> positions = new ArrayList<>();
List<ThreeInts> positions = new ArrayList();
public int[] findCoreRec(World world, int x, int y, int z) {
@ -198,7 +178,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
if(i == 3) {
dir = ForgeDirection.getOrientation(4);
}
dir = getDirModified(dir);
if(!checkRequirement(world, x, y, z, dir, o)) {
@ -236,6 +216,11 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
super.onBlockPlacedBy(world, x, y, z, player, itemStack);
}
/*@Override
public void onBlockAdded(World world, int x, int y, int z) {
lastBlockSet = new BlockPos(x, y, z);
}*/
/**
* A bit more advanced than the dir modifier, but it is important that the resulting direction meta is in the core range.
* Using the "extra" metas is technically possible but requires a bit of tinkering, e.g. preventing a recursive loop
@ -251,7 +236,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
protected int getMetaForCore(World world, int x, int y, int z, EntityPlayer player, int original) {
return original;
}
/**
* Allows to modify the general placement direction as if the player had another rotation.
* Quite basic due to only having 1 param but it's more meant to fix/limit the amount of directions
@ -282,11 +267,11 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
return;
// world.setBlockMetadataWithNotify(x, y, z, meta + extra, 3);
safeRem = true;
this.safeRem = true;
world.setBlock(x, y, z, this, meta + extra, 3);
safeRem = false;
this.safeRem = false;
}
public void removeExtra(World world, int x, int y, int z) {
if(world.getBlock(x, y, z) != this)
@ -298,9 +283,9 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
return;
// world.setBlockMetadataWithNotify(x, y, z, meta + extra, 3);
safeRem = true;
this.safeRem = true;
world.setBlock(x, y, z, this, meta - extra, 3);
safeRem = false;
this.safeRem = false;
}
// checks if the dummy metadata is within the extra range
@ -324,7 +309,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
// if(pos != null) {
ForgeDirection d = ForgeDirection.getOrientation(i);
if(world.getBlock(x - d.offsetX, y - d.offsetY, z - d.offsetZ) == this)
world.setBlockToAir(x - d.offsetX, y - d.offsetY, z - d.offsetZ);
// }
@ -399,7 +384,7 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
}
protected boolean standardOpenBehavior(World world, int x, int y, int z, EntityPlayer player, int id) {
if(world.isRemote) {
return true;
} else if(!player.isSneaking()) {
@ -417,14 +402,14 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
@Override
public void onBlockHarvested(World world, int x, int y, int z, int meta, EntityPlayer player) {
if(!player.capabilities.isCreativeMode) {
harvesters.set(player);
this.dropBlockAsItem(world, x, y, z, meta, 0);
harvesters.set(null);
}
}
/*
* Called after the block and TE are already gone, so this method is of no use to us.
*/
@ -433,85 +418,56 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
player.addStat(StatList.mineBlockStatArray[getIdFromBlock(this)], 1);
player.addExhaustion(0.025F);
}
public boolean useDetailedHitbox() {
return !bounding.isEmpty();
}
public List<AxisAlignedBB> bounding = new ArrayList();
public List<AxisAlignedBB> bounding = new ArrayList<>();
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public void addCollisionBoxesToList(World world, int x, int y, int z, AxisAlignedBB entityBounding, List list, Entity entity) {
if(!this.useDetailedHitbox()) {
super.addCollisionBoxesToList(world, x, y, z, entityBounding, list, entity);
return;
}
int[] pos = this.findCore(world, x, y, z);
if(pos == null)
return;
x = pos[0];
y = pos[1];
z = pos[2];
ForgeDirection rot = ForgeDirection.getOrientation(world.getBlockMetadata(x, y, z) - offset).getRotation(ForgeDirection.UP);
for(AxisAlignedBB aabb : this.bounding) {
AxisAlignedBB boxlet = getAABBRotationOffset(aabb, x + 0.5, y, z + 0.5, rot);
for(AxisAlignedBB aabb :this.bounding) {
AxisAlignedBB boxlet = getAABBRotationOffset(aabb, x + 0.5, y, z + 0.5, ForgeDirection.getOrientation(world.getBlockMetadata(x, y, z) - this.offset).getRotation(ForgeDirection.UP));
if(entityBounding.intersectsWith(boxlet)) {
list.add(boxlet);
}
}
}
public static AxisAlignedBB getAABBRotationOffset(AxisAlignedBB aabb, double x, double y, double z, ForgeDirection dir) {
AxisAlignedBB newBox = null;
if(dir == ForgeDirection.NORTH) newBox = AxisAlignedBB.getBoundingBox(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ);
if(dir == ForgeDirection.EAST) newBox = AxisAlignedBB.getBoundingBox(-aabb.maxZ, aabb.minY, aabb.minX, -aabb.minZ, aabb.maxY, aabb.maxX);
if(dir == ForgeDirection.SOUTH) newBox = AxisAlignedBB.getBoundingBox(-aabb.maxX, aabb.minY, -aabb.maxZ, -aabb.minX, aabb.maxY, -aabb.minZ);
if(dir == ForgeDirection.WEST) newBox = AxisAlignedBB.getBoundingBox(aabb.minZ, aabb.minY, -aabb.maxX, aabb.maxZ, aabb.maxY, -aabb.minX);
if(newBox != null) {
newBox.offset(x, y, z);
return newBox;
}
return AxisAlignedBB.getBoundingBox(aabb.minX, aabb.minY, aabb.minZ, aabb.maxX, aabb.maxY, aabb.maxZ).offset(x + 0.5, y + 0.5, z + 0.5);
}
// Don't mutate the xyz parameters, or the interaction max distance will bite you
@Override
public MovingObjectPosition collisionRayTrace(World world, int x, int y, int z, Vec3 startVec, Vec3 endVec) {
if(!this.useDetailedHitbox()) {
return super.collisionRayTrace(world, x, y, z, startVec, endVec);
}
int[] pos = this.findCore(world, x, y, z);
if(pos == null)
return super.collisionRayTrace(world, x, y, z, startVec, endVec);
ForgeDirection rot = ForgeDirection.getOrientation(world.getBlockMetadata(pos[0], pos[1], pos[2]) - offset).getRotation(ForgeDirection.UP);
for(AxisAlignedBB aabb : this.bounding) {
AxisAlignedBB boxlet = getAABBRotationOffset(aabb, pos[0] + 0.5, pos[1], pos[2] + 0.5, rot);
MovingObjectPosition intercept = boxlet.calculateIntercept(startVec, endVec);
if(intercept != null) {
return new MovingObjectPosition(x, y, z, intercept.sideHit, intercept.hitVec);
}
}
return null;
}
@Override
public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) {
if(!this.useDetailedHitbox()) {
@ -520,86 +476,35 @@ public abstract class BlockDummyable extends BlockContainer implements ICustomBl
this.setBlockBounds(0.0F, 0.0F, 0.0F, 1.0F, 0.999F, 1.0F); //for some fucking reason setting maxY to something that isn't 1 magically fixes item collisions
}
}
@Override
@SideOnly(Side.CLIENT)
public boolean shouldDrawHighlight(World world, int x, int y, int z) {
return !this.bounding.isEmpty();
}
@Override
@SideOnly(Side.CLIENT)
public void drawHighlight(DrawBlockHighlightEvent event, World world, int x, int y, int z) {
int[] pos = this.findCore(world, x, y, z);
if(pos == null) return;
x = pos[0];
y = pos[1];
z = pos[2];
EntityPlayer player = event.player;
float interp = event.partialTicks;
double dX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) interp;
double dY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) interp;
double dZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double)interp;
float exp = 0.002F;
ForgeDirection rot = ForgeDirection.getOrientation(world.getBlockMetadata(x, y, z) - offset).getRotation(ForgeDirection.UP);
int meta = world.getBlockMetadata(x, y, z);
ICustomBlockHighlight.setup();
for(AxisAlignedBB aabb : this.bounding) RenderGlobal.drawOutlinedBoundingBox(getAABBRotationOffset(aabb.expand(exp, exp, exp), 0, 0, 0, rot).getOffsetBoundingBox(x - dX + 0.5, y - dY, z - dZ + 0.5), -1);
for(AxisAlignedBB aabb : this.bounding) event.context.drawOutlinedBoundingBox(getAABBRotationOffset(aabb.expand(exp, exp, exp), 0, 0, 0, ForgeDirection.getOrientation(meta - offset).getRotation(ForgeDirection.UP)).getOffsetBoundingBox(x - dX + 0.5, y - dY, z - dZ + 0.5), -1);
ICustomBlockHighlight.cleanup();
}
@Override
public NBTTagCompound getSettings(World world, int x, int y, int z) {
int[] pos = findCore(world, x, y, z);
TileEntity tile = world.getTileEntity(pos[0], pos[1], pos[2]);
if (tile instanceof ICopiable)
return ((ICopiable) tile).getSettings(world, pos[0], pos[1], pos[2]);
else
return null;
}
@Override
public void pasteSettings(NBTTagCompound nbt, int index, World world, EntityPlayer player, int x, int y, int z) {
int[] pos = findCore(world, x, y, z);
if(pos == null) return;
TileEntity tile = world.getTileEntity(pos[0], pos[1], pos[2]);
if (tile instanceof ICopiable)
((ICopiable) tile).pasteSettings(nbt, index, world, player, pos[0], pos[1], pos[2]);
}
@Override
public String[] infoForDisplay(World world, int x, int y, int z) {
int[] pos = findCore(world, x, y, z);
TileEntity tile = world.getTileEntity(pos[0], pos[1], pos[2]);
if (tile instanceof ICopiable)
return ((ICopiable) tile).infoForDisplay(world, x, y, z);
return null;
}
@Override
public int transformMeta(int meta, int coordBaseMode) {
boolean isOffset = meta >= 12; // squishing causes issues
boolean isExtra = !isOffset && meta >= extra;
if(isOffset) {
meta -= offset;
} else if(isExtra) {
meta -= extra;
}
meta = INBTBlockTransformable.transformMetaDeco(meta, coordBaseMode);
if(isOffset) {
meta += offset;
} else if(isExtra) {
meta += extra;
}
return meta;
}
}
}

View File

@ -1,6 +1,9 @@
package com.hbm.blocks;
import java.util.Locale;
import com.hbm.util.EnumUtil;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.material.Material;
@ -8,8 +11,6 @@ import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import java.util.Locale;
public class BlockEnumMulti extends BlockMulti {
public Class<? extends Enum> theEnum;
@ -22,17 +23,17 @@ public class BlockEnumMulti extends BlockMulti {
this.multiName = multiName;
this.multiTexture = multiTexture;
}
protected IIcon[] icons;
@Override
@SideOnly(Side.CLIENT)
public void registerBlockIcons(IIconRegister reg) {
if(multiTexture) {
Enum[] enums = theEnum.getEnumConstants();
this.icons = new IIcon[enums.length];
for(int i = 0; i < icons.length; i++) {
Enum num = enums[i];
this.icons[i] = reg.registerIcon(this.getTextureMultiName(num));
@ -41,25 +42,25 @@ public class BlockEnumMulti extends BlockMulti {
this.blockIcon = reg.registerIcon(this.getTextureName());
}
}
public String getUnlocalizedName(ItemStack stack) {
if(this.multiName) {
Enum num = EnumUtil.grabEnumSafely(this.theEnum, stack.getItemDamage());
return getUnlocalizedMultiName(num);
}
return this.getUnlocalizedName();
}
public String getTextureMultiName(Enum num) {
return this.getTextureName() + "." + num.name().toLowerCase(Locale.US);
}
public String getUnlocalizedMultiName(Enum num) {
return super.getUnlocalizedName() + "." + num.name().toLowerCase(Locale.US);
}
@Override
@SideOnly(Side.CLIENT)
public IIcon getIcon(int side, int meta) {

View File

@ -11,14 +11,6 @@ public class BlockEnums {
BAUXITE
}
public static enum EnumMeteorType {
IRON,
COPPER,
ALUMINIUM,
RAREEARTH,
COBALT
}
public static enum EnumBiomeType {
DESERT,
WOODLAND
@ -58,14 +50,6 @@ public class BlockEnums {
SMALL
}
public static enum LightstoneType {
UNREFINED,
TILE,
BRICKS,
BRICKS_CHISELED,
CHISELED
}
public static enum DecoComputerEnum {
IBM_300PL
}
@ -80,5 +64,4 @@ public class BlockEnums {
FLUORESCENT,
HALOGEN
}
}

View File

@ -1,6 +1,9 @@
package com.hbm.blocks;
import java.util.Random;
import com.hbm.entity.item.EntityFallingBlockNT;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
@ -11,8 +14,6 @@ import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.init.Blocks;
import net.minecraft.world.World;
import java.util.Random;
public class BlockFallingNT extends Block {
public static boolean fallInstantly;
@ -44,7 +45,7 @@ public class BlockFallingNT extends Block {
}
protected void fall(World world, int x, int y, int z) {
if(canFallThrough(world, x, y - 1, z) && y >= 0) {
byte range = 32;

View File

@ -1,5 +1,7 @@
package com.hbm.blocks;
import java.util.List;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.material.Material;
@ -7,8 +9,6 @@ import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import java.util.List;
public abstract class BlockMulti extends BlockBase implements IBlockMulti {
public BlockMulti() {
@ -31,4 +31,8 @@ public abstract class BlockMulti extends BlockBase implements IBlockMulti {
list.add(new ItemStack(item, 1, i));
}
}
public String getUnlocalizedName(ItemStack stack) {
return this.getUnlocalizedName();
}
}

View File

@ -1,5 +1,8 @@
package com.hbm.blocks;
import java.util.ArrayList;
import java.util.Random;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
@ -9,11 +12,8 @@ import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderGameOverlayEvent.Pre;
import java.util.ArrayList;
import java.util.Random;
public class BlockRemap extends Block implements ILookOverlay {
public Block remapBlock;
public int remapMeta;
@ -29,7 +29,7 @@ public class BlockRemap extends Block implements ILookOverlay {
public IIcon getIcon(int meta, int side) {
return this.remapBlock.getIcon(meta, side);
}
@Override
public Item getItemDropped(int meta, Random rand, int fortune) {
return this.remapBlock.getItemDropped(meta, rand, fortune);

View File

@ -1,9 +1,9 @@
package com.hbm.blocks;
import net.minecraft.world.World;
import java.util.List;
import net.minecraft.world.World;
public interface IAnalyzable {
public List<String> getDebugInfo(World world, int x, int y, int z);

View File

@ -1,20 +1,9 @@
package com.hbm.blocks;
import net.minecraft.block.Block;
import net.minecraft.item.ItemStack;
public interface IBlockMulti {
public int getSubCount();
public default String getUnlocalizedName(ItemStack stack) {
return ((Block)this).getUnlocalizedName();
}
public default String getOverrideDisplayName(ItemStack stack) {
return null;
}
public default int rectify(int meta) {
return Math.abs(meta % getSubCount());
}

View File

@ -11,27 +11,4 @@ public interface IBlockSideRotation {
public static int getRenderType() {
return renderID;
}
// 0 1 3 2 becomes 0 2 3 1
// I want to smoke that swedish kush because it clearly makes you fucking stupid
public static int topToBottom(int topRotation) {
switch(topRotation) {
case 1: return 2;
case 2: return 1;
default: return topRotation;
}
}
public static boolean isOpposite(int from, int to) {
switch(from) {
case 0: return to == 1;
case 1: return to == 0;
case 2: return to == 3;
case 3: return to == 2;
case 4: return to == 5;
case 5: return to == 4;
default: return false;
}
}
}

View File

@ -1,17 +1,18 @@
package com.hbm.blocks;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.world.World;
import net.minecraftforge.client.event.DrawBlockHighlightEvent;
import org.lwjgl.opengl.GL11;
public interface ICustomBlockHighlight {
@SideOnly(Side.CLIENT) public boolean shouldDrawHighlight(World world, int x, int y, int z);
@SideOnly(Side.CLIENT) public void drawHighlight(DrawBlockHighlightEvent event, World world, int x, int y, int z);
@SideOnly(Side.CLIENT)
public static void setup() {
GL11.glEnable(GL11.GL_BLEND);
@ -21,7 +22,7 @@ public interface ICustomBlockHighlight {
GL11.glDisable(GL11.GL_TEXTURE_2D);
GL11.glDepthMask(false);
}
@SideOnly(Side.CLIENT)
public static void cleanup() {
GL11.glDepthMask(true);

View File

@ -1,5 +1,9 @@
package com.hbm.blocks;
import java.util.List;
import org.lwjgl.opengl.GL11;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
@ -7,9 +11,6 @@ import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.ScaledResolution;
import net.minecraft.world.World;
import net.minecraftforge.client.event.RenderGameOverlayEvent;
import org.lwjgl.opengl.GL11;
import java.util.List;
public interface ILookOverlay {
@ -32,14 +33,14 @@ public interface ILookOverlay {
try {
for(String line : text) {
int color = 0xFFFFFF;
if(line.startsWith("&[")) {
int end = line.lastIndexOf("&]");
color = Integer.parseInt(line.substring(2, end));
line = line.substring(end + 2);
}
mc.fontRenderer.drawStringWithShadow(line, pX, pZ, color);
pZ += 10;
}

View File

@ -1,11 +1,11 @@
package com.hbm.blocks;
import java.util.List;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import java.util.List;
public interface IPersistentInfoProvider {
public void addInformation(ItemStack stack, NBTTagCompound persistentTag, EntityPlayer player, List list, boolean ext);

View File

@ -1,22 +1,23 @@
package com.hbm.blocks;
import java.util.List;
import org.lwjgl.input.Keyboard;
import com.hbm.util.I18nUtil;
import net.minecraft.block.Block;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumRarity;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumChatFormatting;
import org.lwjgl.input.Keyboard;
import com.hbm.util.i18n.I18nUtil;
import java.util.List;
public interface ITooltipProvider {
public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean ext);
public default void addStandardInfo(ItemStack stack, EntityPlayer player, List list, boolean ext) {
if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)) {
for(String s : I18nUtil.resolveKeyArray(((Block)this).getUnlocalizedName() + ".desc")) list.add(EnumChatFormatting.YELLOW + s);
} else {
@ -25,7 +26,7 @@ public interface ITooltipProvider {
EnumChatFormatting.DARK_GRAY + "" + EnumChatFormatting.ITALIC + "> to display more info");
}
}
public default EnumRarity getRarity(ItemStack stack) {
return EnumRarity.common;
}

File diff suppressed because it is too large Load Diff

View File

@ -7,10 +7,8 @@ import static net.minecraftforge.common.util.ForgeDirection.SOUTH;
import static net.minecraftforge.common.util.ForgeDirection.UP;
import static net.minecraftforge.common.util.ForgeDirection.WEST;
import java.awt.Color;
import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.potion.HbmPotion;
import cpw.mods.fml.relauncher.Side;
@ -49,9 +47,9 @@ public class Balefire extends BlockFire {
return icon;
}
@Override
public void updateTick(World world, int x, int y, int z, Random rand) {
if(world.getGameRules().getGameRuleBooleanValue("doFireTick")) {
boolean onNetherrack = world.getBlock(x, y - 1, z).isFireSource(world, x, y - 1, z, UP);
if(!this.canPlaceBlockAt(world, x, y, z)) {
world.setBlockToAir(x, y, z);
@ -59,10 +57,12 @@ public class Balefire extends BlockFire {
int meta = world.getBlockMetadata(x, y, z);
if(meta < 15) world.scheduleBlockUpdate(x, y, z, this, this.tickRate(world) + rand.nextInt(10));
world.scheduleBlockUpdate(x, y, z, this, this.tickRate(world) + rand.nextInt(10));
if(!this.canNeighborBurn(world, x, y, z) && !World.doesBlockHaveSolidTopSurface(world, x, y - 1, z)) {
world.setBlockToAir(x, y, z);
if(!onNetherrack && !this.canNeighborBurn(world, x, y, z)) {
if(!World.doesBlockHaveSolidTopSurface(world, x, y - 1, z)) {
world.setBlockToAir(x, y, z);
}
} else {
if(meta < 15) {
this.tryCatchFire(world, x + 1, y, z, 500, rand, meta, WEST);
@ -71,33 +71,31 @@ public class Balefire extends BlockFire {
this.tryCatchFire(world, x, y + 1, z, 300, rand, meta, DOWN);
this.tryCatchFire(world, x, y, z - 1, 500, rand, meta, SOUTH);
this.tryCatchFire(world, x, y, z + 1, 500, rand, meta, NORTH);
int h = 3;
}
for(int ix = x - h; ix <= x + h; ++ix) {
for(int iz = z - h; iz <= z + h; ++iz) {
for(int iy = y - 1; iy <= y + 4; ++iy) {
if(ix != x || iy != y || iz != z) {
int fireLimit = 100;
for(int i1 = x - 1; i1 <= x + 1; ++i1) {
for(int j1 = z - 1; j1 <= z + 1; ++j1) {
for(int k1 = y - 1; k1 <= y + 4; ++k1) {
if(i1 != x || k1 != y || j1 != z) {
int l1 = 100;
if(iy > y + 1) {
fireLimit += (iy - (y + 1)) * 100;
}
if(world.getBlock(ix, iy, iz) == ModBlocks.balefire && world.getBlockMetadata(ix, iy, iz) > meta + 1) {
world.setBlock(ix, iy, iz, this, meta + 1, 3);
continue;
}
if(k1 > y + 1) {
l1 += (k1 - (y + 1)) * 100;
}
int neighborFireChance = this.getChanceOfNeighborsEncouragingFire(world, ix, iy, iz);
int i2 = this.getChanceOfNeighborsEncouragingFire(world, i1, k1, j1);
if(neighborFireChance > 0) {
int adjustedFireChance = (neighborFireChance + 40 + world.difficultySetting.getDifficultyId() * 7) / (meta + 30);
if(i2 > 0) {
int j2 = (i2 + 40 + world.difficultySetting.getDifficultyId() * 7) / (meta + 30);
if(adjustedFireChance > 0 && rand.nextInt(fireLimit) <= adjustedFireChance) {
world.setBlock(ix, iy, iz, this, meta + 1, 3);
if(j2 > 0 && rand.nextInt(l1) <= j2) {
int k2 = meta + rand.nextInt(5) / 4;
if(k2 > 15) {
k2 = 15;
}
world.setBlock(i1, k1, j1, this, k2, 3);
}
}
}
@ -158,15 +156,5 @@ public class Balefire extends BlockFire {
if(entity instanceof EntityLivingBase) ((EntityLivingBase) entity).addPotionEffect(new PotionEffect(HbmPotion.radiation.id, 5 * 20, 9));
}
@SideOnly(Side.CLIENT)
public int colorMultiplier(IBlockAccess world, int x, int y, int z) {
int meta = world.getBlockMetadata(x, y, z);
return Color.HSBtoRGB(0F, 0F, 1F - meta / 30F);
}
@Override
public int getRenderType() {
return 1;
}
}

View File

@ -8,6 +8,6 @@ public class BlockC4 extends BlockTNTBase {
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
world.createExplosion(entity, x, y, z, 15F, true);
world.createExplosion(entity, x, y, z, 26F, true);
}
}

View File

@ -12,13 +12,10 @@ import java.util.Random;
import com.hbm.blocks.BlockContainerBase;
import com.hbm.blocks.ITooltipProvider;
import com.hbm.entity.item.EntityTNTPrimedBase;
import com.hbm.interfaces.IBomb;
import com.hbm.tileentity.bomb.TileEntityCharge;
import api.hbm.block.IFuckingExplode;
import api.hbm.block.IToolable;
import net.minecraft.util.MathHelper;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
@ -32,7 +29,7 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public abstract class BlockChargeBase extends BlockContainerBase implements IBomb, IToolable, ITooltipProvider, IFuckingExplode {
public abstract class BlockChargeBase extends BlockContainerBase implements IBomb, IToolable, ITooltipProvider {
public static boolean safe = false;
@ -137,18 +134,8 @@ public abstract class BlockChargeBase extends BlockContainerBase implements IBom
}
@Override
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion explosion) {
if(!world.isRemote) {
EntityTNTPrimedBase tntPrimed = new EntityTNTPrimedBase(world, x + 0.5D, y + 0.5D, z + 0.5D, explosion != null ? explosion.getExplosivePlacedBy() : null, this);
tntPrimed.fuse = 0;
tntPrimed.detonateOnCollision = false;
world.spawnEntityInWorld(tntPrimed);
}
}
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
explode(world, MathHelper.floor_double(x), MathHelper.floor_double(y), MathHelper.floor_double(z));
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion p_149723_5_) {
this.explode(world, x, y, z);
}
@Override

View File

@ -5,9 +5,6 @@ import java.util.List;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.BlockAllocatorStandard;
import com.hbm.explosion.vanillant.standard.BlockProcessorStandard;
import com.hbm.explosion.vanillant.standard.EntityProcessorStandard;
import com.hbm.explosion.vanillant.standard.PlayerProcessorStandard;
import com.hbm.particle.helper.ExplosionCreator;
import cpw.mods.fml.client.registry.RenderingRegistry;
import net.minecraft.entity.player.EntityPlayer;
@ -25,13 +22,10 @@ public class BlockChargeC4 extends BlockChargeBase {
world.setBlockToAir(x, y, z);
safe = false;
ExplosionVNT xnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 15F);
ExplosionVNT xnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 15F).makeStandard();
xnt.setBlockAllocator(new BlockAllocatorStandard(32));
xnt.setBlockProcessor(new BlockProcessorStandard().setNoDrop());
xnt.setEntityProcessor(new EntityProcessorStandard());
xnt.setPlayerProcessor(new PlayerProcessorStandard());
xnt.explode();
ExplosionCreator.composeEffectSmall(world, x + 0.5, y + 1, z + 0.5);
return BombReturnCode.DETONATED;
}

View File

@ -1,7 +1,7 @@
package com.hbm.blocks.bomb;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.ExplosionNT;
import com.hbm.particle.helper.ExplosionSmallCreator;
import cpw.mods.fml.client.registry.RenderingRegistry;
import net.minecraft.world.World;
@ -17,7 +17,7 @@ public class BlockChargeDynamite extends BlockChargeBase {
safe = false;
ExplosionNT exp = new ExplosionNT(world, null, x + 0.5, y + 0.5, z + 0.5, 4F);
exp.explode();
ExplosionSmallCreator.composeEffect(world, x + 0.5, y + 0.5, z + 0.5, 15, 3F, 1.25F);
ExplosionLarge.spawnParticles(world, x + 0.5, y + 0.5, z + 0.5, 20);
return BombReturnCode.DETONATED;
}

View File

@ -2,9 +2,9 @@ package com.hbm.blocks.bomb;
import java.util.List;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.ExplosionNT;
import com.hbm.explosion.ExplosionNT.ExAttrib;
import com.hbm.particle.helper.ExplosionSmallCreator;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@ -23,7 +23,7 @@ public class BlockChargeMiner extends BlockChargeBase {
ExplosionNT exp = new ExplosionNT(world, null, x + 0.5, y + 0.5, z + 0.5, 4F);
exp.addAllAttrib(ExAttrib.NOHURT, ExAttrib.ALLDROP);
exp.explode();
ExplosionSmallCreator.composeEffect(world, x + 0.5, y + 0.5, z + 0.5, 15, 3F, 1.25F);
ExplosionLarge.spawnParticles(world, x + 0.5, y + 0.5, z + 0.5, 20);
return BombReturnCode.DETONATED;
}

View File

@ -5,7 +5,7 @@ import java.util.List;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.BlockAllocatorStandard;
import com.hbm.explosion.vanillant.standard.BlockProcessorStandard;
import com.hbm.particle.helper.ExplosionCreator;
import com.hbm.explosion.vanillant.standard.ExplosionEffectStandard;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
@ -27,8 +27,8 @@ public class BlockChargeSemtex extends BlockChargeBase {
xnt.setBlockProcessor(new BlockProcessorStandard()
.setAllDrop()
.setFortune(3));
xnt.setSFX(new ExplosionEffectStandard());
xnt.explode();
ExplosionCreator.composeEffectSmall(world, x + 0.5, y + 1, z + 0.5);
return BombReturnCode.DETONATED;
}

View File

@ -1,77 +1,91 @@
package com.hbm.blocks.bomb;
import com.hbm.blocks.BlockEnumMulti;
import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.config.BombConfig;
import com.hbm.entity.logic.EntityBalefire;
import com.hbm.entity.logic.EntityNukeExplosionMK5;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.BlockAllocatorStandard;
import com.hbm.explosion.vanillant.standard.BlockProcessorStandard;
import com.hbm.explosion.vanillant.standard.EntityProcessorCross;
import com.hbm.explosion.vanillant.standard.PlayerProcessorStandard;
import com.hbm.handler.threading.PacketThreading;
import com.hbm.interfaces.IBomb;
import com.hbm.items.ModItems;
import com.hbm.main.MainRegistry;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import com.hbm.particle.helper.ExplosionCreator;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
import com.hbm.tileentity.bomb.TileEntityCrashedBomb;
import com.hbm.util.EnumUtil;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.block.ITileEntityProvider;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.material.Material;
import net.minecraft.entity.EntityLivingBase;
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.tileentity.TileEntity;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public class BlockCrashedBomb extends BlockEnumMulti implements ITileEntityProvider, IBomb {
public static enum EnumDudType {
BALEFIRE, CONVENTIONAL, NUKE, SALTED
}
public class BlockCrashedBomb extends BlockContainer implements IBomb {
public BlockCrashedBomb(Material mat) {
super(mat, EnumDudType.class, false, false);
public BlockCrashedBomb(Material p_i45386_1_) {
super(p_i45386_1_);
}
@Override
public TileEntity createNewTileEntity(World world, int meta) {
public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) {
return new TileEntityCrashedBomb();
}
@Override public int getRenderType() { return -1; }
@Override public boolean isOpaqueCube() { return false; }
@Override public boolean renderAsNormalBlock() { return false; }
@Override
public Item getItemDropped(int p_149650_1_, Random p_149650_2_, int p_149650_3_) {
return Item.getItemFromBlock(ModBlocks.crashed_balefire);
}
@Override
public int getRenderType() {
return -1;
}
@Override
public boolean isOpaqueCube() {
return false;
}
@Override
public boolean renderAsNormalBlock() {
return false;
}
@Override
public void onBlockPlacedBy(World world, int x, int y, int z, EntityLivingBase player, ItemStack itemStack) {
int i = MathHelper.floor_double(player.rotationYaw * 4.0F / 360.0F + 0.5D) & 3;
if(i == 0) {
world.setBlockMetadataWithNotify(x, y, z, 5, 2);
}
if(i == 1) {
world.setBlockMetadataWithNotify(x, y, z, 3, 2);
}
if(i == 2) {
world.setBlockMetadataWithNotify(x, y, z, 4, 2);
}
if(i == 3) {
world.setBlockMetadataWithNotify(x, y, z, 2, 2);
}
}
public boolean onBlockActivated(World world, int x, int y, int z, EntityPlayer player, int i, float fx, float fy, float fz) {
if(world.isRemote) return true;
if(world.isRemote)
return true;
if(player.getHeldItem() != null && player.getHeldItem().getItem() == ModItems.defuser) {
EnumDudType type = EnumUtil.grabEnumSafely(EnumDudType.class, world.getBlockMetadata(x, y, z));
//TODO: make this less scummy
if(type == type.BALEFIRE) {
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.egg_balefire_shard)));
}
if(type == type.CONVENTIONAL) {
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.ball_tnt, 16)));
}
if(type == type.NUKE) {
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.ball_tnt, 8)));
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.billet_plutonium, 4)));
}
if(type == type.SALTED) {
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.ball_tnt, 8)));
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.billet_plutonium, 2)));
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.ingot_cobalt, 12)));
}
world.func_147480_a(x, y, z, false);
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.egg_balefire_shard)));
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.plate_steel, 10 + world.rand.nextInt(15))));
world.spawnEntityInWorld(new EntityItem(world, x + 0.5, y + 0.5, z + 0.5, new ItemStack(ModItems.plate_titanium, 2 + world.rand.nextInt(7))));
return true;
}
@ -83,46 +97,21 @@ public class BlockCrashedBomb extends BlockEnumMulti implements ITileEntityProvi
if(!world.isRemote) {
EnumDudType type = EnumUtil.grabEnumSafely(EnumDudType.class, world.getBlockMetadata(x, y, z));
world.setBlockToAir(x, y, z);
EntityBalefire bf = new EntityBalefire(world).mute();
bf.posX = x;
bf.posY = y;
bf.posZ = z;
bf.destructionRange = (int) (BombConfig.fatmanRadius * 1.25);
world.spawnEntityInWorld(bf);
if(type == type.BALEFIRE) {
EntityBalefire bf = new EntityBalefire(world);
bf.setPosition(x, y, z);
bf.destructionRange = (int) (BombConfig.fatmanRadius * 1.25);
world.spawnEntityInWorld(bf);
spawnMush(world, x, y, z, true);
}
if(type == type.CONVENTIONAL) {
ExplosionVNT xnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 35F);
xnt.setBlockAllocator(new BlockAllocatorStandard(24));
xnt.setBlockProcessor(new BlockProcessorStandard().setNoDrop());
xnt.setEntityProcessor(new EntityProcessorCross(5D).withRangeMod(1.5F));
xnt.setPlayerProcessor(new PlayerProcessorStandard());
xnt.explode();
ExplosionCreator.composeEffectLarge(world, x + 0.5, y + 0.5, z + 0.5);
}
if(type == type.NUKE) {
world.spawnEntityInWorld(EntityNukeExplosionMK5.statFac(world, 35, x + 0.5, y + 0.5, z + 0.5));
spawnMush(world, x, y, z, MainRegistry.polaroidID == 11 || world.rand.nextInt(100) == 0);
}
if(type == type.SALTED) {
world.spawnEntityInWorld(EntityNukeExplosionMK5.statFac(world, 25, x + 0.5, y + 0.5, z + 0.5).moreFallout(25));
spawnMush(world, x, y, z, MainRegistry.polaroidID == 11 || world.rand.nextInt(100) == 0);
}
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "muke");
data.setBoolean("balefire", true);
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, x + 0.5, y + 0.5, z + 0.5), new TargetPoint(world.provider.dimensionId, x + 0.5, y + 0.5, z + 0.5, 250));
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "hbm:weapon.mukeExplosion", 15.0F, 1.0F);
}
return BombReturnCode.DETONATED;
}
public static void spawnMush(World world, int x, int y, int z, boolean balefire) {
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "hbm:weapon.mukeExplosion", 15.0F, 1.0F);
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "muke");
data.setBoolean("balefire", balefire);
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(data, x + 0.5, y + 0.5, z + 0.5), new TargetPoint(world.provider.dimensionId, x + 0.5, y + 0.5, z + 0.5, 250));
}
}

View File

@ -1,55 +0,0 @@
package com.hbm.blocks.bomb;
import com.hbm.blocks.generic.BlockFlammable;
import com.hbm.entity.item.EntityTNTPrimedBase;
import api.hbm.block.IFuckingExplode;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
public abstract class BlockDetonatable extends BlockFlammable implements IFuckingExplode {
protected int popFuse; // A shorter fuse for when this explosive is dinked by another
protected boolean detonateOnCollision;
protected boolean detonateOnShot;
public BlockDetonatable(Material mat, int en, int flam, int popFuse, boolean detonateOnCollision, boolean detonateOnShot) {
super(mat, en, flam);
this.popFuse = popFuse;
this.detonateOnCollision = detonateOnCollision;
this.detonateOnShot = detonateOnShot;
}
@Override
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion explosion) {
if(!world.isRemote) {
EntityTNTPrimedBase tntPrimed = new EntityTNTPrimedBase(world, x + 0.5D, y + 0.5D, z + 0.5D, explosion != null ? explosion.getExplosivePlacedBy() : null, this);
tntPrimed.fuse = popFuse <= 0 ? 0 : world.rand.nextInt(popFuse) + popFuse / 2;
tntPrimed.detonateOnCollision = detonateOnCollision;
world.spawnEntityInWorld(tntPrimed);
}
}
@Override
public boolean canDropFromExplosion(Explosion explosion) {
return false;
}
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {
if(!world.isRemote && shouldIgnite(world, x, y, z)) {
world.setBlockToAir(x, y, z);
onBlockDestroyedByExplosion(world, x, y, z, null);
}
}
public void onShot(World world, int x, int y, int z) {
if (!detonateOnShot) return;
world.setBlockToAir(x, y, z);
explodeEntity(world, x, y, z, null); // insta-explod
}
}

View File

@ -3,7 +3,6 @@ package com.hbm.blocks.bomb;
import com.hbm.blocks.ModBlocks;
import com.hbm.entity.item.EntityTNTPrimedBase;
import com.hbm.explosion.ExplosionNukeSmall;
import com.hbm.world.biome.BiomeGenCraterBase;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
@ -17,8 +16,6 @@ public class BlockFissureBomb extends BlockTNTBase {
int range = 5;
boolean crater = world.getBiomeGenForCoords((int) Math.floor(x), (int) Math.floor(z)) instanceof BiomeGenCraterBase;
for(int i = -range; i <= range; i++) {
for(int j = -range; j <= range; j++) {
for(int k = -range; k <= range; k++) {
@ -30,7 +27,7 @@ public class BlockFissureBomb extends BlockTNTBase {
Block block = world.getBlock(a, b, c);
if(block == ModBlocks.ore_bedrock) {
world.setBlock(a, b, c, ModBlocks.ore_volcano, crater ? 1 : 0, 3);
world.setBlock(a, b, c, ModBlocks.ore_volcano);
} else if(block == ModBlocks.ore_bedrock_oil) {
world.setBlock(a, b, c, Blocks.bedrock);
}

View File

@ -1,8 +1,7 @@
package com.hbm.blocks.bomb;
import com.hbm.entity.item.EntityTNTPrimedBase;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.BlockProcessorStandard;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.ExplosionNT;
import com.hbm.interfaces.IBomb;
import cpw.mods.fml.relauncher.Side;
@ -14,16 +13,17 @@ import net.minecraft.entity.EntityLivingBase;
import net.minecraft.item.ItemStack;
import net.minecraft.util.IIcon;
import net.minecraft.util.MathHelper;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class BlockPlasticExplosive extends BlockDetonatable implements IBomb {
public class BlockPlasticExplosive extends Block implements IBomb {
@SideOnly(Side.CLIENT)
private IIcon topIcon;
public BlockPlasticExplosive(Material mat) {
super(mat, 0, 0, 0, false, false);
super(mat);
}
@SideOnly(Side.CLIENT)
@ -68,7 +68,12 @@ public class BlockPlasticExplosive extends BlockDetonatable implements IBomb {
}
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion explosion) {
this.explode(world, x, y, z);
}
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block p_149695_5_) {
if(world.isBlockIndirectlyGettingPowered(x, y, z)) {
this.explode(world, x, y, z);
}
@ -78,14 +83,10 @@ public class BlockPlasticExplosive extends BlockDetonatable implements IBomb {
public BombReturnCode explode(World world, int x, int y, int z) {
if(!world.isRemote) {
new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 20).makeStandard().setBlockProcessor(new BlockProcessorStandard().setNoDrop()).explode();
new ExplosionNT(world, null, x + 0.5, y + 0.5, z + 0.5, 50).overrideResolution(64).explode();
ExplosionLarge.spawnParticles(world, x, y, z, ExplosionLarge.cloudFunction(15));
}
return BombReturnCode.DETONATED;
}
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
explode(world, MathHelper.floor_double(x), MathHelper.floor_double(y), MathHelper.floor_double(z));
}
}

View File

@ -8,6 +8,6 @@ public class BlockSemtex extends BlockTNTBase {
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
world.createExplosion(entity, x, y, z, 12F, true);
world.createExplosion(entity, x, y, z, 20F, true);
}
}

View File

@ -8,6 +8,6 @@ public class BlockTNT extends BlockTNTBase {
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
world.createExplosion(entity, x, y, z, 10F, true);
world.createExplosion(entity, x, y, z, 12F, true);
}
}

View File

@ -2,6 +2,7 @@ package com.hbm.blocks.bomb;
import java.util.Random;
import com.hbm.blocks.generic.BlockFlammable;
import com.hbm.entity.item.EntityTNTPrimedBase;
import com.hbm.util.ChatBuilder;
@ -15,18 +16,21 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.projectile.EntityArrow;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.util.EnumChatFormatting;
import net.minecraft.util.IIcon;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public abstract class BlockTNTBase extends BlockDetonatable implements IToolable {
public abstract class BlockTNTBase extends BlockFlammable implements IToolable {
@SideOnly(Side.CLIENT) private IIcon topIcon;
@SideOnly(Side.CLIENT) private IIcon bottomIcon;
public BlockTNTBase() {
super(Material.tnt, 15, 100, 20, false, false);
super(Material.tnt, 15, 100);
}
@Override
@ -58,9 +62,13 @@ public abstract class BlockTNTBase extends BlockDetonatable implements IToolable
}
public void checkAndIgnite(World world, int x, int y, int z) {
if (shouldIgnite(world, x, y, z)) {
this.onBlockDestroyedByPlayer(world, x, y, z, 1);
world.setBlockToAir(x, y, z);
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
if(world.getBlock(x + dir.offsetX, y + dir.offsetY, z + dir.offsetZ) == Blocks.fire) {
this.onBlockDestroyedByPlayer(world, x, y, z, 1);
world.setBlockToAir(x, y, z);
return;
}
}
}
@ -69,6 +77,15 @@ public abstract class BlockTNTBase extends BlockDetonatable implements IToolable
return 1;
}
@Override
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion explosion) {
if(!world.isRemote) {
EntityTNTPrimedBase entitytntprimed = new EntityTNTPrimedBase(world, x + 0.5D, y + 0.5D, z + 0.5D, explosion.getExplosivePlacedBy(), this);
entitytntprimed.fuse = world.rand.nextInt(entitytntprimed.fuse / 4) + entitytntprimed.fuse / 8;
world.spawnEntityInWorld(entitytntprimed);
}
}
@Override
public void onBlockDestroyedByPlayer(World world, int x, int y, int z, int meta) {
this.prime(world, x, y, z, meta, (EntityLivingBase) null);
@ -108,12 +125,19 @@ public abstract class BlockTNTBase extends BlockDetonatable implements IToolable
}
}
@Override
public boolean canDropFromExplosion(Explosion explosion) {
return false;
}
public abstract void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity);
@Override
@SideOnly(Side.CLIENT)
public void registerBlockIcons(IIconRegister iconRegister) {
this.blockIcon = iconRegister.registerIcon(this.getTextureName() + "_side");
this.topIcon = iconRegister.registerIcon(this.getTextureName() + "_top");
this.bottomIcon = iconRegister.registerIcon(this.getTextureName() + "_bottom");
public void registerBlockIcons(IIconRegister p_149651_1_) {
this.blockIcon = p_149651_1_.registerIcon(this.getTextureName() + "_side");
this.topIcon = p_149651_1_.registerIcon(this.getTextureName() + "_top");
this.bottomIcon = p_149651_1_.registerIcon(this.getTextureName() + "_bottom");
}
@Override

View File

@ -4,72 +4,169 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import com.hbm.blocks.ITooltipProvider;
import com.hbm.blocks.ModBlocks;
import com.hbm.entity.mob.EntityTaintCrab;
import com.hbm.entity.mob.EntityCreeperTainted;
import com.hbm.entity.mob.EntityTeslaCrab;
import com.hbm.potion.HbmPotion;
import cpw.mods.fml.client.registry.RenderingRegistry;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.creativetab.CreativeTabs;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.item.EntityFallingBlock;
import net.minecraft.entity.monster.EntityCreeper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.potion.PotionEffect;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import net.minecraftforge.common.util.ForgeDirection;
public class BlockTaint extends Block implements ITooltipProvider {
public class BlockTaint extends Block/*Container*/ {
@SideOnly(Side.CLIENT)
private IIcon[] icons;
public BlockTaint(Material mat) {
super(mat);
this.setTickRandomly(true);
public BlockTaint(Material p_i45386_1_) {
super(p_i45386_1_);
this.setTickRandomly(true);
}
@Override public MapColor getMapColor(int meta) { return MapColor.grayColor; }
@Override public Item getItemDropped(int i, Random rand, int j) { return null; }
/*@Override
public TileEntity createNewTileEntity(World p_149915_1_, int p_149915_2_) {
return new TileEntityTaint();
}*/
@SideOnly(Side.CLIENT)
public IIcon getIcon(int p_149691_1_, int meta)
{
return this.icons[meta % this.icons.length];
}
public int damageDropped(int meta)
{
return 0;
}
public static int func_150032_b(int p_150032_0_)
{
return func_150031_c(p_150032_0_);
}
public static int func_150031_c(int p_150031_0_)
{
return p_150031_0_ & 15;
}
@SideOnly(Side.CLIENT)
public void getSubBlocks(Item p_149666_1_, CreativeTabs p_149666_2_, List p_149666_3_)
{
for (int i = 0; i < 16; ++i)
{
p_149666_3_.add(new ItemStack(p_149666_1_, 1, i));
}
}
@SideOnly(Side.CLIENT)
public void registerBlockIcons(IIconRegister p_149651_1_)
{
this.icons = new IIcon[16];
for (int i = 0; i < this.icons.length; ++i)
{
this.icons[i] = p_149651_1_.registerIcon("hbm:taint_" + i);
}
}
public MapColor getMapColor(int p_149728_1_)
{
return MapColor.purpleColor;
}
public static int renderID = RenderingRegistry.getNextAvailableRenderId();
@Override
public void updateTick(World world, int x, int y, int z, Random rand) {
int meta = world.getBlockMetadata(x, y, z);
if(meta >= 15) return;
for(int i = -3; i <= 3; i++) for(int j = -3; j <= 3; j++) for(int k = -3; k <= 3; k++) {
if(Math.abs(i) + Math.abs(j) + Math.abs(k) > 4) continue;
if(rand.nextFloat() > 0.25F) continue;
Block b = world.getBlock(x + i, y + j, z + k);
if(b.isAir(world, x + i, y + j, z + k) || b == Blocks.bedrock) continue;
int targetMeta = meta + 1;
boolean hasAir = false;
for(ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) {
if(world.getBlock(x + i + dir.offsetX, y + j + dir.offsetY, z + k + dir.offsetZ).isAir(world, x + i + dir.offsetX, y + j + dir.offsetY, z + k + dir.offsetZ)) {
hasAir = true;
break;
}
}
if(!hasAir) targetMeta = meta + 3;
if(targetMeta > 15) continue;
if(b == this && world.getBlockMetadata(x + i, y + j, z + k) >= targetMeta) continue;
world.setBlock(x + i, y + j, z + k, this, targetMeta, 3);
if(rand.nextFloat() < 0.25F && BlockFalling.func_149831_e(world, x + i, y + j - 1, z + k)) {
EntityFallingBlock falling = new EntityFallingBlock(world, x + i + 0.5, y + j + 0.5, z + k + 0.5, this, targetMeta);
world.spawnEntityInWorld(falling);
}
}
public int getRenderType(){
return renderID;
}
@Override
public Item getItemDropped(int p_149650_1_, Random p_149650_2_, int p_149650_3_)
{
return null;
}
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
return AxisAlignedBB.getBoundingBox(x, y, z, x + 1, y + 0.75, z + 1);
public boolean isOpaqueCube() {
return false;
}
@Override
public boolean renderAsNormalBlock() {
return false;
}
public void onNeighborBlockChange(World world, int x, int y, int z, Block b)
{
if(!hasPosNeightbour(world, x, y, z) && !world.isRemote)
world.setBlockToAir(x, y, z);
}
public void updateTick(World world, int x, int y, int z, Random rand)
{
int meta = world.getBlockMetadata(x, y, z);
if(!world.isRemote && meta < 15) {
for(int i = 0; i < 15; i++) {
int a = rand.nextInt(11) + x - 5;
int b = rand.nextInt(11) + y - 5;
int c = rand.nextInt(11) + z - 5;
if(world.getBlock(a, b, c).isReplaceable(world, a, b, c) && hasPosNeightbour(world, a, b, c))
world.setBlock(a, b, c, ModBlocks.taint, meta + 1, 2);
}
for(int i = 0; i < 85; i++) {
int a = rand.nextInt(7) + x - 3;
int b = rand.nextInt(7) + y - 3;
int c = rand.nextInt(7) + z - 3;
if(world.getBlock(a, b, c).isReplaceable(world, a, b, c) && hasPosNeightbour(world, a, b, c))
world.setBlock(a, b, c, ModBlocks.taint, meta + 1, 2);
}
}
}
public static boolean hasPosNeightbour(World world, int x, int y, int z) {
Block b0 = world.getBlock(x + 1, y, z);
Block b1 = world.getBlock(x, y + 1, z);
Block b2 = world.getBlock(x, y, z + 1);
Block b3 = world.getBlock(x - 1, y, z);
Block b4 = world.getBlock(x, y - 1, z);
Block b5 = world.getBlock(x, y, z - 1);
boolean b = (b0.renderAsNormalBlock() && b0.getMaterial().isOpaque()) ||
(b1.renderAsNormalBlock() && b1.getMaterial().isOpaque()) ||
(b2.renderAsNormalBlock() && b2.getMaterial().isOpaque()) ||
(b3.renderAsNormalBlock() && b3.getMaterial().isOpaque()) ||
(b4.renderAsNormalBlock() && b4.getMaterial().isOpaque()) ||
(b5.renderAsNormalBlock() && b5.getMaterial().isOpaque());
return b;
}
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
{
return null;
}
@Override
public AxisAlignedBB getSelectedBoundingBoxFromPool(World par1World, int par2, int par3, int par4)
{
return AxisAlignedBB.getBoundingBox(par2, par3, par4, par2, par3, par4);
}
@Override
@ -77,43 +174,36 @@ public class BlockTaint extends Block implements ITooltipProvider {
int meta = world.getBlockMetadata(x, y, z);
int level = 15 - meta;
List<ItemStack> list = new ArrayList<ItemStack>();
PotionEffect effect = new PotionEffect(HbmPotion.taint.id, 15 * 20, level);
effect.setCurativeItems(list);
if(entity instanceof EntityLivingBase) {
if(world.rand.nextInt(50) == 0) {
((EntityLivingBase)entity).addPotionEffect(effect);
}
}
if(entity != null && entity.getClass().equals(EntityCreeper.class)) {
EntityCreeperTainted creep = new EntityCreeperTainted(world);
creep.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch);
entity.motionX *= 0.6;
entity.motionZ *= 0.6;
if(!world.isRemote) {
entity.setDead();
world.spawnEntityInWorld(creep);
}
}
if(entity instanceof EntityTeslaCrab) {
EntityTaintCrab crab = new EntityTaintCrab(world);
crab.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch);
List<ItemStack> list = new ArrayList<ItemStack>();
PotionEffect effect = new PotionEffect(HbmPotion.taint.id, 15 * 20, level);
effect.setCurativeItems(list);
if(entity instanceof EntityLivingBase) {
if(world.rand.nextInt(50) == 0) {
((EntityLivingBase) entity).addPotionEffect(effect);
}
}
if(entity != null && entity.getClass().equals(EntityCreeper.class)) {
EntityCreeperTainted creep = new EntityCreeperTainted(world);
creep.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch);
if(!world.isRemote) {
entity.setDead();
world.spawnEntityInWorld(creep);
}
}
if(entity instanceof EntityTeslaCrab) {
EntityTaintCrab crab = new EntityTaintCrab(world);
crab.setLocationAndAngles(entity.posX, entity.posY, entity.posZ, entity.rotationYaw, entity.rotationPitch);
if(!world.isRemote) {
entity.setDead();
world.spawnEntityInWorld(crab);
}
}
if(!world.isRemote) {
entity.setDead();
world.spawnEntityInWorld(crab);
}
}
}
@Override
public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean ext) {
list.add("DO NOT TOUCH, BREATHE OR STARE AT.");
}
}

View File

@ -9,8 +9,8 @@ import com.hbm.blocks.ModBlocks;
import com.hbm.entity.projectile.EntityShrapnel;
import com.hbm.explosion.ExplosionNT;
import com.hbm.explosion.ExplosionNT.ExAttrib;
import com.hbm.handler.threading.PacketThreading;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import com.hbm.packet.AuxParticlePacketNT;
import com.hbm.packet.PacketDispatcher;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import cpw.mods.fml.relauncher.Side;
@ -43,10 +43,10 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
public int getSubCount() {
return 5;
}
@SideOnly(Side.CLIENT)
public void getSubBlocks(Item item, CreativeTabs tab, List list) {
for(int i = 0; i < 5; ++i) {
list.add(new ItemStack(item, 1, i));
}
@ -54,14 +54,14 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
@Override
public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean ext) {
int meta = stack.getItemDamage();
if(meta == META_SMOLDERING) {
list.add(EnumChatFormatting.GOLD + "SHIELD VOLCANO");
return;
}
list.add(BlockVolcano.isGrowing(meta) ? (EnumChatFormatting.RED + "DOES GROW") : (EnumChatFormatting.DARK_GRAY + "DOES NOT GROW"));
list.add(BlockVolcano.isExtinguishing(meta) ? (EnumChatFormatting.RED + "DOES EXTINGUISH") : (EnumChatFormatting.DARK_GRAY + "DOES NOT EXTINGUISH"));
}
@ -71,25 +71,25 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
public static final int META_GROWING_ACTIVE = 2;
public static final int META_GROWING_EXTINGUISHING = 3;
public static final int META_SMOLDERING = 4;
public static boolean isGrowing(int meta) {
return meta == META_GROWING_ACTIVE || meta == META_GROWING_EXTINGUISHING;
}
public static boolean isExtinguishing(int meta) {
return meta == META_STATIC_EXTINGUISHING || meta == META_GROWING_EXTINGUISHING;
}
public static class TileEntityVolcanoCore extends TileEntity {
private static List<ExAttrib> volcanoExplosion = Arrays.asList(new ExAttrib[] {ExAttrib.NODROP, ExAttrib.LAVA_V, ExAttrib.NOSOUND, ExAttrib.ALLMOD, ExAttrib.NOHURT});
private static List<ExAttrib> volcanoRadExplosion = Arrays.asList(new ExAttrib[] {ExAttrib.NODROP, ExAttrib.LAVA_R, ExAttrib.NOSOUND, ExAttrib.ALLMOD, ExAttrib.NOHURT});
public int volcanoTimer;
@Override
public void updateEntity() {
if(!worldObj.isRemote) {
this.volcanoTimer++;
@ -99,24 +99,24 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
this.blastMagmaChannel();
this.raiseMagma();
}
double magmaChamber = this.magmaChamberSize();
if(magmaChamber > 0) this.blastMagmaChamber(magmaChamber);
Object[] melting = this.surfaceMeltingParams();
if(melting != null) this.meltSurface((int)melting[0], (double)melting[1], (double)melting[2]);
//self-explanatory
if(this.isSpewing()) this.spawnBlobs();
if(this.isSmoking()) this.spawnSmoke();
//generates a 3x3x3 cube of lava
this.surroundLava();
}
if(this.volcanoTimer >= this.getUpdateRate()) {
this.volcanoTimer = 0;
if(this.shouldGrow()) {
worldObj.setBlock(xCoord, yCoord + 1, zCoord, this.getBlockType(), this.getBlockMetadata(), 3);
worldObj.setBlock(xCoord, yCoord, zCoord, getLava());
@ -128,16 +128,16 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
}
}
}
public boolean isRadioacitve() {
return this.getBlockType() == ModBlocks.volcano_rad_core;
}
protected Block getLava() {
if(isRadioacitve()) return ModBlocks.rad_lava_block;
return ModBlocks.volcanic_lava_block;
}
protected List<ExAttrib> getExpAttrb() {
return this.isRadioacitve() ? this.volcanoRadExplosion : this.volcanoExplosion;
}
@ -151,44 +151,44 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
@Override
public void writeToNBT(NBTTagCompound nbt) {
super.writeToNBT(nbt);
nbt.setInteger("timer", this.volcanoTimer);
nbt.setInteger("tier", this.volcanoTimer);
}
private boolean shouldGrow() {
return isGrowing() && yCoord < 200;
}
private boolean isGrowing() {
int meta = this.getBlockMetadata();
return meta == META_GROWING_ACTIVE || meta == META_GROWING_EXTINGUISHING;
}
private boolean isExtinguishing() {
int meta = this.getBlockMetadata();
return meta == META_STATIC_EXTINGUISHING || meta == META_GROWING_EXTINGUISHING;
}
private boolean isSmoking() {
return this.getBlockMetadata() != META_SMOLDERING;
}
private boolean isSpewing() {
return this.getBlockMetadata() != META_SMOLDERING;
}
private boolean hasVerticalChannel() {
return this.getBlockMetadata() != META_SMOLDERING;
}
private double magmaChamberSize() {
return this.getBlockMetadata() == META_SMOLDERING ? 15 : 0;
}
/* count per tick, radius, depth */
private Object[] surfaceMeltingParams() {
return this.getBlockMetadata() == META_SMOLDERING ? new Object[] {50, 50D, 10D} : null;
}
private int getUpdateRate() {
switch(this.getBlockMetadata()) {
case META_STATIC_EXTINGUISHING: return 60 * 60 * 20; //once per hour
@ -197,7 +197,7 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
default: return 10;
}
}
/** Causes two magma explosions, one from bedrock to the core and one from the core to 15 blocks above. */
private void blastMagmaChannel() {
ExplosionNT explosion = new ExplosionNT(worldObj, null, xCoord + 0.5, yCoord + worldObj.rand.nextInt(15) + 1.5, zCoord + 0.5, 7);
@ -205,53 +205,53 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
ExplosionNT explosion2 = new ExplosionNT(worldObj, null, xCoord + 0.5 + worldObj.rand.nextGaussian() * 3, worldObj.rand.nextInt(yCoord + 1), zCoord + 0.5 + worldObj.rand.nextGaussian() * 3, 10);
explosion2.addAllAttrib(getExpAttrb()).explode();
}
/** Causes two magma explosions at a random position around the core, one at normal and one at half range. */
private void blastMagmaChamber(double size) {
for(int i = 0; i < 2; i++) {
double dist = size / (double) (i + 1);
ExplosionNT explosion = new ExplosionNT(worldObj, null, xCoord + 0.5 + worldObj.rand.nextGaussian() * dist, yCoord + 0.5 + worldObj.rand.nextGaussian() * dist, zCoord + 0.5 + worldObj.rand.nextGaussian() * dist, 7);
explosion.addAllAttrib(getExpAttrb()).explode();
}
}
/** Randomly selects surface blocks and converts them into lava if solid or air if not solid. */
private void meltSurface(int count, double radius, double depth) {
for(int i = 0; i < count; i++) {
int x = (int) Math.floor(xCoord + worldObj.rand.nextGaussian() * radius);
int z = (int) Math.floor(zCoord + worldObj.rand.nextGaussian() * radius);
//gaussian distribution makes conversions more likely on the surface and rarer at the bottom
int y = worldObj.getHeightValue(x, z) + 1 - (int) Math.floor(Math.abs(worldObj.rand.nextGaussian() * depth));
Block b = worldObj.getBlock(x, y, z);
if(!b.isAir(worldObj, x, y, z) && b.getExplosionResistance(null) < Blocks.obsidian.getExplosionResistance(null)) {
//turn into lava if solid block, otherwise just break
worldObj.setBlock(x, y, z, b.isNormalCube() ? this.getLava() : Blocks.air);
}
}
}
/** Increases the magma level in a small radius around the core. */
private void raiseMagma() {
int rX = xCoord - 10 + worldObj.rand.nextInt(21);
int rY = yCoord + worldObj.rand.nextInt(11);
int rZ = zCoord - 10 + worldObj.rand.nextInt(21);
if(worldObj.getBlock(rX, rY, rZ) == Blocks.air && worldObj.getBlock(rX, rY - 1, rZ) == this.getLava())
worldObj.setBlock(rX, rY, rZ, this.getLava());
}
/** Creates a 3x3x3 lava sphere around the core. */
private void surroundLava() {
for(int i = -1; i <= 1; i++) {
for(int j = -1; j <= 1; j++) {
for(int k = -1; k <= 1; k++) {
if(i != 0 || j != 0 || k != 0) {
worldObj.setBlock(xCoord + i, yCoord + j, zCoord + k, this.getLava());
}
@ -259,10 +259,10 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
}
}
}
/** Spews specially tagged shrapnels which create volcanic lava and monoxide clouds. */
private void spawnBlobs() {
for(int i = 0; i < 3; i++) {
EntityShrapnel frag = new EntityShrapnel(worldObj);
frag.setLocationAndAngles(xCoord + 0.5, yCoord + 1.5, zCoord + 0.5, 0.0F, 0.0F);
@ -277,13 +277,13 @@ public class BlockVolcano extends BlockContainer implements ITooltipProvider, IB
worldObj.spawnEntityInWorld(frag);
}
}
/** I SEE SMOKE, AND WHERE THERE'S SMOKE THERE'S FIRE! */
private void spawnSmoke() {
NBTTagCompound dPart = new NBTTagCompound();
dPart.setString("type", "vanillaExt");
dPart.setString("mode", "volcano");
PacketThreading.createAllAroundThreadedPacket(new AuxParticlePacketNT(dPart, xCoord + 0.5, yCoord + 10, zCoord + 0.5), new TargetPoint(worldObj.provider.dimensionId, xCoord + 0.5, yCoord + 10, zCoord + 0.5, 250));
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(dPart, xCoord + 0.5, yCoord + 10, zCoord + 0.5), new TargetPoint(worldObj.provider.dimensionId, xCoord + 0.5, yCoord + 10, zCoord + 0.5, 250));
}
}
}

View File

@ -1,13 +1,7 @@
package com.hbm.blocks.bomb;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.BlockAllocatorStandard;
import com.hbm.explosion.vanillant.standard.BlockProcessorStandard;
import com.hbm.explosion.vanillant.standard.EntityProcessorCrossSmooth;
import com.hbm.explosion.vanillant.standard.ExplosionEffectTiny;
import com.hbm.explosion.vanillant.standard.PlayerProcessorStandard;
import com.hbm.explosion.ExplosionChaos;
import com.hbm.interfaces.IBomb;
import com.hbm.particle.helper.ExplosionCreator;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
@ -23,7 +17,9 @@ public class BombFlameWar extends Block implements IBomb {
public void onNeighborBlockChange(World world, int x, int y, int z, Block block) {
if(world.isBlockIndirectlyGettingPowered(x, y, z)) {
explode(world, x, y, z);
ExplosionChaos.explode(world, x, y, z, 15);
ExplosionChaos.spawnExplosion(world, x, y, z, 75);
ExplosionChaos.flameDeath(world, x, y, z, 100);
}
}
@ -31,24 +27,9 @@ public class BombFlameWar extends Block implements IBomb {
public BombReturnCode explode(World world, int x, int y, int z) {
if(!world.isRemote) {
world.func_147480_a(x, y, z, false);
for(int i = 0; i < 150; i++) {
ExplosionVNT vnt = new ExplosionVNT(world, x + world.rand.nextInt(51) - 25, y + world.rand.nextInt(11) - 5, z + world.rand.nextInt(51) - 25, 4, null);
vnt.setEntityProcessor(new EntityProcessorCrossSmooth(1, 25));
vnt.setPlayerProcessor(new PlayerProcessorStandard());
vnt.setSFX(new ExplosionEffectTiny());
vnt.explode();
}
ExplosionVNT xnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 15F);
xnt.setBlockAllocator(new BlockAllocatorStandard(32));
xnt.setBlockProcessor(new BlockProcessorStandard().setNoDrop());
xnt.setEntityProcessor(new EntityProcessorCrossSmooth(2, 200));
xnt.setPlayerProcessor(new PlayerProcessorStandard());
xnt.explode();
ExplosionCreator.composeEffectSmall(world, x + 0.5, y + 0.5, z + 0.5);
ExplosionChaos.explode(world, x, y, z, 15);
ExplosionChaos.spawnExplosion(world, x, y, z, 75);
ExplosionChaos.flameDeath(world, x, y, z, 100);
}
return BombReturnCode.DETONATED;

View File

@ -18,12 +18,10 @@ import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World;
import com.hbm.blocks.ModBlocks;
import com.hbm.entity.effect.EntityMist;
import com.hbm.explosion.ExplosionChaos;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.ExplosionNukeGeneric;
import com.hbm.interfaces.IBomb;
import com.hbm.inventory.fluid.Fluids;
import com.hbm.main.MainRegistry;
import com.hbm.tileentity.bomb.TileEntityBombMulti;
@ -171,11 +169,7 @@ public class BombMulti extends BlockContainer implements IBomb {
}
if(gasCloud > 0) {
EntityMist mist = new EntityMist(world);
mist.setType(Fluids.CHLORINE);
mist.setPosition(x + 0.5, y + 0.5, z + 0.5);
mist.setArea(gasCloud * 15F / 50F, gasCloud * 7.5F / 50F);
world.spawnEntityInWorld(mist);
ExplosionChaos.spawnChlorine(world, x, y, z, gasCloud, gasCloud / 50, 0);
}
return BombReturnCode.DETONATED;

View File

@ -1,18 +1,16 @@
package com.hbm.blocks.bomb;
import com.hbm.entity.item.EntityTNTPrimedBase;
import net.minecraft.util.MathHelper;
import cpw.mods.fml.client.registry.RenderingRegistry;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.init.Blocks;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
public class DetCord extends BlockDetonatable implements IDetConnectible {
public class DetCord extends Block implements IDetConnectible {
public DetCord(Material material) {
super(material, 0, 0, 0, false, false);
public DetCord(Material p_i45394_1_) {
super(p_i45394_1_);
}
public static int renderID = RenderingRegistry.getNextAvailableRenderId();
@ -32,6 +30,16 @@ public class DetCord extends BlockDetonatable implements IDetConnectible {
return false;
}
@Override
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion p_149723_5_) {
this.explode(world, x, y, z);
}
@Override
public boolean canDropFromExplosion(Explosion explosion) {
return false;
}
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block p_149695_5_) {
if(world.isBlockIndirectlyGettingPowered(x, y, z)) {
@ -40,14 +48,10 @@ public class DetCord extends BlockDetonatable implements IDetConnectible {
}
public void explode(World world, int x, int y, int z) {
if(!world.isRemote) {
world.setBlock(x, y, z, Blocks.air);
world.createExplosion(null, x + 0.5, y + 0.5, z + 0.5, 1.5F, true);
}
}
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
explode(world, MathHelper.floor_double(x), MathHelper.floor_double(y), MathHelper.floor_double(z));
}
}

View File

@ -3,21 +3,18 @@ package com.hbm.blocks.bomb;
import java.util.Random;
import com.hbm.blocks.machine.BlockPillar;
import com.hbm.entity.item.EntityTNTPrimedBase;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.ExplosionNT;
import com.hbm.explosion.ExplosionNT.ExAttrib;
import com.hbm.interfaces.IBomb;
import api.hbm.block.IFuckingExplode;
import net.minecraft.util.MathHelper;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.item.Item;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
public class DetMiner extends BlockPillar implements IBomb, IFuckingExplode {
public class DetMiner extends BlockPillar implements IBomb {
public DetMiner(Material mat, String top) {
super(mat, top);
@ -47,13 +44,8 @@ public class DetMiner extends BlockPillar implements IBomb, IFuckingExplode {
}
@Override
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion explosion) {
if(!world.isRemote) {
EntityTNTPrimedBase tntPrimed = new EntityTNTPrimedBase(world, x + 0.5D, y + 0.5D, z + 0.5D, explosion != null ? explosion.getExplosivePlacedBy() : null, this);
tntPrimed.fuse = 0;
tntPrimed.detonateOnCollision = false;
world.spawnEntityInWorld(tntPrimed);
}
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion p_149723_5_) {
this.explode(world, x, y, z);
}
@Override
@ -62,9 +54,4 @@ public class DetMiner extends BlockPillar implements IBomb, IFuckingExplode {
this.explode(world, x, y, z);
}
}
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
explode(world, MathHelper.floor_double(x), MathHelper.floor_double(y), MathHelper.floor_double(z));
}
}

View File

@ -3,14 +3,12 @@ package com.hbm.blocks.bomb;
import com.hbm.blocks.ModBlocks;
import com.hbm.config.BombConfig;
import com.hbm.entity.effect.EntityNukeTorex;
import com.hbm.entity.item.EntityTNTPrimedBase;
import com.hbm.entity.logic.EntityNukeExplosionMK5;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.ExplosionNT;
import com.hbm.interfaces.IBomb;
import com.hbm.lib.RefStrings;
import com.hbm.particle.helper.ExplosionCreator;
import net.minecraft.util.MathHelper;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.block.Block;
@ -18,15 +16,16 @@ import net.minecraft.block.material.Material;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.init.Blocks;
import net.minecraft.util.IIcon;
import net.minecraft.world.Explosion;
import net.minecraft.world.World;
public class ExplosiveCharge extends BlockDetonatable implements IBomb, IDetConnectible {
public class ExplosiveCharge extends Block implements IBomb, IDetConnectible {
@SideOnly(Side.CLIENT)
private IIcon iconTop;
public ExplosiveCharge(Material material) {
super(material, 0, 0, 0, false, false);
public ExplosiveCharge(Material p_i45394_1_) {
super(p_i45394_1_);
}
@Override
@ -48,6 +47,16 @@ public class ExplosiveCharge extends BlockDetonatable implements IBomb, IDetConn
return side == 1 ? this.iconTop : (side == 0 ? this.iconTop : this.blockIcon);
}
@Override
public void onBlockDestroyedByExplosion(World world, int x, int y, int z, Explosion p_149723_5_) {
this.explode(world, x, y, z);
}
@Override
public boolean canDropFromExplosion(Explosion explosion) {
return false;
}
@Override
public void onNeighborBlockChange(World world, int x, int y, int z, Block p_149695_5_) {
if(world.isBlockIndirectlyGettingPowered(x, y, z)) {
@ -65,20 +74,15 @@ public class ExplosiveCharge extends BlockDetonatable implements IBomb, IDetConn
}
if(this == ModBlocks.det_charge) {
new ExplosionNT(world, null, x + 0.5, y + 0.5, z + 0.5, 15).overrideResolution(64).explode();
ExplosionCreator.composeEffectStandard(world, x + 0.5, y + 1, z + 0.5);
ExplosionLarge.spawnParticles(world, x, y, z, ExplosionLarge.cloudFunction(15));
}
if(this == ModBlocks.det_nuke) {
world.spawnEntityInWorld(EntityNukeExplosionMK5.statFac(world, BombConfig.missileRadius, x + 0.5, y + 0.5, z + 0.5));
EntityNukeTorex.statFacStandard(world, x + 0.5, y + 0.5, z + 0.5, BombConfig.missileRadius);
EntityNukeTorex.statFac(world, x + 0.5, y + 0.5, z + 0.5, BombConfig.missileRadius);
}
}
return BombReturnCode.DETONATED;
}
@Override
public void explodeEntity(World world, double x, double y, double z, EntityTNTPrimedBase entity) {
explode(world, MathHelper.floor_double(x), MathHelper.floor_double(y), MathHelper.floor_double(z));
}
}

View File

@ -3,29 +3,20 @@ package com.hbm.blocks.bomb;
import java.util.Random;
import com.hbm.blocks.ModBlocks;
import com.hbm.config.ServerConfig;
import com.hbm.explosion.ExplosionLarge;
import com.hbm.explosion.vanillant.ExplosionVNT;
import com.hbm.explosion.vanillant.standard.*;
import com.hbm.explosion.ExplosionNukeSmall;
import com.hbm.interfaces.IBomb;
import com.hbm.items.ModItems;
import com.hbm.items.weapon.sedna.factory.XFactoryCatapult;
import com.hbm.main.MainRegistry;
import com.hbm.packet.PacketDispatcher;
import com.hbm.packet.toclient.AuxParticlePacketNT;
import com.hbm.tileentity.bomb.TileEntityLandmine;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;
import net.minecraft.block.Block;
import net.minecraft.block.BlockContainer;
import net.minecraft.block.BlockFence;
import net.minecraft.block.material.Material;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.AxisAlignedBB;
import net.minecraft.world.IBlockAccess;
@ -40,6 +31,7 @@ public class Landmine extends BlockContainer implements IBomb {
public Landmine(Material mat, double range, double height) {
super(mat);
this.range = range;
this.height = height;
}
@ -49,9 +41,20 @@ public class Landmine extends BlockContainer implements IBomb {
return new TileEntityLandmine();
}
@Override public int getRenderType() { return -1; }
@Override public boolean isOpaqueCube() { return false; }
@Override public boolean renderAsNormalBlock() { return false; }
@Override
public int getRenderType() {
return -1;
}
@Override
public boolean isOpaqueCube() {
return false;
}
@Override
public boolean renderAsNormalBlock() {
return false;
}
@Override
public Item getItemDropped(int i, Random rand, int j) {
@ -61,10 +64,15 @@ public class Landmine extends BlockContainer implements IBomb {
@Override
public void setBlockBoundsBasedOnState(IBlockAccess world, int x, int y, int z) {
float f = 0.0625F;
if(this == ModBlocks.mine_ap) this.setBlockBounds(5 * f, 0.0F, 5 * f, 11 * f, 1 * f, 11 * f);
if(this == ModBlocks.mine_he) this.setBlockBounds(4 * f, 0.0F, 4 * f, 12 * f, 2 * f, 12 * f);
if(this == ModBlocks.mine_shrap) this.setBlockBounds(5 * f, 0.0F, 5 * f, 11 * f, 1 * f, 11 * f);
if(this == ModBlocks.mine_fat) this.setBlockBounds(5 * f, 0.0F, 4 * f, 11 * f, 6 * f, 12 * f);}
if(this == ModBlocks.mine_ap)
this.setBlockBounds(6 * f, 0.0F, 6 * f, 10 * f, 2 * f, 10 * f);
if(this == ModBlocks.mine_he)
this.setBlockBounds(4 * f, 0.0F, 4 * f, 12 * f, 2 * f, 12 * f);
if(this == ModBlocks.mine_shrap)
this.setBlockBounds(4 * f, 0.0F, 4 * f, 12 * f, 2 * f, 12 * f);
if(this == ModBlocks.mine_fat)
this.setBlockBounds(5 * f, 0.0F, 4 * f, 11 * f, 6 * f, 12 * f);
}
@Override
public AxisAlignedBB getCollisionBoundingBoxFromPool(World world, int x, int y, int z) {
@ -129,18 +137,6 @@ public class Landmine extends BlockContainer implements IBomb {
return false;
}
public boolean isWaterAbove(World world, int x, int y, int z) {
for(int xo = -1; xo <= 1; xo++) {
for(int zo = -1; zo <= 1; zo++) {
Block blockAbove = world.getBlock(x + xo, y + 1, z + zo);
if(blockAbove == Blocks.water || blockAbove == Blocks.flowing_water) {
return true;
}
}
}
return false;
}
@Override
public BombReturnCode explode(World world, int x, int y, int z) {
@ -151,64 +147,20 @@ public class Landmine extends BlockContainer implements IBomb {
Landmine.safeMode = false;
if(this == ModBlocks.mine_ap) {
ExplosionVNT vnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 3F);
vnt.setEntityProcessor(new EntityProcessorCrossSmooth(0.5, ServerConfig.MINE_AP_DAMAGE.get()).setupPiercing(5F, 0.2F));
vnt.setPlayerProcessor(new PlayerProcessorStandard());
vnt.setSFX(new ExplosionEffectWeapon(5, 1F, 0.5F));
vnt.explode();
world.newExplosion(null, x + 0.5, y + 0.5, z + 0.5, 2.5F, false, false);
} else if(this == ModBlocks.mine_he) {
ExplosionVNT vnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 4F);
vnt.setBlockAllocator(new BlockAllocatorStandard());
vnt.setBlockProcessor(new BlockProcessorStandard());
vnt.setEntityProcessor(new EntityProcessorCrossSmooth(1, ServerConfig.MINE_HE_DAMAGE.get()).setupPiercing(15F, 0.2F));
vnt.setPlayerProcessor(new PlayerProcessorStandard());
vnt.setSFX(new ExplosionEffectWeapon(15, 3.5F, 1.25F));
vnt.explode();
ExplosionLarge.explode(world, x + 0.5, y + 0.5, z + 0.5, 3F, true, false, false);
world.newExplosion(null, x + 0.5, y + 2, z + 0.5, 15F, false, false);
} else if(this == ModBlocks.mine_shrap) {
ExplosionVNT vnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 3F);
vnt.setEntityProcessor(new EntityProcessorCrossSmooth(0.5, ServerConfig.MINE_SHRAP_DAMAGE.get()));
vnt.setPlayerProcessor(new PlayerProcessorStandard());
vnt.setSFX(new ExplosionEffectWeapon(5, 1F, 0.5F));
vnt.explode();
ExplosionLarge.explode(world, x + 0.5, y + 0.5, z + 0.5, 1, true, false, false);
ExplosionLarge.spawnShrapnelShower(world, x + 0.5, y + 0.5, z + 0.5, 0, 1D, 0, 45, 0.2D);
ExplosionLarge.spawnShrapnels(world, x + 0.5, y + 0.5, z + 0.5, 5);
} else if(this == ModBlocks.mine_naval) {
ExplosionVNT vnt = new ExplosionVNT(world, x + 5, y + 5, z + 5, 25F);
vnt.setBlockAllocator(new BlockAllocatorWater(32));
vnt.setBlockProcessor(new BlockProcessorStandard());
vnt.setEntityProcessor(new EntityProcessorCrossSmooth(0.5, ServerConfig.MINE_NAVAL_DAMAGE.get()).setupPiercing(5F, 0.2F));
vnt.setPlayerProcessor(new PlayerProcessorStandard());
vnt.setSFX(new ExplosionEffectWeapon(10, 1F, 0.5F));
vnt.explode();
ExplosionLarge.spawnParticlesRadial(world, x + 0.5, y + 2, z + 0.5, 30);
ExplosionLarge.spawnRubble(world,x + 0.5, y + 0.5, z + 0.5, 5 );
// Only spawn water effects if there's water above the mine
if (isWaterAbove(world, x, y, z)) {
ExplosionLarge.spawnFoam(world, x + 0.5, y + 0.5, z + 0.5, 60);
}
} else if(this == ModBlocks.mine_fat) {
ExplosionVNT vnt = new ExplosionVNT(world, x + 0.5, y + 0.5, z + 0.5, 10);
vnt.setBlockAllocator(new BlockAllocatorStandard(64));
vnt.setBlockProcessor(new BlockProcessorStandard());
vnt.setEntityProcessor(new EntityProcessorCrossSmooth(2, ServerConfig.MINE_NUKE_DAMAGE.get()).withRangeMod(1.5F));
vnt.setPlayerProcessor(new PlayerProcessorStandard());
vnt.explode();
XFactoryCatapult.incrementRad(world, x, y, z, 1.5F);
NBTTagCompound data = new NBTTagCompound();
data.setString("type", "muke");
data.setBoolean("balefire", MainRegistry.polaroidID == 11 || world.rand.nextInt(100) == 0);
PacketDispatcher.wrapper.sendToAllAround(new AuxParticlePacketNT(data, x + 0.5, y + 0.5, z + 0.5), new TargetPoint(world.provider.dimensionId, x + 0.5, y + 0.5, z + 0.5, 250));
world.playSoundEffect(x + 0.5, y + 0.5, z + 0.5, "hbm:weapon.mukeExplosion", 25.0F, 0.9F); // this has to be the single worst solution ever
ExplosionNukeSmall.explode(world, x + 0.5, y + 0.5, z + 0.5, ExplosionNukeSmall.PARAMS_MEDIUM);
}
}
return BombReturnCode.DETONATED;
}
}

Some files were not shown because too many files have changed in this diff Show More