├── .github
└── workflows
│ ├── build.yml
│ └── release.yml
├── .gitignore
├── LICENSE
├── README.en.md
├── README.md
├── VERSION.md
├── build.gradle
├── datapack
├── data
│ ├── minecraft
│ │ ├── loot_tables
│ │ │ └── gameplay
│ │ │ │ ├── hero_of_the_village
│ │ │ │ ├── farmer_gift.json
│ │ │ │ ├── leatherworker_gift.json
│ │ │ │ └── toolsmith_gift.json
│ │ │ │ └── piglin_bartering.json
│ │ └── recipes
│ │ │ ├── blast_furnace.json
│ │ │ └── pointed_dripstone.json
│ └── skyland
│ │ └── recipes
│ │ ├── glow_ink_sac_4_ink_sac.json
│ │ └── netherrack_from_blasting.json
├── pack.mcmeta
└── pack.png
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
└── main
├── generated
└── data
│ └── skyland
│ └── advancements
│ ├── ancient_debris.json
│ ├── bedrock_layer.json
│ ├── better_wood.json
│ ├── blast_furnace.json
│ ├── breed_villagers.json
│ ├── bulk_lava.json
│ ├── composter.json
│ ├── coral_fan.json
│ ├── elytra.json
│ ├── gold_ingot.json
│ ├── ice.json
│ ├── kill_wrong.json
│ ├── kill_zombified_piglin.json
│ ├── lava_bucket.json
│ ├── netherrack.json
│ ├── respawn.json
│ ├── root.json
│ ├── save_villager.json
│ ├── shulker_box.json
│ ├── slime.json
│ ├── the_end.json
│ ├── village_hero.json
│ ├── water.json
│ ├── weakness.json
│ └── wood.json
├── java
└── dev
│ └── dubhe
│ └── skyland
│ ├── ComposterCoolDown.java
│ ├── SkyLandChunkGenerator.java
│ ├── SkyLandGamerules.java
│ ├── SkyLandMod.java
│ ├── SkyLandStructures.java
│ ├── SkyLandTrades.java
│ ├── data
│ ├── AdvancementProvider.java
│ └── SkyLandDataGenerator.java
│ ├── mixin
│ ├── BoneMealItemMixin.java
│ ├── CauldronBlockMixin.java
│ ├── ChunkGeneratorsMixin.java
│ ├── EnderDragonFightMixin.java
│ ├── FallingBlockEntityMixin.java
│ ├── FluidBlockMixin.java
│ ├── IntegratedServerLoaderMixin.java
│ ├── LeveledCauldronBlockMixin.java
│ ├── MinecraftServerMixin.java
│ ├── PatrolSpawnerMixin.java
│ ├── PlayerInventoryMixin.java
│ ├── SellItemFactoryAccessor.java
│ ├── ServerPlayerEntityMixin.java
│ ├── ServerWorldMixin.java
│ ├── SlimeEntityMixin.java
│ ├── SnowGolemEntityMixin.java
│ ├── SpawnHelperMixin.java
│ ├── TheEndBiomeCreatorMixin.java
│ ├── TheNetherBiomeCreatorMixin.java
│ ├── WanderingTraderManagerMixin.java
│ ├── WaterCreatureEntityMixin.java
│ ├── WorldPresetsRegistrarMixin.java
│ └── ZombieEntityMixin.java
│ └── plugin
│ ├── ComposterCoolDownProvider.java
│ └── ComposterPlugin.java
└── resources
├── assets
└── skyland
│ └── lang
│ ├── en_us.json
│ ├── zh_cn.json
│ ├── zh_hk.json
│ └── zh_tw.json
├── data
├── minecraft
│ ├── loot_tables
│ │ └── blocks
│ │ │ └── powder_snow.json
│ ├── tags
│ │ ├── mineable
│ │ │ └── shovel.json
│ │ └── worldgen
│ │ │ └── world_preset
│ │ │ └── normal.json
│ └── worldgen
│ │ └── structure
│ │ └── bastion_remnant.json
└── skyland
│ └── structures
│ ├── spawn_platform.nbt
│ └── the_end_portal.nbt
├── fabric.mod.json
├── pack.png
├── skyland.accesswidener
└── skyland.mixins.json
/.github/workflows/build.yml:
--------------------------------------------------------------------------------
1 | name: build
2 | on:
3 | push:
4 | branches:
5 | - "1.19"
6 | - "1.18.2"
7 | paths:
8 | - "*.gradle"
9 | - "gradle.properties"
10 | - "src/**"
11 | - ".github/**"
12 | - "datapack/**"
13 | pull_request:
14 |
15 | jobs:
16 | build:
17 | strategy:
18 | matrix:
19 | java: [ 17 ]
20 | os: [ ubuntu-latest ]
21 | runs-on: ${{ matrix.os }}
22 | steps:
23 | - uses: actions/checkout@v3
24 |
25 | - name: validate gradle wrapper
26 | uses: gradle/wrapper-validation-action@v1
27 |
28 | - name: setup jdk ${{ matrix.java }}
29 | uses: actions/setup-java@v3
30 | with:
31 | distribution: 'temurin'
32 | java-version: ${{ matrix.java }}
33 |
34 | - name: Cache gradle files
35 | uses: actions/cache@v2
36 | with:
37 | path: |
38 | ~/.gradle/caches
39 | ~/.gradle/wrapper
40 | ./.gradle/loom-cache
41 | key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle', 'gradle.properties', '**/*.accesswidener') }}
42 | restore-keys: |
43 | ${{ runner.os }}-gradle-
44 |
45 | - name: make gradle wrapper executable
46 | if: ${{ runner.os != 'Windows' }}
47 | run: chmod +x ./gradlew
48 |
49 | - name: Build with Gradle
50 | run: ./gradlew build --no-daemon --stacktrace
51 |
52 | - uses: actions/upload-artifact@v3
53 | with:
54 | name: build-artifact
55 | path: build/libs/**
56 |
--------------------------------------------------------------------------------
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a package using Gradle and then publish it to GitHub packages when a release is created
2 | # For more information see: https://github.com/actions/setup-java/blob/main/docs/advanced-usage.md#Publishing-using-gradle
3 |
4 | name: Publish Release
5 |
6 | on:
7 | release:
8 | types: [published]
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 | steps:
14 | - uses: actions/checkout@v3
15 |
16 | - name: validate gradle wrapper
17 | uses: gradle/wrapper-validation-action@v1
18 |
19 | - name: setup jdk ${{ matrix.java }}
20 | uses: actions/setup-java@v3
21 | with:
22 | distribution: 'temurin'
23 | java-version: ${{ matrix.java }}
24 |
25 | - name: Cache gradle files
26 | uses: actions/cache@v2
27 | with:
28 | path: |
29 | ~/.gradle/caches
30 | ~/.gradle/wrapper
31 | ./.gradle/loom-cache
32 | key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle', 'gradle.properties', '**/*.accesswidener') }}
33 | restore-keys: |
34 | ${{ runner.os }}-gradle-
35 |
36 | - name: make gradle wrapper executable
37 | if: ${{ runner.os != 'Windows' }}
38 | run: chmod +x ./gradlew
39 |
40 | - name: Build with Gradle
41 | run: ./gradlew build --no-daemon --stacktrace
42 |
43 | - name: Get jar
44 | id: getjar
45 | run: |
46 | output="$(find build/libs/ ! -name "*-dev.jar" ! -name "*.zip" ! -name "*-sources.jar" -type f -printf "%f\n")"
47 | echo "::set-output name=jarname::$output"
48 |
49 | - name: Get zip
50 | id: getzip
51 | run: |
52 | output="$(find build/libs/ ! -name "*.jar" -type f -printf "%f\n")"
53 | echo "::set-output name=zipname::$output"
54 |
55 | - uses: actions/upload-artifact@v3
56 | with:
57 | name: build-artifact
58 | path: build/libs/**
59 |
60 | - name: Upload mod to Github
61 | uses: actions/upload-release-asset@v1
62 | env:
63 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
64 | with:
65 | upload_url: ${{ github.event.release.upload_url }}
66 | asset_path: build/libs/${{ steps.getjar.outputs.jarname }}
67 | asset_name: ${{ steps.getjar.outputs.jarname }}
68 | asset_content_type: application/java-archive
69 |
70 | - name: Upload datapack to Github
71 | uses: actions/upload-release-asset@v1
72 | env:
73 | GITHUB_TOKEN: ${{ secrets.GH_TOKEN }}
74 | with:
75 | upload_url: ${{ github.event.release.upload_url }}
76 | asset_path: build/libs/${{ steps.getzip.outputs.zipname }}
77 | asset_name: ${{ steps.getzip.outputs.zipname }}
78 | asset_content_type: application/java-archive
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # gradle
2 |
3 | .gradle/
4 | build/
5 | out/
6 | classes/
7 |
8 | # eclipse
9 |
10 | *.launch
11 |
12 | # idea
13 |
14 | .idea/
15 | *.iml
16 | *.ipr
17 | *.iws
18 |
19 | # vscode
20 |
21 | .settings/
22 | .vscode/
23 | bin/
24 | .classpath
25 | .project
26 |
27 | # macos
28 |
29 | *.DS_Store
30 |
31 | # fabric
32 |
33 | run/
34 | /src/main/generated/.cache/
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.en.md:
--------------------------------------------------------------------------------
1 | # 下界空岛 | Nether Sky Block
2 |
3 | [](https://www.minecraft.net/)
4 | [](https://fabricmc.net/use/installer/)
5 | [](https://modrinth.com/mod/fabric-api)
6 | [](https://github.com/Nether-Power/Nether-Sky-Block/releases/latest)
7 | [](https://discord.gg/nEt5QTRYTN)
8 |
9 | [](https://github.com/Nether-Power/Nether-Sky-Block/actions/workflows/build.yml/badge.svg)
10 | [](https://github.com/Nether-Power/Nether-Sky-Block/blob/main/LICENSE)
11 | [](https://github.com/Nether-Power/Nether-Sky-Block/pulls)
12 | [](https://github.com/Nether-Power/Nether-Sky-Block/network/members)
13 | [](https://github.com/Nether-Power/Nether-Sky-Block/stargazers)
14 | [](https://github.com/Nether-Power/Nether-Sky-Block/issues)
15 | [](https://docs.microsoft.com/java/openjdk/download)
16 |
17 | ## [中文](README.md) | English
18 |
19 | ## Install
20 |
21 | ### Client
22 |
23 | * Download and install `Minecraft 1.19` , install `Fabric 0.14.8` .
24 | * From [Release](https://github.com/Nether-Power/Nether-Sky-Block/releases/latest) download the last release `mod`
25 | and `datapack` , then put the `mod` to `mods` directory.
26 | * Download `Fabric API 0.57.0+1.19`, then put it to `mods` directory.
27 | * When you create new world, Set `World Type` to `SkyLand` in `More World Options` , and add the DataPack.
28 | * After entering the world, type `/skyland gamerule true` command to enable Nether-Sky-Block settings.
29 |
30 | ### Server
31 |
32 | * Download and install `Minecraft Server 1.19` , install `Fabric 0.14.8` .
33 | * From [Release](https://github.com/Nether-Power/Nether-Sky-Block/releases/latest) download the last release `mod`
34 | and `datapack` , then put the `mod` to `mods` directory and put the `datapack` to `world/datapacks` directory.
35 | * Download `Fabric API 0.57.0+1.19`, then put it to `mods` directory.
36 | * Set `level-type` to `skyland:skyland` in `server.properties` .
37 | * After starting the server, type `/skyland gamerule true` command in console to enable Nether-Sky-Block settings.
38 |
39 | ## Features
40 |
41 | ### MOD
42 |
43 | - Set three dimensions to void
44 | - Replace overworld with nether
45 | - Removed the experimental world warning
46 | - All features of one key switch
47 | - `/skyland gamerule `
48 | - Ignore the influence of LC value on monster spawn efficiency
49 | - `/gamerule qnmdLC true`
50 | - Increase the spawning probability of Wandering Trader merchants by 10 times
51 | - `/gamerule chieftainMode true`
52 | - When creating a map, an initial platform will be created on the y-axis 64(A crimson nylium, a warped nylium, crimson
53 | fungus is planted above the crimson nylium, and an apple in item frame is hung above the warped nylium)
54 | - When the first player first entered the world, he was given 32 bone meal
55 | - Zombie villager is generated when zombified piglin and zombie trigger zombie reinforcements
56 | - `/gamerule villagerReinforcements true`
57 | - The nether will generate patrol
58 | - `/gamerule netherPatrol true`
59 | - Soul Sand Valley spawn Witch (extremely low probability)
60 | - Bastion Remnant spawn Pillager
61 | - Basalt Deltas spawn Slime
62 | - The lava beside the Water Cauldron (full of water) is converted into obsidian and consumes all the water in the Water
63 | Cauldron
64 | - `/gamerule waterCauldron true`
65 | - Enable the nether biome to spawn Wandering Trader riding Strider(When the highest point of a player's 40 blocks radius
66 | is lava, there is a 10% probability of spawn every 20min. When the first spawn fails, the probability of subsequent
67 | spawn increases to 30%)
68 | - `/gamerule netherTrader true`
69 | - Delete the Emerald for Pumpkin Pie transaction when the Farmer Villager apprentice level is removed
70 | - The water above the coral blocks will spawn squid
71 | - When you kill the resurrected Ender Dragon, you will refresh the Shulker above the Exit portal
72 | - `/gamerule killDragonSpawnShulker true`
73 | - When you kill the Ender Dragon, you will drop an Elytra with the remaining 1% durability
74 | - `/gamerule killDragonDropElytra true`
75 | - Generate the End Portal in the nether
76 | - The world will generate `8` End Portal frames with a radius of `1024` centered on `spawnpoint`
77 | - Anvil Handle
78 | - `/gamerule anvilHandle true`
79 | - Press a Moss Block and a Dirt into a Grass Block
80 | - The Raid can be triggered in the nether
81 | - Items no longer scatter when you death
82 | - Use bone meal on the side of the coral block to make it grow a coral fan, and use bone meal on the top to grow coral
83 | - Dig powder snow to get snowballs
84 | - The Snow Golem standing on the water will turn the water into ice
85 | - `/gamerule iceGolem true`
86 | - Sneak in composer can produce bone meal
87 | - `/gamerule ComposterBoneMeal true`
88 | - The following animals will be spawn on the Grass Block of the Nether Waste
89 | - Cow
90 | - Sheep
91 | - Llama
92 | - Wolf
93 | - Horse
94 | - Donkey
95 | - The FoodLevel before death will be remembered after death
96 | - `/gamerule memoryFoodLevel true`
97 | - Minimum FoodLevel after death and resurrection (effective after the rule `memoryFoodLevel` is turned on, the default is `4`)
98 | - `/gamerule respawnMinFoodLevel 4`
99 | - The Wandering Trader deals in additional items
100 | - You can containing powder snow in Basalt Deltas
101 |
102 | | **Item** | **Count** | **Price** | **Transactions Count** |
103 | |-------------|-----------|-----------|------------------------|
104 | | Turtle Egg | 1 | 16 | 4 |
105 | | Tall Flower | 1 | 8 | 8 |
106 | | Cocoa Bean | 1 | 16 | 8 |
107 | | Bamboo | 1 | 16 | 8 |
108 | | Nether Wart | 1 | 32 | 4 |
109 |
110 | ### DATAPACK
111 |
112 | - recipes
113 | - Blast furnace recipe of replacing Smooth Stone with Obsidian
114 | - Burn the Nether Wart Block in the blast furnace to obtain the Nether Wart Block
115 | - Use the stone cutter to cut the dripstone block to obtain dripstone
116 | - Glow ink sac synthesized by glowstone powder and ink sac
117 | - Modify piglin transaction
118 | - Delete Fire Resistance Potion trading
119 | - Increase Blackstone trading probability
120 | - Reduce Water Bottle trading probability
121 | - Added Glowstone Dust trading
122 | - Delete Ender Pearl trading
123 | - When owning a Hero of the Village Status Effect
124 | - the Mason Villager has a probability to throw Lava Bucket (weight 3)
125 | - the Toolsmith Villager has a probability to throw Netherite Scrap (weight 3)
126 | - Farmers have a chance to throw pumpkins (weight 3)
127 |
128 | ## Contributor
129 |
130 | * Planner
131 | * [朽白](https://space.bilibili.com/178682437)
132 | * Programmer
133 | * [古镇天Gugle](https://space.bilibili.com/19822751)
134 | * [Cjsah](https://space.bilibili.com/19170004)
135 | * [DancingSnow](https://space.bilibili.com/302121711)
136 | * [Huaji_MUR233](https://space.bilibili.com/434118309)
137 |
138 | ## Powered by
139 |
140 | * [AnvilCraft-SkyLandMod](https://github.com/Dubhe-Studio/AnvilCraft-SkyLandMod)
141 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # 下界空岛 | Nether Sky Block
2 |
3 | [](https://www.minecraft.net/)
4 | [](https://fabricmc.net/use/installer/)
5 | [](https://modrinth.com/mod/fabric-api)
6 | [](https://github.com/Nether-Power/Nether-Sky-Block/releases/latest)
7 | [](https://kook.top/eZ59fk)
8 |
9 |
10 | [](https://github.com/Nether-Power/Nether-Sky-Block/actions/workflows/build.yml/badge.svg)
11 | [](https://github.com/Nether-Power/Nether-Sky-Block/blob/main/LICENSE)
12 | [](https://github.com/Nether-Power/Nether-Sky-Block/pulls)
13 | [](https://github.com/Nether-Power/Nether-Sky-Block/network/members)
14 | [](https://github.com/Nether-Power/Nether-Sky-Block/stargazers)
15 | [](https://github.com/Nether-Power/Nether-Sky-Block/issues)
16 | [](https://docs.microsoft.com/java/openjdk/download)
17 |
18 | ## 中文 | [English](README.en.md)
19 |
20 | ## Install
21 |
22 | ### Client
23 |
24 | * 下载安装 `Minecraft 1.19`, 安装 `Fabric 0.14.8`
25 | * 从 [Release](https://github.com/Nether-Power/Nether-Sky-Block/releases/latest) 下载最新发行版 `mod` 和 `datapack`, 并将 `mod` 放入 `mods` 文件夹
26 | * 下载 `Fabric API 0.57.0+1.19`, 并放入 `mods` 文件夹
27 | * 创建世界时, 在 `更多选项` 中将 `世界类型` 调为 `空岛` 并添加数据包
28 | * 进入进入世界后,输入 `/skyland gamerule true` 命令打开地狱空岛的所需规则
29 |
30 | ### Server
31 |
32 | * 下载安装 `Minecraft Server 1.19`, 安装 `Fabric 0.14.8`
33 | * 从 [Release](https://github.com/Nether-Power/Nether-Sky-Block/releases/latest) 下载最新发行版 `mod` 和 `datapack`, 并分别放入 `mods` 与 `world/datapacks` 文件夹
34 | * 下载 `Fabric API 0.57.0+1.19`, 并放入 `mods` 文件夹
35 | * 创建世界时, 在 `server.properties` 中将 `level-type` 调为 `skyland:skyland`
36 | * 开启服务器后,在控制台输入 `/skyland gamerule true` 命令打开地狱空岛的所需规则
37 |
38 | ## Features
39 |
40 | ### 模组
41 |
42 | - 将三个维度设置为虚空
43 | - 将主世界生成替换为下界
44 | - 去除了实验性世界警告
45 | - 一键开关所有特性
46 | - `/skyland gamerule `
47 | - 忽略LC值对刷怪效率的影响
48 | - `/gamerule qnmdLC true`
49 | - 使流浪商人的刷新概率提升10倍
50 | - `/gamerule chieftainMode true`
51 | - 创建地图时会在Y轴64创建一个初始平台(一个绯红菌岩、一个诡异菌岩、绯红菌岩上方种植绯红菌、诡异菌岩上方挂着放着苹果的展示框)
52 | - 第一个玩家第一次进入世界时给予32个骨粉
53 | - 僵尸猪灵和僵尸触发僵尸增援时生成僵尸村民
54 | - `/gamerule villagerReinforcements true`
55 | - 下界会生成灾厄巡逻队
56 | - `/gamerule netherPatrol true`
57 | - 灵魂沙峡谷刷新女巫(概率极低)
58 | - 堡垒遗迹刷新劫掠者
59 | - 玄武岩三角洲刷新史莱姆
60 | - 储水炼药锅(满水)旁的熔岩转化为黑曜石并消耗储水炼药锅内的全部水
61 | - `/gamerule waterCauldron true`
62 | - 使下界群系可以生成骑着赤足兽的游商(玩家40格半径最高点为熔岩时,每20min有10%概率生成,当第一次生成失败时后续生成概率提高至30%)
63 | - `/gamerule netherTrader true`
64 | - 删除农民学徒等级时的绿宝石换南瓜派交易
65 | - 珊瑚块上方的水会生成鱿鱼
66 | - 击杀复活的末影龙时会在祭坛上方刷新潜影贝
67 | - `/gamerule killDragonSpawnShulker true`
68 | - 击杀末影龙时会掉落一个剩余1%耐久的鞘翅
69 | - `/gamerule killDragonDropElytra true`
70 | - 下界内生成末地传送门
71 | - 世界内会以 `出生点` 为中心, 半径 `1024` 生成 `8` 个末地门框架
72 | - 铁砧处理
73 | - `/gamerule anvilHandle true`
74 | - 将一个苔藓块与一个泥土压合成草方块
75 | - 在下界里可以触发袭击
76 | - 死亡时物品不再散开
77 | - 对着珊瑚块侧面使用骨粉使之生长出珊瑚扇,对其顶面使用骨粉生长出珊瑚
78 | - 挖掘细雪获取雪球
79 | - 雪傀儡站在水上面会将水变为冰
80 | - `/gamerule iceGolem true`
81 | - 站在堆肥桶中下蹲,可以产生骨粉
82 | - `/gamerule composterBoneMeal true`
83 | - 下界荒地的草方块上会生成以下动物
84 | - 牛
85 | - 马
86 | - 羊
87 | - 驴
88 | - 羊驼
89 | - 狼
90 | - 死亡后会记忆死亡前的饱食度
91 | - `/gamerule memoryFoodLevel true`
92 | - 死亡复活后最低饱食度(在规则 `memoryFoodLevel` 开启后有效, 默认为 `4`)
93 | - `/gamerule respawnMinFoodLevel 4`
94 | - 玄武岩三角洲接细雪
95 | - 游商会交易除基础物品外的额外物品
96 |
97 | | **物品** | **数量** | **价格** | **交易次数** |
98 | |--------|--------|--------|----------|
99 | | 海龟蛋 | 1 | 16 | 4 |
100 | | 高花 | 1 | 8 | 8 |
101 | | 可可豆 | 1 | 16 | 8 |
102 | | 竹子 | 1 | 16 | 8 |
103 | | 地狱疣 | 1 | 32 | 4 |
104 |
105 | ### 数据包
106 |
107 | - 配方
108 | - 用黑曜石替换平滑石的高炉合成
109 | - 高炉里烧下界疣块以获取下界岩
110 | - 使用切石机切割滴水石块获取滴水石锥
111 | - 萤石粉和墨囊合成荧光墨囊
112 | - 修改猪灵交易
113 | - 删除抗火药水
114 | - 增加黑石交易概率
115 | - 降低水瓶交易概率
116 | - 增加萤石粉交易
117 | - 删除末影珍珠交易
118 | - 拥有村庄英雄时
119 | - 皮匠会有概率丢岩浆桶(权重3)
120 | - 工具匠会有概率丢下界合金碎片(权重3)
121 | - 农民有概率丢南瓜(权重3)
122 |
123 | ## Contributor
124 |
125 | * 策划
126 | * [朽白](https://space.bilibili.com/178682437)
127 | * 代码
128 | * [古镇天Gugle](https://space.bilibili.com/19822751)
129 | * [Cjsah](https://space.bilibili.com/19170004)
130 | * [DancingSnow](https://space.bilibili.com/302121711)
131 | * [Huaji_MUR233](https://space.bilibili.com/434118309)
132 |
133 | ## Powered by
134 |
135 | * [AnvilCraft-SkyLandMod](https://github.com/Dubhe-Studio/AnvilCraft-SkyLandMod)
136 |
--------------------------------------------------------------------------------
/VERSION.md:
--------------------------------------------------------------------------------
1 | ## 2022/07/23 1.1.0
2 | * Added
3 | * 在满水的储水炼药锅内消耗全部水将玄武岩洗涤为滴水石块
4 | * 使用切石机切割滴水石块获取滴水石锥
5 | * 玄武岩三角洲接细雪
6 | * 细雪挖掘可以获得雪球
7 | * 对着珊瑚块侧面使用骨粉使之生长出珊瑚扇,对其顶面右键生长出珊瑚
8 | * 死亡时物品不再散开
9 | * 下界荒地的草方块上会生成以下动物
10 | * 牛
11 | * 马
12 | * 羊
13 | * 驴
14 | * 羊驼
15 | * 狼
16 | * Remove
17 | * 删除灵魂土配方
18 | * 农民不再有概率丢小麦种子
19 | * 游商会出售雪球、珊瑚扇
20 | * 用铁砧砸一下滴水石块将其变为滴水石锥
21 | * 珊瑚扇在有水炼药锅里用铁砧砸一下会消耗一层水并增加多一个珊瑚扇
22 |
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | plugins {
2 | id 'fabric-loom' version '0.12-SNAPSHOT'
3 | id 'io.github.juuxel.loom-quiltflower' version '1.7.3'
4 | id 'maven-publish'
5 | }
6 |
7 | version = project.mod_version
8 | group = project.maven_group
9 |
10 | sourceCompatibility = JavaVersion.VERSION_17
11 | targetCompatibility = JavaVersion.VERSION_17
12 |
13 | println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch'))
14 |
15 | sourceSets {
16 | main {
17 | resources {
18 | srcDirs += [
19 | "src/main/generated"
20 | ]
21 | }
22 | }
23 | }
24 |
25 | loom {
26 | accessWidenerPath = file("src/main/resources/skyland.accesswidener")
27 |
28 | runs {
29 | datagen {
30 | server()
31 |
32 | name "Minecraft Data"
33 |
34 | vmArg "-Dfabric-api.datagen"
35 | vmArg "-Dfabric-api.datagen.output-dir=${file("src/main/generated")}"
36 |
37 | runDir "build/datagen"
38 | }
39 | }
40 | }
41 | assemble.dependsOn runDatagen
42 |
43 | repositories {
44 | maven {
45 | url "https://cursemaven.com"
46 | content {
47 | includeGroup "curse.maven"
48 | }
49 | }
50 | }
51 | dependencies {
52 | minecraft "com.mojang:minecraft:${project.mc_version}"
53 | mappings "net.fabricmc:yarn:${project.yarn_version}:v2"
54 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
55 |
56 | // Fabric API. This is technically optional, but you probably want it anyway.
57 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
58 |
59 | // Nullable
60 | compileOnly "com.google.code.findbugs:jsr305:3.0.2"
61 |
62 | // Add other mod.
63 | modImplementation "curse.maven:jade-324717:${jade_file}"
64 |
65 | }
66 |
67 | processResources {
68 | inputs.property "version", project.version
69 |
70 | filesMatching("fabric.mod.json") {
71 | expand "version": project.version
72 | }
73 | }
74 |
75 | tasks.withType(JavaCompile).configureEach {
76 | it.options.release = 17
77 | }
78 |
79 | java {
80 | // withSourcesJar()
81 | }
82 |
83 | jar {
84 | from("LICENSE") {
85 | rename { "${it}_${project.name}" }
86 | }
87 | }
88 |
89 | publishing {
90 | publications {
91 | mavenJava(MavenPublication) {
92 | artifact(remapJar) {
93 | builtBy remapJar
94 | }
95 | // artifact(sourcesJar) {
96 | // builtBy remapSourcesJar
97 | // }
98 | }
99 | }
100 |
101 | def ENV = System.getenv()
102 | if (ENV.MAVEN_URL) {
103 | repositories.maven {
104 | url ENV.MAVEN_URL
105 | credentials {
106 | username ENV.MAVEN_USERNAME
107 | password ENV.MAVEN_PASSWORD
108 | }
109 | }
110 | }
111 | }
112 |
113 | task build_datapack(type: Zip) {
114 | archiveName "${project.name}-datapack-${project.version}.zip"
115 |
116 | destinationDir file('build/libs')
117 |
118 | from 'datapack'
119 | from("LICENSE") {
120 | rename { "${it}_${project.name}" }
121 | }
122 | }
123 |
124 | build.dependsOn build_datapack
125 |
--------------------------------------------------------------------------------
/datapack/data/minecraft/loot_tables/gameplay/hero_of_the_village/farmer_gift.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:gift",
3 | "pools": [
4 | {
5 | "bonus_rolls": 0.0,
6 | "entries": [
7 | {
8 | "type": "minecraft:item",
9 | "name": "minecraft:bread",
10 | "weight": 30
11 | },
12 | {
13 | "type": "minecraft:item",
14 | "name": "minecraft:pumpkin_pie",
15 | "weight": 30
16 | },
17 | {
18 | "type": "minecraft:item",
19 | "name": "minecraft:cookie",
20 | "weight": 30
21 | },
22 | {
23 | "type": "minecraft:item",
24 | "name": "minecraft:pumpkin",
25 | "weight": 1
26 | }
27 | ],
28 | "rolls": 1.0
29 | }
30 | ]
31 | }
--------------------------------------------------------------------------------
/datapack/data/minecraft/loot_tables/gameplay/hero_of_the_village/leatherworker_gift.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:gift",
3 | "pools": [
4 | {
5 | "bonus_rolls": 0.0,
6 | "entries": [
7 | {
8 | "type": "minecraft:item",
9 | "name": "minecraft:leather",
10 | "weight": 40
11 | },
12 | {
13 | "type": "minecraft:item",
14 | "name": "minecraft:lava_bucket",
15 | "weight": 3
16 | }
17 | ],
18 | "rolls": 1.0
19 | }
20 | ]
21 | }
--------------------------------------------------------------------------------
/datapack/data/minecraft/loot_tables/gameplay/hero_of_the_village/toolsmith_gift.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:gift",
3 | "pools": [
4 | {
5 | "bonus_rolls": 0.0,
6 | "entries": [
7 | {
8 | "type": "minecraft:item",
9 | "name": "minecraft:stone_pickaxe",
10 | "weight": 40
11 | },
12 | {
13 | "type": "minecraft:item",
14 | "name": "minecraft:stone_axe",
15 | "weight": 40
16 | },
17 | {
18 | "type": "minecraft:item",
19 | "name": "minecraft:stone_hoe",
20 | "weight": 40
21 | },
22 | {
23 | "type": "minecraft:item",
24 | "name": "minecraft:stone_shovel",
25 | "weight": 40
26 | },
27 | {
28 | "type": "minecraft:item",
29 | "name": "minecraft:ancient_debris",
30 | "weight": 3
31 | }
32 | ],
33 | "rolls": 1.0
34 | }
35 | ]
36 | }
--------------------------------------------------------------------------------
/datapack/data/minecraft/loot_tables/gameplay/piglin_bartering.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:barter",
3 | "pools": [
4 | {
5 | "bonus_rolls": 0.0,
6 | "entries": [
7 | {
8 | "type": "minecraft:item",
9 | "functions": [
10 | {
11 | "enchantments": [
12 | "minecraft:soul_speed"
13 | ],
14 | "function": "minecraft:enchant_randomly"
15 | }
16 | ],
17 | "name": "minecraft:book",
18 | "weight": 5
19 | },
20 | {
21 | "type": "minecraft:item",
22 | "functions": [
23 | {
24 | "function": "minecraft:set_potion",
25 | "id": "minecraft:water"
26 | }
27 | ],
28 | "name": "minecraft:potion",
29 | "weight": 10
30 | },
31 | {
32 | "type": "minecraft:item",
33 | "functions": [
34 | {
35 | "add": false,
36 | "count": {
37 | "type": "minecraft:uniform",
38 | "max": 46.0,
39 | "min": 20.0
40 | },
41 | "function": "minecraft:set_count"
42 | }
43 | ],
44 | "name": "minecraft:iron_nugget",
45 | "weight": 15
46 | },
47 | {
48 | "type": "minecraft:item",
49 | "functions": [
50 | {
51 | "add": false,
52 | "count": {
53 | "type": "minecraft:uniform",
54 | "max": 9.0,
55 | "min": 3.0
56 | },
57 | "function": "minecraft:set_count"
58 | }
59 | ],
60 | "name": "minecraft:string",
61 | "weight": 20
62 | },
63 | {
64 | "type": "minecraft:item",
65 | "functions": [
66 | {
67 | "add": false,
68 | "count": {
69 | "type": "minecraft:uniform",
70 | "max": 12.0,
71 | "min": 5.0
72 | },
73 | "function": "minecraft:set_count"
74 | }
75 | ],
76 | "name": "minecraft:quartz",
77 | "weight": 20
78 | },
79 | {
80 | "type": "minecraft:item",
81 | "name": "minecraft:obsidian",
82 | "weight": 40
83 | },
84 | {
85 | "type": "minecraft:item",
86 | "functions": [
87 | {
88 | "add": false,
89 | "count": {
90 | "type": "minecraft:uniform",
91 | "max": 3.0,
92 | "min": 1.0
93 | },
94 | "function": "minecraft:set_count"
95 | }
96 | ],
97 | "name": "minecraft:crying_obsidian",
98 | "weight": 40
99 | },
100 | {
101 | "type": "minecraft:item",
102 | "name": "minecraft:fire_charge",
103 | "weight": 40
104 | },
105 | {
106 | "type": "minecraft:item",
107 | "functions": [
108 | {
109 | "add": false,
110 | "count": {
111 | "type": "minecraft:uniform",
112 | "max": 4.0,
113 | "min": 2.0
114 | },
115 | "function": "minecraft:set_count"
116 | }
117 | ],
118 | "name": "minecraft:leather",
119 | "weight": 40
120 | },
121 | {
122 | "type": "minecraft:item",
123 | "functions": [
124 | {
125 | "add": false,
126 | "count": {
127 | "type": "minecraft:uniform",
128 | "max": 8.0,
129 | "min": 2.0
130 | },
131 | "function": "minecraft:set_count"
132 | }
133 | ],
134 | "name": "minecraft:soul_sand",
135 | "weight": 40
136 | },
137 | {
138 | "type": "minecraft:item",
139 | "functions": [
140 | {
141 | "add": false,
142 | "count": {
143 | "type": "minecraft:uniform",
144 | "max": 8.0,
145 | "min": 2.0
146 | },
147 | "function": "minecraft:set_count"
148 | }
149 | ],
150 | "name": "minecraft:nether_brick",
151 | "weight": 40
152 | },
153 | {
154 | "type": "minecraft:item",
155 | "functions": [
156 | {
157 | "add": false,
158 | "count": {
159 | "type": "minecraft:uniform",
160 | "max": 12.0,
161 | "min": 6.0
162 | },
163 | "function": "minecraft:set_count"
164 | }
165 | ],
166 | "name": "minecraft:spectral_arrow",
167 | "weight": 40
168 | },
169 | {
170 | "type": "minecraft:item",
171 | "functions": [
172 | {
173 | "add": false,
174 | "count": {
175 | "type": "minecraft:uniform",
176 | "max": 16.0,
177 | "min": 8.0
178 | },
179 | "function": "minecraft:set_count"
180 | }
181 | ],
182 | "name": "minecraft:gravel",
183 | "weight": 30
184 | },
185 | {
186 | "type": "minecraft:item",
187 | "functions": [
188 | {
189 | "add": false,
190 | "count": {
191 | "type": "minecraft:uniform",
192 | "max": 24.0,
193 | "min": 16.0
194 | },
195 | "function": "minecraft:set_count"
196 | }
197 | ],
198 | "name": "minecraft:blackstone",
199 | "weight": 60
200 | },
201 | {
202 | "type": "minecraft:item",
203 | "name": "minecraft:glowstone_dust",
204 | "weight": 40
205 | }
206 | ],
207 | "rolls": 1.0
208 | }
209 | ]
210 | }
--------------------------------------------------------------------------------
/datapack/data/minecraft/recipes/blast_furnace.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:crafting_shaped",
3 | "key": {
4 | "#": {
5 | "item": "minecraft:obsidian"
6 | },
7 | "I": {
8 | "item": "minecraft:iron_ingot"
9 | },
10 | "X": {
11 | "item": "minecraft:furnace"
12 | }
13 | },
14 | "pattern": [
15 | "III",
16 | "IXI",
17 | "###"
18 | ],
19 | "result": {
20 | "item": "minecraft:blast_furnace"
21 | }
22 | }
--------------------------------------------------------------------------------
/datapack/data/minecraft/recipes/pointed_dripstone.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:stonecutting",
3 | "ingredient": {
4 | "item": "minecraft:dripstone_block"
5 | },
6 | "result": "minecraft:pointed_dripstone",
7 | "count": 1
8 | }
--------------------------------------------------------------------------------
/datapack/data/skyland/recipes/glow_ink_sac_4_ink_sac.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:crafting_shapeless",
3 | "ingredients": [
4 | {
5 | "item": "minecraft:ink_sac"
6 | },
7 | {
8 | "item": "minecraft:glowstone_dust"
9 | }
10 | ],
11 | "result": {
12 | "item": "minecraft:glow_ink_sac"
13 | }
14 | }
--------------------------------------------------------------------------------
/datapack/data/skyland/recipes/netherrack_from_blasting.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:blasting",
3 | "ingredient": {
4 | "item": "minecraft:nether_wart_block"
5 | },
6 | "result": "minecraft:netherrack",
7 | "experience": 0.1,
8 | "cookingtime": 100
9 | }
10 |
--------------------------------------------------------------------------------
/datapack/pack.mcmeta:
--------------------------------------------------------------------------------
1 | {
2 | "pack": {
3 | "description": "Nether_Sky_Block datapack",
4 | "pack_format": 10
5 | }
6 | }
--------------------------------------------------------------------------------
/datapack/pack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nether-Power/Nether-Sky-Block/d155f0f4b3898cd11a1a218cf6d359662c9c8c92/datapack/pack.png
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | org.gradle.jvmargs=-Xmx1G
2 |
3 | mc_version=1.19.2
4 | yarn_version=1.19.2+build.4
5 | loader_version=0.14.9
6 |
7 | mod_version=1.1.0
8 | maven_group=dev.dubhe
9 |
10 | fabric_version=0.60.0+1.19.2
11 |
12 | jade_file=3836188
13 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nether-Power/Nether-Sky-Block/d155f0f4b3898cd11a1a218cf6d359662c9c8c92/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | distributionBase=GRADLE_USER_HOME
2 | distributionPath=wrapper/dists
3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | #
4 | # Copyright 2015 the original author or authors.
5 | #
6 | # Licensed under the Apache License, Version 2.0 (the "License");
7 | # you may not use this file except in compliance with the License.
8 | # You may obtain a copy of the License at
9 | #
10 | # https://www.apache.org/licenses/LICENSE-2.0
11 | #
12 | # Unless required by applicable law or agreed to in writing, software
13 | # distributed under the License is distributed on an "AS IS" BASIS,
14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 | # See the License for the specific language governing permissions and
16 | # limitations under the License.
17 | #
18 |
19 | ##############################################################################
20 | ##
21 | ## Gradle start up script for UN*X
22 | ##
23 | ##############################################################################
24 |
25 | # Attempt to set APP_HOME
26 | # Resolve links: $0 may be a link
27 | PRG="$0"
28 | # Need this for relative symlinks.
29 | while [ -h "$PRG" ] ; do
30 | ls=`ls -ld "$PRG"`
31 | link=`expr "$ls" : '.*-> \(.*\)$'`
32 | if expr "$link" : '/.*' > /dev/null; then
33 | PRG="$link"
34 | else
35 | PRG=`dirname "$PRG"`"/$link"
36 | fi
37 | done
38 | SAVED="`pwd`"
39 | cd "`dirname \"$PRG\"`/" >/dev/null
40 | APP_HOME="`pwd -P`"
41 | cd "$SAVED" >/dev/null
42 |
43 | APP_NAME="Gradle"
44 | APP_BASE_NAME=`basename "$0"`
45 |
46 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
47 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
48 |
49 | # Use the maximum available, or set MAX_FD != -1 to use that value.
50 | MAX_FD="maximum"
51 |
52 | warn () {
53 | echo "$*"
54 | }
55 |
56 | die () {
57 | echo
58 | echo "$*"
59 | echo
60 | exit 1
61 | }
62 |
63 | # OS specific support (must be 'true' or 'false').
64 | cygwin=false
65 | msys=false
66 | darwin=false
67 | nonstop=false
68 | case "`uname`" in
69 | CYGWIN* )
70 | cygwin=true
71 | ;;
72 | Darwin* )
73 | darwin=true
74 | ;;
75 | MSYS* | MINGW* )
76 | msys=true
77 | ;;
78 | NONSTOP* )
79 | nonstop=true
80 | ;;
81 | esac
82 |
83 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
84 |
85 |
86 | # Determine the Java command to use to start the JVM.
87 | if [ -n "$JAVA_HOME" ] ; then
88 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
89 | # IBM's JDK on AIX uses strange locations for the executables
90 | JAVACMD="$JAVA_HOME/jre/sh/java"
91 | else
92 | JAVACMD="$JAVA_HOME/bin/java"
93 | fi
94 | if [ ! -x "$JAVACMD" ] ; then
95 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
96 |
97 | Please set the JAVA_HOME variable in your environment to match the
98 | location of your Java installation."
99 | fi
100 | else
101 | JAVACMD="java"
102 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
103 |
104 | Please set the JAVA_HOME variable in your environment to match the
105 | location of your Java installation."
106 | fi
107 |
108 | # Increase the maximum file descriptors if we can.
109 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
110 | MAX_FD_LIMIT=`ulimit -H -n`
111 | if [ $? -eq 0 ] ; then
112 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
113 | MAX_FD="$MAX_FD_LIMIT"
114 | fi
115 | ulimit -n $MAX_FD
116 | if [ $? -ne 0 ] ; then
117 | warn "Could not set maximum file descriptor limit: $MAX_FD"
118 | fi
119 | else
120 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
121 | fi
122 | fi
123 |
124 | # For Darwin, add options to specify how the application appears in the dock
125 | if $darwin; then
126 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
127 | fi
128 |
129 | # For Cygwin or MSYS, switch paths to Windows format before running java
130 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
131 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
132 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
133 |
134 | JAVACMD=`cygpath --unix "$JAVACMD"`
135 |
136 | # We build the pattern for arguments to be converted via cygpath
137 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
138 | SEP=""
139 | for dir in $ROOTDIRSRAW ; do
140 | ROOTDIRS="$ROOTDIRS$SEP$dir"
141 | SEP="|"
142 | done
143 | OURCYGPATTERN="(^($ROOTDIRS))"
144 | # Add a user-defined pattern to the cygpath arguments
145 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
146 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
147 | fi
148 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
149 | i=0
150 | for arg in "$@" ; do
151 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
152 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
153 |
154 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
155 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
156 | else
157 | eval `echo args$i`="\"$arg\""
158 | fi
159 | i=`expr $i + 1`
160 | done
161 | case $i in
162 | 0) set -- ;;
163 | 1) set -- "$args0" ;;
164 | 2) set -- "$args0" "$args1" ;;
165 | 3) set -- "$args0" "$args1" "$args2" ;;
166 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
167 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
168 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
169 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
170 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
171 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
172 | esac
173 | fi
174 |
175 | # Escape application args
176 | save () {
177 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
178 | echo " "
179 | }
180 | APP_ARGS=`save "$@"`
181 |
182 | # Collect all arguments for the java command, following the shell quoting and substitution rules
183 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
184 |
185 | exec "$JAVACMD" "$@"
186 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @rem
2 | @rem Copyright 2015 the original author or authors.
3 | @rem
4 | @rem Licensed under the Apache License, Version 2.0 (the "License");
5 | @rem you may not use this file except in compliance with the License.
6 | @rem You may obtain a copy of the License at
7 | @rem
8 | @rem https://www.apache.org/licenses/LICENSE-2.0
9 | @rem
10 | @rem Unless required by applicable law or agreed to in writing, software
11 | @rem distributed under the License is distributed on an "AS IS" BASIS,
12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | @rem See the License for the specific language governing permissions and
14 | @rem limitations under the License.
15 | @rem
16 |
17 | @if "%DEBUG%" == "" @echo off
18 | @rem ##########################################################################
19 | @rem
20 | @rem Gradle startup script for Windows
21 | @rem
22 | @rem ##########################################################################
23 |
24 | @rem Set local scope for the variables with windows NT shell
25 | if "%OS%"=="Windows_NT" setlocal
26 |
27 | set DIRNAME=%~dp0
28 | if "%DIRNAME%" == "" set DIRNAME=.
29 | set APP_BASE_NAME=%~n0
30 | set APP_HOME=%DIRNAME%
31 |
32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
34 |
35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
37 |
38 | @rem Find java.exe
39 | if defined JAVA_HOME goto findJavaFromJavaHome
40 |
41 | set JAVA_EXE=java.exe
42 | %JAVA_EXE% -version >NUL 2>&1
43 | if "%ERRORLEVEL%" == "0" goto execute
44 |
45 | echo.
46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
47 | echo.
48 | echo Please set the JAVA_HOME variable in your environment to match the
49 | echo location of your Java installation.
50 |
51 | goto fail
52 |
53 | :findJavaFromJavaHome
54 | set JAVA_HOME=%JAVA_HOME:"=%
55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
56 |
57 | if exist "%JAVA_EXE%" goto execute
58 |
59 | echo.
60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
61 | echo.
62 | echo Please set the JAVA_HOME variable in your environment to match the
63 | echo location of your Java installation.
64 |
65 | goto fail
66 |
67 | :execute
68 | @rem Setup the command line
69 |
70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
71 |
72 |
73 | @rem Execute Gradle
74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
75 |
76 | :end
77 | @rem End local scope for the variables with windows NT shell
78 | if "%ERRORLEVEL%"=="0" goto mainEnd
79 |
80 | :fail
81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
82 | rem the _cmd.exe /c_ return code!
83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
84 | exit /b 1
85 |
86 | :mainEnd
87 | if "%OS%"=="Windows_NT" endlocal
88 |
89 | :omega
90 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | pluginManagement {
2 | repositories {
3 | maven {
4 | name = 'Fabric'
5 | url = 'https://maven.fabricmc.net/'
6 | }
7 | mavenCentral()
8 | gradlePluginPortal()
9 | }
10 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/ancient_debris.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:village_hero",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:ancient_debris"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.ancient_debris.desc"
22 | },
23 | "frame": "challenge",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:ancient_debris"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.ancient_debris.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/bedrock_layer.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:root",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "player": [
7 | {
8 | "condition": "minecraft:entity_properties",
9 | "entity": "this",
10 | "predicate": {
11 | "location": {
12 | "position": {
13 | "y": {
14 | "max": 1.0
15 | }
16 | }
17 | }
18 | }
19 | }
20 | ]
21 | },
22 | "trigger": "minecraft:location"
23 | }
24 | },
25 | "display": {
26 | "announce_to_chat": true,
27 | "background": "minecraft:textures/block/crimson_planks.png",
28 | "description": {
29 | "translate": "advancement.skyland.bedrock_layer.desc"
30 | },
31 | "frame": "goal",
32 | "hidden": false,
33 | "icon": {
34 | "item": "minecraft:bedrock"
35 | },
36 | "show_toast": true,
37 | "title": {
38 | "translate": "advancement.skyland.bedrock_layer.title"
39 | }
40 | },
41 | "requirements": [
42 | [
43 | "0"
44 | ]
45 | ]
46 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/better_wood.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:lava_bucket",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:spruce_sapling"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | },
16 | "1": {
17 | "conditions": {
18 | "items": [
19 | {
20 | "items": [
21 | "minecraft:acacia_sapling"
22 | ]
23 | }
24 | ]
25 | },
26 | "trigger": "minecraft:inventory_changed"
27 | },
28 | "2": {
29 | "conditions": {
30 | "items": [
31 | {
32 | "items": [
33 | "minecraft:birch_sapling"
34 | ]
35 | }
36 | ]
37 | },
38 | "trigger": "minecraft:inventory_changed"
39 | },
40 | "3": {
41 | "conditions": {
42 | "items": [
43 | {
44 | "items": [
45 | "minecraft:dark_oak_sapling"
46 | ]
47 | }
48 | ]
49 | },
50 | "trigger": "minecraft:inventory_changed"
51 | },
52 | "4": {
53 | "conditions": {
54 | "items": [
55 | {
56 | "items": [
57 | "minecraft:jungle_sapling"
58 | ]
59 | }
60 | ]
61 | },
62 | "trigger": "minecraft:inventory_changed"
63 | },
64 | "5": {
65 | "conditions": {
66 | "items": [
67 | {
68 | "items": [
69 | "minecraft:oak_sapling"
70 | ]
71 | }
72 | ]
73 | },
74 | "trigger": "minecraft:inventory_changed"
75 | },
76 | "6": {
77 | "conditions": {
78 | "items": [
79 | {
80 | "items": [
81 | "minecraft:mangrove_propagule"
82 | ]
83 | }
84 | ]
85 | },
86 | "trigger": "minecraft:inventory_changed"
87 | }
88 | },
89 | "display": {
90 | "announce_to_chat": true,
91 | "background": "minecraft:textures/block/crimson_planks.png",
92 | "description": {
93 | "translate": "advancement.skyland.better_wood.desc"
94 | },
95 | "frame": "task",
96 | "hidden": false,
97 | "icon": {
98 | "item": "minecraft:oak_wood"
99 | },
100 | "show_toast": true,
101 | "title": {
102 | "translate": "advancement.skyland.better_wood.title"
103 | }
104 | },
105 | "requirements": [
106 | [
107 | "0",
108 | "1",
109 | "2",
110 | "3",
111 | "4",
112 | "5",
113 | "6"
114 | ]
115 | ]
116 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/blast_furnace.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:gold_ingot",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:blast_furnace"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.blast_furnace.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:blast_furnace"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.blast_furnace.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/breed_villagers.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:village_hero",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:bread"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.breed_villagers.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:bread"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.breed_villagers.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/bulk_lava.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:ice",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:pointed_dripstone"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.bulk_lava.desc"
22 | },
23 | "frame": "goal",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:pointed_dripstone"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.bulk_lava.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/composter.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:wood",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:composter"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.composter.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:composter"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.composter.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/coral_fan.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:lava_bucket",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:brain_coral_fan"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | },
16 | "1": {
17 | "conditions": {
18 | "items": [
19 | {
20 | "items": [
21 | "minecraft:tube_coral_fan"
22 | ]
23 | }
24 | ]
25 | },
26 | "trigger": "minecraft:inventory_changed"
27 | },
28 | "2": {
29 | "conditions": {
30 | "items": [
31 | {
32 | "items": [
33 | "minecraft:bubble_coral_fan"
34 | ]
35 | }
36 | ]
37 | },
38 | "trigger": "minecraft:inventory_changed"
39 | },
40 | "3": {
41 | "conditions": {
42 | "items": [
43 | {
44 | "items": [
45 | "minecraft:fire_coral_fan"
46 | ]
47 | }
48 | ]
49 | },
50 | "trigger": "minecraft:inventory_changed"
51 | },
52 | "4": {
53 | "conditions": {
54 | "items": [
55 | {
56 | "items": [
57 | "minecraft:horn_coral_fan"
58 | ]
59 | }
60 | ]
61 | },
62 | "trigger": "minecraft:inventory_changed"
63 | }
64 | },
65 | "display": {
66 | "announce_to_chat": true,
67 | "background": "minecraft:textures/block/crimson_planks.png",
68 | "description": {
69 | "translate": "advancement.skyland.coral_fan.desc"
70 | },
71 | "frame": "goal",
72 | "hidden": false,
73 | "icon": {
74 | "item": "minecraft:fire_coral_fan"
75 | },
76 | "show_toast": true,
77 | "title": {
78 | "translate": "advancement.skyland.coral_fan.title"
79 | }
80 | },
81 | "requirements": [
82 | [
83 | "0",
84 | "1",
85 | "2",
86 | "3",
87 | "4"
88 | ]
89 | ]
90 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/elytra.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:the_end",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:elytra"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.elytra.desc"
22 | },
23 | "frame": "challenge",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:elytra",
27 | "nbt": "{Damage:0}"
28 | },
29 | "show_toast": true,
30 | "title": {
31 | "translate": "advancement.skyland.elytra.title"
32 | }
33 | },
34 | "requirements": [
35 | [
36 | "0"
37 | ]
38 | ]
39 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/gold_ingot.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:kill_zombified_piglin",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:gold_ingot"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.gold_ingot.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:gold_ingot"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.gold_ingot.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/ice.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:water",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:ice"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.ice.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:ice"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.ice.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/kill_wrong.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:kill_zombified_piglin",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "entity": [
7 | {
8 | "condition": "minecraft:entity_properties",
9 | "entity": "this",
10 | "predicate": {
11 | "type": "minecraft:zombie_villager"
12 | }
13 | }
14 | ]
15 | },
16 | "trigger": "minecraft:player_killed_entity"
17 | }
18 | },
19 | "display": {
20 | "announce_to_chat": true,
21 | "background": "minecraft:textures/block/crimson_planks.png",
22 | "description": {
23 | "translate": "advancement.skyland.kill_wrong.desc"
24 | },
25 | "frame": "task",
26 | "hidden": false,
27 | "icon": {
28 | "item": "minecraft:wooden_sword",
29 | "nbt": "{Damage:0}"
30 | },
31 | "show_toast": true,
32 | "title": {
33 | "translate": "advancement.skyland.kill_wrong.title"
34 | }
35 | },
36 | "requirements": [
37 | [
38 | "0"
39 | ]
40 | ]
41 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/kill_zombified_piglin.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:wood",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "entity": [
7 | {
8 | "condition": "minecraft:entity_properties",
9 | "entity": "this",
10 | "predicate": {
11 | "type": "minecraft:zombified_piglin"
12 | }
13 | }
14 | ]
15 | },
16 | "trigger": "minecraft:player_killed_entity"
17 | }
18 | },
19 | "display": {
20 | "announce_to_chat": true,
21 | "background": "minecraft:textures/block/crimson_planks.png",
22 | "description": {
23 | "translate": "advancement.skyland.kill_zombified_piglin.desc"
24 | },
25 | "frame": "task",
26 | "hidden": false,
27 | "icon": {
28 | "item": "minecraft:diamond_sword",
29 | "nbt": "{Damage:0}"
30 | },
31 | "show_toast": true,
32 | "title": {
33 | "translate": "advancement.skyland.kill_zombified_piglin.title"
34 | }
35 | },
36 | "requirements": [
37 | [
38 | "0"
39 | ]
40 | ]
41 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/lava_bucket.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:village_hero",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:lava_bucket"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.lava_bucket.desc"
22 | },
23 | "frame": "goal",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:lava_bucket"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.lava_bucket.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/netherrack.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:blast_furnace",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:netherrack"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.netherrack.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:netherrack"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.netherrack.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/respawn.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:kill_zombified_piglin",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:respawn_anchor"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.respawn.desc"
22 | },
23 | "frame": "goal",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:respawn_anchor"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.respawn.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/root.json:
--------------------------------------------------------------------------------
1 | {
2 | "criteria": {
3 | "0": {
4 | "conditions": {},
5 | "trigger": "minecraft:inventory_changed"
6 | }
7 | },
8 | "display": {
9 | "announce_to_chat": false,
10 | "background": "minecraft:textures/block/crimson_planks.png",
11 | "description": {
12 | "translate": "advancement.skyland.root.desc"
13 | },
14 | "frame": "task",
15 | "hidden": false,
16 | "icon": {
17 | "item": "minecraft:crimson_fungus"
18 | },
19 | "show_toast": false,
20 | "title": {
21 | "translate": "advancement.skyland.root.title"
22 | }
23 | },
24 | "requirements": [
25 | [
26 | "0"
27 | ]
28 | ]
29 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/save_villager.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:weakness",
3 | "criteria": {
4 | "0": {
5 | "conditions": {},
6 | "trigger": "minecraft:cured_zombie_villager"
7 | }
8 | },
9 | "display": {
10 | "announce_to_chat": true,
11 | "background": "minecraft:textures/block/crimson_planks.png",
12 | "description": {
13 | "translate": "advancement.skyland.save_villager.desc"
14 | },
15 | "frame": "goal",
16 | "hidden": false,
17 | "icon": {
18 | "item": "minecraft:golden_apple"
19 | },
20 | "show_toast": true,
21 | "title": {
22 | "translate": "advancement.skyland.save_villager.title"
23 | }
24 | },
25 | "requirements": [
26 | [
27 | "0"
28 | ]
29 | ]
30 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/shulker_box.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:elytra",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:shulker_shell"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.shulker_box.desc"
22 | },
23 | "frame": "challenge",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:shulker_shell"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.shulker_box.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/slime.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:bedrock_layer",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:slime_ball"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.slime.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:slime_ball"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.slime.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/the_end.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:root",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:ender_eye"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.the_end.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:end_portal_frame"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.the_end.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/village_hero.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:save_villager",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "effects": {
7 | "minecraft:bad_omen": {}
8 | }
9 | },
10 | "trigger": "minecraft:effects_changed"
11 | },
12 | "1": {
13 | "conditions": {
14 | "effects": {
15 | "minecraft:hero_of_the_village": {}
16 | }
17 | },
18 | "trigger": "minecraft:effects_changed"
19 | }
20 | },
21 | "display": {
22 | "announce_to_chat": true,
23 | "background": "minecraft:textures/block/crimson_planks.png",
24 | "description": {
25 | "translate": "advancement.skyland.village_hero.desc"
26 | },
27 | "frame": "challenge",
28 | "hidden": false,
29 | "icon": {
30 | "item": "minecraft:emerald"
31 | },
32 | "show_toast": true,
33 | "title": {
34 | "translate": "advancement.skyland.village_hero.title"
35 | }
36 | },
37 | "requirements": [
38 | [
39 | "0"
40 | ],
41 | [
42 | "1"
43 | ]
44 | ]
45 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/water.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:the_end",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "item": {
7 | "items": [
8 | "minecraft:water_bucket"
9 | ]
10 | }
11 | },
12 | "trigger": "minecraft:filled_bucket"
13 | }
14 | },
15 | "display": {
16 | "announce_to_chat": true,
17 | "background": "minecraft:textures/block/crimson_planks.png",
18 | "description": {
19 | "translate": "advancement.skyland.water.desc"
20 | },
21 | "frame": "goal",
22 | "hidden": false,
23 | "icon": {
24 | "item": "minecraft:water_bucket"
25 | },
26 | "show_toast": true,
27 | "title": {
28 | "translate": "advancement.skyland.water.title"
29 | }
30 | },
31 | "requirements": [
32 | [
33 | "0"
34 | ]
35 | ]
36 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/weakness.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:composter",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "effects": {
7 | "minecraft:weakness": {}
8 | }
9 | },
10 | "trigger": "minecraft:effects_changed"
11 | }
12 | },
13 | "display": {
14 | "announce_to_chat": true,
15 | "background": "minecraft:textures/block/crimson_planks.png",
16 | "description": {
17 | "translate": "advancement.skyland.weakness.desc"
18 | },
19 | "frame": "task",
20 | "hidden": false,
21 | "icon": {
22 | "item": "minecraft:splash_potion"
23 | },
24 | "show_toast": true,
25 | "title": {
26 | "translate": "advancement.skyland.weakness.title"
27 | }
28 | },
29 | "requirements": [
30 | [
31 | "0"
32 | ]
33 | ]
34 | }
--------------------------------------------------------------------------------
/src/main/generated/data/skyland/advancements/wood.json:
--------------------------------------------------------------------------------
1 | {
2 | "parent": "skyland:root",
3 | "criteria": {
4 | "0": {
5 | "conditions": {
6 | "items": [
7 | {
8 | "items": [
9 | "minecraft:crimson_stem"
10 | ]
11 | }
12 | ]
13 | },
14 | "trigger": "minecraft:inventory_changed"
15 | }
16 | },
17 | "display": {
18 | "announce_to_chat": true,
19 | "background": "minecraft:textures/block/crimson_planks.png",
20 | "description": {
21 | "translate": "advancement.skyland.wood.desc"
22 | },
23 | "frame": "task",
24 | "hidden": false,
25 | "icon": {
26 | "item": "minecraft:crimson_stem"
27 | },
28 | "show_toast": true,
29 | "title": {
30 | "translate": "advancement.skyland.wood.title"
31 | }
32 | },
33 | "requirements": [
34 | [
35 | "0"
36 | ]
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/ComposterCoolDown.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland;
2 |
3 | public class ComposterCoolDown {
4 |
5 | public static boolean last_is_sneaking = false;
6 | public static int cool_down = 0;
7 | public static final int MAX_COOL_DOWN = 40;
8 | }
9 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/SkyLandChunkGenerator.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland;
2 |
3 | import com.mojang.serialization.Codec;
4 | import com.mojang.serialization.codecs.RecordCodecBuilder;
5 | import net.minecraft.block.BlockState;
6 | import net.minecraft.structure.StructurePiece;
7 | import net.minecraft.structure.StructurePieceType;
8 | import net.minecraft.structure.StructureSet;
9 | import net.minecraft.util.Identifier;
10 | import net.minecraft.util.dynamic.RegistryOps;
11 | import net.minecraft.util.math.BlockPos;
12 | import net.minecraft.util.math.ChunkPos;
13 | import net.minecraft.util.math.ChunkSectionPos;
14 | import net.minecraft.util.math.noise.DoublePerlinNoiseSampler;
15 | import net.minecraft.util.math.random.ChunkRandom;
16 | import net.minecraft.util.math.random.RandomSeed;
17 | import net.minecraft.util.math.random.Xoroshiro128PlusPlusRandom;
18 | import net.minecraft.util.registry.Registry;
19 | import net.minecraft.util.registry.RegistryEntry;
20 | import net.minecraft.world.ChunkRegion;
21 | import net.minecraft.world.HeightLimitView;
22 | import net.minecraft.world.StructureWorldAccess;
23 | import net.minecraft.world.biome.source.BiomeAccess;
24 | import net.minecraft.world.biome.source.BiomeSource;
25 | import net.minecraft.world.chunk.Chunk;
26 | import net.minecraft.world.gen.GenerationStep;
27 | import net.minecraft.world.gen.StructureAccessor;
28 | import net.minecraft.world.gen.chunk.Blender;
29 | import net.minecraft.world.gen.chunk.ChunkGenerator;
30 | import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
31 | import net.minecraft.world.gen.chunk.NoiseChunkGenerator;
32 | import net.minecraft.world.gen.chunk.VerticalBlockSample;
33 | import net.minecraft.world.gen.noise.NoiseConfig;
34 |
35 | import java.util.concurrent.CompletableFuture;
36 | import java.util.concurrent.Executor;
37 |
38 | public class SkyLandChunkGenerator extends NoiseChunkGenerator {
39 |
40 | private final Registry structuresRegistry;
41 |
42 | public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group(
43 | RegistryOps.createRegistryCodec(Registry.STRUCTURE_SET_KEY)
44 | .forGetter(generator -> generator.structureSetRegistry),
45 | RegistryOps.createRegistryCodec(Registry.NOISE_KEY).forGetter(generator -> generator.structuresRegistry),
46 | BiomeSource.CODEC.fieldOf("biome_source").forGetter(generator -> generator.biomeSource),
47 | ChunkGeneratorSettings.REGISTRY_CODEC.fieldOf("settings").forGetter(generator -> generator.settings))
48 | .apply(instance, instance.stable(SkyLandChunkGenerator::new)));
49 |
50 | public SkyLandChunkGenerator(Registry noiseRegistry,
51 | Registry structuresRegistry, BiomeSource biomeSource,
52 | RegistryEntry settings) {
53 | super(noiseRegistry, structuresRegistry, biomeSource, settings);
54 | this.structuresRegistry = structuresRegistry;
55 | }
56 |
57 | @Override
58 | protected Codec extends ChunkGenerator> getCodec() {
59 | return CODEC;
60 | }
61 |
62 | @Override
63 | public VerticalBlockSample getColumnSample(int x, int z, HeightLimitView world, NoiseConfig noiseConfig) {
64 | return new VerticalBlockSample(world.getBottomY(), new BlockState[0]);
65 | }
66 |
67 | @Override
68 | public CompletableFuture populateNoise(Executor executor, Blender blender, NoiseConfig noiseConfig,
69 | StructureAccessor structureAccessor, Chunk chunk) {
70 | return CompletableFuture.completedFuture(chunk);
71 | }
72 |
73 | @Override
74 | public void generateFeatures(StructureWorldAccess world, Chunk chunk, StructureAccessor structureAccessor) {
75 | ChunkPos chunkPos = chunk.getPos();
76 | BlockPos pos = new BlockPos(chunkPos.getStartX(), chunk.getBottomY(), chunkPos.getStartZ());
77 |
78 | structureAccessor.getStructureStarts(ChunkSectionPos.from(pos),
79 | world.getRegistryManager().get(Registry.STRUCTURE_KEY).get(new Identifier("minecraft:stronghold")))
80 | .forEach(structureStart -> {
81 | for (StructurePiece piece : structureStart.getChildren()) {
82 | if (piece.getType() == StructurePieceType.STRONGHOLD_PORTAL_ROOM) {
83 | if (piece.intersectsChunk(chunkPos, 0)) {
84 | ChunkRandom random = new ChunkRandom(
85 | new Xoroshiro128PlusPlusRandom(RandomSeed.getSeed()));
86 | random.setCarverSeed(world.getSeed(), chunkPos.x, chunkPos.z);
87 | }
88 | }
89 | }
90 | });
91 | }
92 |
93 | @Override
94 | public void buildSurface(ChunkRegion region, StructureAccessor structures, NoiseConfig noiseConfig, Chunk chunk) {
95 | }
96 |
97 | @Override
98 | public void populateEntities(ChunkRegion region) {
99 | }
100 |
101 | @Override
102 | public void carve(ChunkRegion chunkRegion, long seed, NoiseConfig noiseConfig, BiomeAccess biomeAccess,
103 | StructureAccessor structureAccessor, Chunk chunk, GenerationStep.Carver generationStep) {
104 | }
105 |
106 | }
107 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/SkyLandGamerules.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland;
2 |
3 | import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
4 | import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
5 | import net.minecraft.world.GameRules.BooleanRule;
6 | import net.minecraft.world.GameRules.Category;
7 | import net.minecraft.world.GameRules.IntRule;
8 | import net.minecraft.world.GameRules.Key;
9 |
10 | public class SkyLandGamerules {
11 |
12 | public static void registry() {
13 |
14 | }
15 |
16 | public static final Key LC = GameRuleRegistry.register("qnmdLC", Category.MOBS,
17 | GameRuleFactory.createBooleanRule(false));
18 | public static final Key CHIEFTAIN = GameRuleRegistry.register("chieftainMode", Category.MISC,
19 | GameRuleFactory.createBooleanRule(false));
20 | public static final Key WATER_CAULDRON = GameRuleRegistry.register("waterCauldron", Category.MISC,
21 | GameRuleFactory.createBooleanRule(false));
22 | public static final Key NETHER_TRADER = GameRuleRegistry.register("netherTrader", Category.SPAWNING,
23 | GameRuleFactory.createBooleanRule(false));
24 | public static final Key ICE_GOLEM = GameRuleRegistry.register("iceGolem", Category.MISC,
25 | GameRuleFactory.createBooleanRule(false));
26 | public static final Key ANVIL_HANDLE = GameRuleRegistry.register("anvilHandle", Category.MISC,
27 | GameRuleFactory.createBooleanRule(false));
28 | public static final Key NETHER_PATROL = GameRuleRegistry.register("netherPatrol", Category.SPAWNING,
29 | GameRuleFactory.createBooleanRule(false));
30 | public static final Key VILLAGER_REINFORCEMENTS = GameRuleRegistry.register("villagerReinforcements",
31 | Category.SPAWNING, GameRuleFactory.createBooleanRule(false));
32 | public static final Key KILL_DRAGON_SPAWN_SHULKER = GameRuleRegistry.register("killDragonSpawnShulker",
33 | Category.MOBS, GameRuleFactory.createBooleanRule(false));
34 | public static final Key KILL_DRAGON_DROP_ELYTRA = GameRuleRegistry.register("killDragonDropElytra",
35 | Category.DROPS, GameRuleFactory.createBooleanRule(false));
36 | public static final Key COMPOSTER_BONE_MEAL = GameRuleRegistry.register("composterBoneMeal",
37 | Category.MISC, GameRuleFactory.createBooleanRule(false));
38 | public static final Key MEMORY_FOOD_LEVEL = GameRuleRegistry.register("memoryFoodLevel",
39 | Category.PLAYER, GameRuleFactory.createBooleanRule(false));
40 | public static final Key RESPAWN_MIN_FOOD_LEVEL = GameRuleRegistry.register("respawnMinFoodLevel",
41 | Category.PLAYER, GameRuleFactory.createIntRule(4));
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/SkyLandMod.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland;
2 |
3 | import com.mojang.brigadier.arguments.BoolArgumentType;
4 | import net.fabricmc.api.ModInitializer;
5 | import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback;
6 | import net.fabricmc.fabric.api.entity.event.v1.ServerEntityCombatEvents;
7 | import net.fabricmc.fabric.api.entity.event.v1.ServerPlayerEvents;
8 | import net.minecraft.entity.EntityType;
9 | import net.minecraft.entity.ItemEntity;
10 | import net.minecraft.entity.boss.dragon.EnderDragonEntity;
11 | import net.minecraft.item.ItemStack;
12 | import net.minecraft.item.Items;
13 | import net.minecraft.nbt.NbtCompound;
14 | import net.minecraft.server.command.CommandManager;
15 | import net.minecraft.server.command.ServerCommandSource;
16 | import net.minecraft.server.world.ServerWorld;
17 | import net.minecraft.text.Text;
18 | import net.minecraft.util.Identifier;
19 | import net.minecraft.util.math.Vec3d;
20 | import net.minecraft.util.registry.Registry;
21 | import net.minecraft.util.registry.RegistryKey;
22 | import net.minecraft.world.GameRules;
23 | import net.minecraft.world.gen.WorldPreset;
24 |
25 | public class SkyLandMod implements ModInitializer {
26 |
27 | public static final String MOD_ID = "skyland";
28 | public static final Identifier ID = new Identifier(SkyLandMod.MOD_ID, "skyland");
29 |
30 | public static final RegistryKey SKYLAND = RegistryKey.of(Registry.WORLD_PRESET_KEY, ID);
31 |
32 | @Override
33 | public void onInitialize() {
34 |
35 | SkyLandGamerules.registry();
36 |
37 | SkyLandTrades.mergeWanderingTraderOffers(SkyLandTrades.getSkyLandWanderingTraderOffersTier2());
38 | SkyLandTrades.removeFarmerTrades();
39 |
40 | ServerEntityCombatEvents.AFTER_KILLED_OTHER_ENTITY.register((world, entity, killedEntity) -> {
41 | if (world.getGameRules().getBoolean(SkyLandGamerules.KILL_DRAGON_DROP_ELYTRA)
42 | && killedEntity instanceof EnderDragonEntity enderDragonEntity) {
43 | ItemEntity itemEntity = EntityType.ITEM.create(world);
44 | assert itemEntity != null;
45 |
46 | NbtCompound nbtCompound = new NbtCompound();
47 | nbtCompound.putInt("Damage", 426);
48 |
49 | ItemStack itemStack = new ItemStack(Items.ELYTRA, 1);
50 | itemStack.setNbt(nbtCompound);
51 | itemEntity.setStack(itemStack);
52 | Vec3d pos = enderDragonEntity.getPos();
53 | itemEntity.setPosition(pos);
54 | world.spawnEntityAndPassengers(itemEntity);
55 | }
56 | });
57 |
58 | ServerPlayerEvents.AFTER_RESPAWN.register((oldPlayer, newPlayer, alive) -> {
59 | ServerWorld world = newPlayer.getWorld();
60 | if (world.getGameRules().getBoolean(SkyLandGamerules.MEMORY_FOOD_LEVEL)) {
61 | int old_food_level = oldPlayer.getHungerManager().getFoodLevel();
62 | int new_food_level = Math.max(old_food_level,
63 | world.getGameRules().getInt(SkyLandGamerules.RESPAWN_MIN_FOOD_LEVEL));
64 | float old_saturation_level = oldPlayer.getHungerManager().getSaturationLevel();
65 | newPlayer.getHungerManager().setFoodLevel(new_food_level);
66 | newPlayer.getHungerManager().setSaturationLevel(old_saturation_level);
67 | }
68 | });
69 |
70 | CommandRegistrationCallback.EVENT.register((dispatcher, registryAccess, environment) -> dispatcher.register(
71 | CommandManager.literal("skyland").then(CommandManager.literal("gamerule")
72 | .then(CommandManager.argument("boolean", BoolArgumentType.bool()).executes(context -> {
73 | ServerCommandSource serverCommandSource = context.getSource();
74 | boolean bool = BoolArgumentType.getBool(context, "boolean");
75 | serverCommandSource.getServer().getGameRules().get(SkyLandGamerules.WATER_CAULDRON)
76 | .set(bool, serverCommandSource.getServer());
77 | serverCommandSource.getServer().getGameRules().get(SkyLandGamerules.ICE_GOLEM)
78 | .set(bool, serverCommandSource.getServer());
79 | serverCommandSource.getServer().getGameRules().get(SkyLandGamerules.NETHER_TRADER)
80 | .set(bool, serverCommandSource.getServer());
81 | serverCommandSource.getServer().getGameRules().get(SkyLandGamerules.ANVIL_HANDLE)
82 | .set(bool, serverCommandSource.getServer());
83 | serverCommandSource.getServer().getGameRules().get(SkyLandGamerules.NETHER_PATROL)
84 | .set(bool, serverCommandSource.getServer());
85 | serverCommandSource.getServer().getGameRules().get(SkyLandGamerules.VILLAGER_REINFORCEMENTS)
86 | .set(bool, serverCommandSource.getServer());
87 | serverCommandSource.getServer().getGameRules()
88 | .get(SkyLandGamerules.KILL_DRAGON_SPAWN_SHULKER)
89 | .set(bool, serverCommandSource.getServer());
90 | serverCommandSource.getServer().getGameRules().get(SkyLandGamerules.KILL_DRAGON_DROP_ELYTRA)
91 | .set(bool, serverCommandSource.getServer());
92 | serverCommandSource.getServer().getGameRules().get(GameRules.DO_INSOMNIA)
93 | .set(!bool, serverCommandSource.getServer());
94 | serverCommandSource.sendFeedback(
95 | Text.translatable("skyland.command.gamerule_set_succeed", String.valueOf(bool)),
96 | true);
97 | return 1;
98 | })))));
99 |
100 | }
101 | }
102 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/SkyLandStructures.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland;
2 |
3 | import net.minecraft.block.Block;
4 | import net.minecraft.structure.StructurePlacementData;
5 | import net.minecraft.structure.StructureTemplate;
6 | import net.minecraft.util.Identifier;
7 | import net.minecraft.util.math.BlockPos;
8 | import net.minecraft.util.math.random.Random;
9 | import net.minecraft.world.ServerWorldAccess;
10 |
11 | import java.util.Objects;
12 |
13 | public class SkyLandStructures {
14 |
15 | public record SpawnPlatform(BlockPos worldSpawn) {
16 |
17 | public void generate(ServerWorldAccess world, Random random) {
18 | StructureTemplate structure = Objects.requireNonNull(world.getServer()).getStructureTemplateManager()
19 | .getTemplate(new Identifier(SkyLandMod.MOD_ID, "spawn_platform")).orElseThrow();
20 | BlockPos structureOrigin = worldSpawn.subtract(new BlockPos(0, 1, 0));
21 | structure.place(world, structureOrigin, worldSpawn, new StructurePlacementData(), random,
22 | Block.NOTIFY_LISTENERS);
23 | }
24 | }
25 |
26 | public record TheEndPortal(BlockPos worldSpawn) {
27 |
28 | public void generate(ServerWorldAccess world, Random random, BlockPos fixPos) {
29 | StructureTemplate structure = Objects.requireNonNull(world.getServer()).getStructureTemplateManager()
30 | .getTemplate(new Identifier(SkyLandMod.MOD_ID, "the_end_portal")).orElseThrow();
31 | BlockPos structureOrigin = worldSpawn.subtract(fixPos);
32 | structure.place(world, structureOrigin, worldSpawn, new StructurePlacementData(), random,
33 | Block.NOTIFY_LISTENERS);
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/SkyLandTrades.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland;
2 |
3 | import com.google.common.collect.ImmutableMap;
4 | import dev.dubhe.skyland.mixin.SellItemFactoryAccessor;
5 | import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
6 | import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
7 | import net.fabricmc.fabric.api.object.builder.v1.trade.TradeOfferHelper;
8 | import net.minecraft.item.Item;
9 | import net.minecraft.item.Items;
10 | import net.minecraft.village.TradeOffers;
11 | import net.minecraft.village.TradeOffers.Factory;
12 | import net.minecraft.village.TradeOffers.SellItemFactory;
13 | import net.minecraft.village.VillagerProfession;
14 |
15 | import java.util.List;
16 |
17 | public class SkyLandTrades {
18 |
19 | public static void mergeWanderingTraderOffers(Int2ObjectMap custom) {
20 | TradeOffers.Factory[] customTier1 = custom.get(1);
21 | TradeOffers.Factory[] customTier2 = custom.get(2);
22 |
23 | TradeOfferHelper.registerWanderingTraderOffers(1, factories -> {
24 | if (customTier1 != null) {
25 | factories.addAll(List.of(customTier1));
26 | }
27 | });
28 |
29 | TradeOfferHelper.registerWanderingTraderOffers(2, factories -> {
30 | if (customTier2 != null) {
31 | factories.addAll(List.of(customTier2));
32 | }
33 | });
34 |
35 | }
36 |
37 | private static TradeOffers.Factory sell(Item item, int price, int maxUses) {
38 | return new TradeOffers.SellItemFactory(item, price, 1, maxUses, 1);
39 | }
40 |
41 | public static Int2ObjectMap getSkyLandWanderingTraderOffersTier2() {
42 | return new Int2ObjectOpenHashMap<>(ImmutableMap.of(2,
43 | new TradeOffers.Factory[] {
44 | sell(Items.NETHER_WART, 32, 4),
45 | sell(Items.BAMBOO, 16, 8),
46 | sell(Items.SEA_PICKLE, 16, 8),
47 | sell(Items.COCOA_BEANS, 16, 8),
48 | sell(Items.SUNFLOWER, 8, 8),
49 | sell(Items.LILAC, 8, 8),
50 | sell(Items.ROSE_BUSH, 8, 8),
51 | sell(Items.PEONY, 8, 8),
52 | sell(Items.TURTLE_EGG, 16, 4)
53 | }));
54 | }
55 |
56 | public static void removeFarmerTrades() {
57 |
58 | Factory[] farm_trades = TradeOffers.PROFESSION_TO_LEVELED_TRADE.get(VillagerProfession.FARMER).get(2);
59 | Factory[] new_farm_trades = new Factory[2];
60 |
61 | int counter = 0;
62 | for (Factory factory : farm_trades) {
63 | if (factory instanceof SellItemFactory sellItemFactory) {
64 | if (((SellItemFactoryAccessor) sellItemFactory).getSell().getItem() != Items.PUMPKIN_PIE) {
65 | new_farm_trades[counter] = factory;
66 | counter += 1;
67 | }
68 | } else {
69 | new_farm_trades[counter] = factory;
70 | counter += 1;
71 | }
72 | }
73 | TradeOffers.PROFESSION_TO_LEVELED_TRADE.get(VillagerProfession.FARMER).put(2, new_farm_trades);
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/data/AdvancementProvider.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.data;
2 |
3 | import dev.dubhe.skyland.SkyLandMod;
4 | import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
5 | import net.fabricmc.fabric.api.datagen.v1.provider.FabricAdvancementProvider;
6 | import net.minecraft.advancement.Advancement;
7 | import net.minecraft.advancement.AdvancementFrame;
8 | import net.minecraft.advancement.CriterionMerger;
9 | import net.minecraft.advancement.criterion.ChangedDimensionCriterion;
10 | import net.minecraft.advancement.criterion.CriterionConditions;
11 | import net.minecraft.advancement.criterion.CuredZombieVillagerCriterion;
12 | import net.minecraft.advancement.criterion.EffectsChangedCriterion;
13 | import net.minecraft.advancement.criterion.FilledBucketCriterion;
14 | import net.minecraft.advancement.criterion.InventoryChangedCriterion;
15 | import net.minecraft.advancement.criterion.OnKilledCriterion;
16 | import net.minecraft.advancement.criterion.TickCriterion;
17 | import net.minecraft.entity.EntityType;
18 | import net.minecraft.entity.effect.StatusEffects;
19 | import net.minecraft.item.Item;
20 | import net.minecraft.item.Items;
21 | import net.minecraft.predicate.NumberRange.FloatRange;
22 | import net.minecraft.predicate.entity.EntityEffectPredicate;
23 | import net.minecraft.predicate.entity.EntityPredicate;
24 | import net.minecraft.predicate.entity.LocationPredicate;
25 | import net.minecraft.predicate.item.ItemPredicate;
26 | import net.minecraft.text.Text;
27 | import net.minecraft.util.Identifier;
28 | import net.minecraft.world.World;
29 |
30 | import java.util.function.Consumer;
31 |
32 | public class AdvancementProvider extends FabricAdvancementProvider {
33 |
34 | public static String LANG = "advancement." + SkyLandMod.MOD_ID + ".";
35 | public static final Identifier BACK_GROUND = new Identifier("textures/block/crimson_planks.png");
36 |
37 | protected AdvancementProvider(FabricDataGenerator dataGenerator) {
38 | super(dataGenerator);
39 | }
40 |
41 | @SuppressWarnings("unused")
42 | @Override
43 | public void generateAdvancement(Consumer consumer) {
44 | Advancement ROOT = newAdvancement("root", Items.CRIMSON_FUNGUS, TaskType.ROOT,
45 | new Criterion("0", InventoryChangedCriterion.Conditions.items(new ItemPredicate[]{})), consumer);
46 | Advancement WOOD = newAdvancement("wood", Items.CRIMSON_STEM, TaskType.MILESTONE, ROOT,
47 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.CRIMSON_STEM)), consumer);
48 | Advancement COMPOSTER = newAdvancement("composter", Items.COMPOSTER, TaskType.MILESTONE, WOOD,
49 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.COMPOSTER)), consumer);
50 | Advancement KILL_ZOMBIFIED_PIGLIN = newAdvancement("kill_zombified_piglin", Items.DIAMOND_SWORD,
51 | TaskType.MILESTONE, WOOD, new Criterion("0", OnKilledCriterion.Conditions.createPlayerKilledEntity(
52 | EntityPredicate.Builder.create().type(EntityType.ZOMBIFIED_PIGLIN))), consumer);
53 | Advancement KILL_WRONG = newAdvancement("kill_wrong", Items.WOODEN_SWORD, TaskType.MILESTONE,
54 | KILL_ZOMBIFIED_PIGLIN, new Criterion("0", OnKilledCriterion.Conditions.createPlayerKilledEntity(
55 | EntityPredicate.Builder.create().type(EntityType.ZOMBIE_VILLAGER))), consumer);
56 | Advancement GOLD_INGOT = newAdvancement("gold_ingot", Items.GOLD_INGOT, TaskType.MILESTONE,
57 | KILL_ZOMBIFIED_PIGLIN, new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.GOLD_INGOT)),
58 | consumer);
59 | Advancement BLAST_FURNACE = newAdvancement("blast_furnace", Items.BLAST_FURNACE, TaskType.MILESTONE, GOLD_INGOT,
60 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.BLAST_FURNACE)), consumer);
61 | Advancement NETHERRACK = newAdvancement("netherrack", Items.NETHERRACK, TaskType.MILESTONE, BLAST_FURNACE,
62 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.NETHERRACK)), consumer);
63 | Advancement WEAKNESS = newAdvancement("weakness", Items.SPLASH_POTION, TaskType.MILESTONE, COMPOSTER,
64 | new Criterion("0", EffectsChangedCriterion.Conditions.create(
65 | EntityEffectPredicate.create().withEffect(StatusEffects.WEAKNESS))), consumer);
66 | Advancement SAVE_VILLAGER = newAdvancement("save_villager", Items.GOLDEN_APPLE, TaskType.GOAL, WEAKNESS,
67 | new Criterion("0", CuredZombieVillagerCriterion.Conditions.any()), consumer);
68 | Advancement VILLAGE_HERO = Advancement.Builder.create().parent(SAVE_VILLAGER)
69 | .display(Items.EMERALD, getTranslatableTitle("village_hero"), getTranslatableDesc("village_hero"),
70 | BACK_GROUND, AdvancementFrame.CHALLENGE, true, true, false).criterion("0",
71 | EffectsChangedCriterion.Conditions.create(
72 | EntityEffectPredicate.create().withEffect(StatusEffects.BAD_OMEN))).criterion("1",
73 | EffectsChangedCriterion.Conditions.create(
74 | EntityEffectPredicate.create().withEffect(StatusEffects.HERO_OF_THE_VILLAGE)))
75 | .build(consumer, SkyLandMod.MOD_ID + ":village_hero");
76 | Advancement BREED_VILLAGERS = newAdvancement("breed_villagers", Items.BREAD, TaskType.MILESTONE, VILLAGE_HERO,
77 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.BREAD)), consumer);
78 | Advancement LAVA_BUCKET = newAdvancement("lava_bucket", Items.LAVA_BUCKET, TaskType.GOAL, VILLAGE_HERO,
79 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.LAVA_BUCKET)), consumer);
80 | Advancement BETTER_WOOD = Advancement.Builder.create().parent(LAVA_BUCKET)
81 | .display(Items.OAK_WOOD, getTranslatableTitle("better_wood"), getTranslatableDesc("better_wood"),
82 | BACK_GROUND, AdvancementFrame.TASK, true, true, false).criteriaMerger(CriterionMerger.OR)
83 | .criterion("0", InventoryChangedCriterion.Conditions.items(Items.SPRUCE_SAPLING))
84 | .criterion("1", InventoryChangedCriterion.Conditions.items(Items.ACACIA_SAPLING))
85 | .criterion("2", InventoryChangedCriterion.Conditions.items(Items.BIRCH_SAPLING))
86 | .criterion("3", InventoryChangedCriterion.Conditions.items(Items.DARK_OAK_SAPLING))
87 | .criterion("4", InventoryChangedCriterion.Conditions.items(Items.JUNGLE_SAPLING))
88 | .criterion("5", InventoryChangedCriterion.Conditions.items(Items.OAK_SAPLING))
89 | .criterion("6", InventoryChangedCriterion.Conditions.items(Items.MANGROVE_PROPAGULE))
90 | .build(consumer, SkyLandMod.MOD_ID + ":better_wood");
91 | Advancement ANCIENT_DEBRIS = newAdvancement("ancient_debris", Items.ANCIENT_DEBRIS, TaskType.CHALLENGE,
92 | VILLAGE_HERO, new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.ANCIENT_DEBRIS)),
93 | consumer);
94 | Advancement BEDROCK_LAYER = newAdvancement("bedrock_layer", Items.BEDROCK, TaskType.GOAL, ROOT,
95 | new Criterion("0", TickCriterion.Conditions.createLocation(LocationPredicate.y(FloatRange.atMost(1)))),
96 | consumer);
97 | Advancement SLIME = newAdvancement("slime", Items.SLIME_BALL, TaskType.MILESTONE, BEDROCK_LAYER,
98 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.SLIME_BALL)), consumer);
99 | Advancement THE_END = newAdvancement("the_end", Items.END_PORTAL_FRAME, TaskType.MILESTONE, ROOT,
100 | new Criterion("0", ChangedDimensionCriterion.Conditions.to(World.END)), consumer);
101 | Advancement WATER = newAdvancement("water", Items.WATER_BUCKET, TaskType.GOAL, THE_END, new Criterion("0",
102 | FilledBucketCriterion.Conditions.create(
103 | ItemPredicate.Builder.create().items(Items.WATER_BUCKET).build())), consumer);
104 | Advancement ICE = newAdvancement("ice", Items.ICE, TaskType.MILESTONE, WATER,
105 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.ICE)), consumer);
106 | Advancement CORAL_FAN = Advancement.Builder.create().parent(LAVA_BUCKET)
107 | .display(Items.FIRE_CORAL_FAN, getTranslatableTitle("coral_fan"), getTranslatableDesc("coral_fan"),
108 | BACK_GROUND, AdvancementFrame.GOAL, true, true, false).criteriaMerger(CriterionMerger.OR)
109 | .criterion("0", InventoryChangedCriterion.Conditions.items(Items.BRAIN_CORAL_BLOCK))
110 | .criterion("1", InventoryChangedCriterion.Conditions.items(Items.TUBE_CORAL_BLOCK))
111 | .criterion("2", InventoryChangedCriterion.Conditions.items(Items.BUBBLE_CORAL_BLOCK))
112 | .criterion("3", InventoryChangedCriterion.Conditions.items(Items.FIRE_CORAL_BLOCK))
113 | .criterion("4", InventoryChangedCriterion.Conditions.items(Items.HORN_CORAL_BLOCK))
114 | .build(consumer, SkyLandMod.MOD_ID + ":coral_fan");
115 | Advancement ELYTRA = newAdvancement("elytra", Items.ELYTRA, TaskType.CHALLENGE, THE_END,
116 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.ELYTRA)), consumer);
117 | Advancement SHULKER_BOX = newAdvancement("shulker_box", Items.SHULKER_SHELL, TaskType.CHALLENGE, ELYTRA,
118 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.SHULKER_SHELL)), consumer);
119 | Advancement BULK_LAVA = newAdvancement("bulk_lava", Items.POINTED_DRIPSTONE, TaskType.GOAL, ICE,
120 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.POINTED_DRIPSTONE)), consumer);
121 | Advancement RESPAWN = newAdvancement("respawn", Items.RESPAWN_ANCHOR, TaskType.GOAL, KILL_ZOMBIFIED_PIGLIN,
122 | new Criterion("0", InventoryChangedCriterion.Conditions.items(Items.RESPAWN_ANCHOR)), consumer);
123 | }
124 |
125 | public static Text getTranslatableTitle(String title) {
126 | return Text.translatable(LANG + title + ".title");
127 | }
128 |
129 | public static Text getTranslatableDesc(String desc) {
130 | return Text.translatable(LANG + desc + ".desc");
131 | }
132 |
133 | public static Advancement newAdvancement(String id, Item icon, TaskType type, Advancement parent,
134 | Criterion criterion, Consumer consumer) {
135 | return Advancement.Builder.create().parent(parent)
136 | .display(icon, getTranslatableTitle(id), getTranslatableDesc(id), BACK_GROUND, type.frame, type.toast,
137 | type.announce, type.hide).criterion(criterion.name, criterion.conditions)
138 | .build(consumer, SkyLandMod.MOD_ID + ":" + id);
139 | }
140 |
141 | public static Advancement newAdvancement(String id, Item icon, TaskType type, Criterion criterion,
142 | Consumer consumer) {
143 | return Advancement.Builder.create()
144 | .display(icon, getTranslatableTitle(id), getTranslatableDesc(id), BACK_GROUND, type.frame, type.toast,
145 | type.announce, type.hide).criterion(criterion.name, criterion.conditions)
146 | .build(consumer, SkyLandMod.MOD_ID + ":" + id);
147 | }
148 |
149 | enum TaskType {
150 | ROOT(AdvancementFrame.TASK, false, false, false), MILESTONE(AdvancementFrame.TASK, true, true, false), GOAL(
151 | AdvancementFrame.GOAL, true, true, false), SECRET(AdvancementFrame.GOAL, true, true, true), SILENT_GATE(
152 | AdvancementFrame.CHALLENGE, false, false, false), CHALLENGE(AdvancementFrame.CHALLENGE, true, true,
153 | false),
154 |
155 | ;
156 |
157 | private final AdvancementFrame frame;
158 | private final boolean toast;
159 | private final boolean announce;
160 | private final boolean hide;
161 |
162 | TaskType(AdvancementFrame frame, boolean toast, boolean announce, boolean hide) {
163 | this.frame = frame;
164 | this.toast = toast;
165 | this.announce = announce;
166 | this.hide = hide;
167 | }
168 | }
169 |
170 | public record Criterion(String name, CriterionConditions conditions) {
171 |
172 | }
173 |
174 | }
175 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/data/SkyLandDataGenerator.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.data;
2 |
3 | import net.fabricmc.fabric.api.datagen.v1.DataGeneratorEntrypoint;
4 | import net.fabricmc.fabric.api.datagen.v1.FabricDataGenerator;
5 |
6 | public class SkyLandDataGenerator implements DataGeneratorEntrypoint {
7 |
8 | @Override
9 | public void onInitializeDataGenerator(FabricDataGenerator fabricDataGenerator) {
10 | fabricDataGenerator.addProvider(new AdvancementProvider(fabricDataGenerator));
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/BoneMealItemMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 |
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.block.Blocks;
6 | import net.minecraft.block.CoralWallFanBlock;
7 | import net.minecraft.item.BoneMealItem;
8 | import net.minecraft.item.ItemStack;
9 | import net.minecraft.item.ItemUsageContext;
10 | import net.minecraft.util.ActionResult;
11 | import net.minecraft.util.math.BlockPos;
12 | import net.minecraft.util.math.Direction;
13 | import net.minecraft.world.World;
14 | import net.minecraft.world.WorldEvents;
15 | import org.jetbrains.annotations.Nullable;
16 | import org.spongepowered.asm.mixin.Mixin;
17 | import org.spongepowered.asm.mixin.injection.At;
18 | import org.spongepowered.asm.mixin.injection.Inject;
19 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
20 |
21 | @Mixin(BoneMealItem.class)
22 | public class BoneMealItemMixin {
23 |
24 | @Inject(method = "useOnBlock", at = @At("HEAD"), cancellable = true)
25 | private void useOnBlock(ItemUsageContext context, CallbackInfoReturnable cir){
26 | World world = context.getWorld();
27 | BlockPos blockPos = context.getBlockPos();
28 | BlockPos blockPos2 = blockPos.offset(context.getSide());
29 | BlockState blockState = world.getBlockState(blockPos);
30 | boolean bl = blockState.isSideSolidFullSquare(world, blockPos, context.getSide());
31 | if (bl && useOnGround(context.getStack(), world, blockPos2, blockState, context.getSide())) {
32 | if (!world.isClient) {
33 | world.syncWorldEvent(WorldEvents.BONE_MEAL_USED, blockPos2, 0);
34 | }
35 | cir.setReturnValue(ActionResult.success(world.isClient));
36 | }
37 | }
38 |
39 | private static boolean useOnGround(ItemStack stack, World world, BlockPos blockPos, BlockState blockState, @Nullable Direction facing) {
40 | BlockState blockState2 = world.getBlockState(blockPos);
41 | if (facing == Direction.DOWN || !blockState2.getFluidState().isStill()) {
42 | return false;
43 | }
44 | if (facing == Direction.UP){
45 | if (blockState.getBlock() == Blocks.BUBBLE_CORAL_BLOCK){
46 | world.setBlockState(blockPos, Blocks.BUBBLE_CORAL.getDefaultState());
47 | } else if (blockState.getBlock() == Blocks.BRAIN_CORAL_BLOCK){
48 | world.setBlockState(blockPos, Blocks.BRAIN_CORAL.getDefaultState());
49 | } else if (blockState.getBlock() == Blocks.FIRE_CORAL_BLOCK){
50 | world.setBlockState(blockPos, Blocks.FIRE_CORAL.getDefaultState());
51 | } else if (blockState.getBlock() == Blocks.HORN_CORAL_BLOCK){
52 | world.setBlockState(blockPos, Blocks.HORN_CORAL.getDefaultState());
53 | } else if (blockState.getBlock() == Blocks.TUBE_CORAL_BLOCK){
54 | world.setBlockState(blockPos, Blocks.TUBE_CORAL.getDefaultState());
55 | }
56 | } else {
57 | if (blockState.getBlock() == Blocks.BUBBLE_CORAL_BLOCK){
58 | world.setBlockState(blockPos, Blocks.BUBBLE_CORAL_WALL_FAN.getDefaultState().with(CoralWallFanBlock.FACING, facing));
59 | } else if (blockState.getBlock() == Blocks.BRAIN_CORAL_BLOCK){
60 | world.setBlockState(blockPos, Blocks.BRAIN_CORAL_WALL_FAN.getDefaultState().with(CoralWallFanBlock.FACING, facing));
61 | } else if (blockState.getBlock() == Blocks.FIRE_CORAL_BLOCK){
62 | world.setBlockState(blockPos, Blocks.FIRE_CORAL_WALL_FAN.getDefaultState().with(CoralWallFanBlock.FACING, facing));
63 | } else if (blockState.getBlock() == Blocks.HORN_CORAL_BLOCK){
64 | world.setBlockState(blockPos, Blocks.HORN_CORAL_WALL_FAN.getDefaultState().with(CoralWallFanBlock.FACING, facing));
65 | } else if (blockState.getBlock() == Blocks.TUBE_CORAL_BLOCK){
66 | world.setBlockState(blockPos, Blocks.TUBE_CORAL_WALL_FAN.getDefaultState().with(CoralWallFanBlock.FACING, facing));
67 | }
68 | }
69 | stack.decrement(1);
70 | return true;
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/CauldronBlockMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.block.BlockState;
4 | import net.minecraft.block.Blocks;
5 | import net.minecraft.block.CauldronBlock;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.world.World;
8 | import net.minecraft.world.biome.Biome.Precipitation;
9 | import net.minecraft.world.biome.BiomeKeys;
10 | import net.minecraft.world.event.GameEvent;
11 | import org.spongepowered.asm.mixin.Mixin;
12 | import org.spongepowered.asm.mixin.injection.At;
13 | import org.spongepowered.asm.mixin.injection.Inject;
14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
15 |
16 | @Mixin(CauldronBlock.class)
17 | public class CauldronBlockMixin {
18 |
19 | @Inject(method = "precipitationTick", at = @At("HEAD"))
20 | private void precipitationTick(BlockState state, World world, BlockPos pos, Precipitation precipitation,
21 | CallbackInfo ci){
22 | if (world.getBiome(pos).matchesId(BiomeKeys.BASALT_DELTAS.getValue())){
23 | world.setBlockState(pos, Blocks.POWDER_SNOW_CAULDRON.getDefaultState());
24 | world.emitGameEvent(null, GameEvent.BLOCK_CHANGE, pos);
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/ChunkGeneratorsMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import com.mojang.serialization.Codec;
4 | import dev.dubhe.skyland.SkyLandMod;
5 | import dev.dubhe.skyland.SkyLandChunkGenerator;
6 | import net.minecraft.util.registry.Registry;
7 | import net.minecraft.world.gen.chunk.ChunkGenerator;
8 | import net.minecraft.world.gen.chunk.ChunkGenerators;
9 | import org.spongepowered.asm.mixin.Mixin;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.Inject;
12 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
13 |
14 | @Mixin(ChunkGenerators.class)
15 | public class ChunkGeneratorsMixin {
16 |
17 | @Inject(method = "registerAndGetDefault", at = @At("RETURN"))
18 | private static void register(Registry> registry,
19 | CallbackInfoReturnable> cir) {
20 | Registry.register(registry, SkyLandMod.ID, SkyLandChunkGenerator.CODEC);
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/EnderDragonFightMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandChunkGenerator;
4 | import dev.dubhe.skyland.SkyLandGamerules;
5 | import net.minecraft.entity.EntityType;
6 | import net.minecraft.entity.boss.dragon.EnderDragonEntity;
7 | import net.minecraft.entity.boss.dragon.EnderDragonFight;
8 | import net.minecraft.entity.mob.ShulkerEntity;
9 | import net.minecraft.nbt.NbtCompound;
10 | import net.minecraft.server.world.ServerWorld;
11 | import net.minecraft.util.math.BlockPos;
12 | import net.minecraft.world.Heightmap;
13 | import net.minecraft.world.gen.feature.EndPortalFeature;
14 | import org.spongepowered.asm.mixin.Final;
15 | import org.spongepowered.asm.mixin.Mixin;
16 | import org.spongepowered.asm.mixin.Shadow;
17 | import org.spongepowered.asm.mixin.injection.At;
18 | import org.spongepowered.asm.mixin.injection.At.Shift;
19 | import org.spongepowered.asm.mixin.injection.Inject;
20 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
21 |
22 | @Mixin(EnderDragonFight.class)
23 | public class EnderDragonFightMixin {
24 |
25 | @Final
26 | @Shadow
27 | private ServerWorld world;
28 |
29 | @Shadow
30 | private BlockPos exitPortalLocation;
31 |
32 | @Shadow
33 | private boolean previouslyKilled;
34 |
35 | @Inject(method = "", at = @At("TAIL"))
36 | private void setPortal(ServerWorld world, long gatewaysSeed, NbtCompound nbt, CallbackInfo ci) {
37 | if (this.world.getChunkManager().getChunkGenerator() instanceof SkyLandChunkGenerator
38 | && this.exitPortalLocation == null) {
39 | this.exitPortalLocation = new BlockPos(0, 60, 0);
40 | }
41 | }
42 |
43 | @Inject(method = "dragonKilled(Lnet/minecraft/entity/boss/dragon/EnderDragonEntity;)V",
44 | at = @At(
45 | value = "INVOKE",
46 | target = "Lnet/minecraft/entity/boss/dragon/EnderDragonFight;generateNewEndGateway()V",
47 | shift = Shift.AFTER
48 | )
49 | )
50 | private void spawnShulker(EnderDragonEntity dragon, CallbackInfo ci) {
51 | if (world.getGameRules().getBoolean(SkyLandGamerules.KILL_DRAGON_SPAWN_SHULKER)) {
52 | ShulkerEntity shulker = EntityType.SHULKER.create(world);
53 | if (!previouslyKilled || shulker == null) {
54 | return;
55 | }
56 | BlockPos pos = this.world.getTopPosition(Heightmap.Type.MOTION_BLOCKING, EndPortalFeature.ORIGIN);
57 | shulker.setPos(pos.getX(), pos.getY() + 1, pos.getZ());
58 |
59 | world.spawnEntityAndPassengers(shulker);
60 | }
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/FallingBlockEntityMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandGamerules;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.block.Blocks;
6 | import net.minecraft.entity.Entity;
7 | import net.minecraft.entity.EntityType;
8 | import net.minecraft.entity.FallingBlockEntity;
9 | import net.minecraft.entity.ItemEntity;
10 | import net.minecraft.item.Item;
11 | import net.minecraft.item.ItemStack;
12 | import net.minecraft.item.Items;
13 | import net.minecraft.server.world.ServerWorld;
14 | import net.minecraft.tag.BlockTags;
15 | import net.minecraft.util.math.BlockPos;
16 | import net.minecraft.util.math.Box;
17 | import net.minecraft.world.World;
18 | import org.spongepowered.asm.mixin.Mixin;
19 | import org.spongepowered.asm.mixin.Shadow;
20 | import org.spongepowered.asm.mixin.injection.At;
21 | import org.spongepowered.asm.mixin.injection.Inject;
22 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
23 |
24 | import java.util.List;
25 |
26 | @Mixin(FallingBlockEntity.class)
27 | public abstract class FallingBlockEntityMixin extends Entity {
28 | @Shadow
29 | public abstract BlockState getBlockState();
30 |
31 | public FallingBlockEntityMixin(EntityType> type, World world) {
32 | super(type, world);
33 | }
34 |
35 | @Inject(
36 | method = "tick",
37 | at = @At(
38 | value = "INVOKE",
39 | target = "Lnet/minecraft/block/FallingBlock;canFallThrough(Lnet/minecraft/block/BlockState;)Z",
40 | shift = At.Shift.AFTER
41 | )
42 | )
43 | private void onTick(CallbackInfo ci) {
44 | if (world.getGameRules().getBoolean(SkyLandGamerules.ANVIL_HANDLE) && getBlockState().isIn(
45 | BlockTags.ANVIL)) {
46 | BlockState downBlockState = this.world.getBlockState(
47 | new BlockPos(this.getX(), this.getY() - 0.06, this.getZ()));
48 | BlockState downDownBlockState = this.world.getBlockState(
49 | new BlockPos(this.getX(), this.getY() - 1.12, this.getZ()));
50 | // 压合
51 | if (downBlockState.getBlock() == Blocks.MOSS_BLOCK && downDownBlockState.getBlock() == Blocks.DIRT) {
52 | world.setBlockState(new BlockPos(this.getX(), this.getY() - 1.06, this.getZ()), Blocks.GRASS_BLOCK.getDefaultState());
53 | world.setBlockState(new BlockPos(this.getX(), this.getY() - 0.06, this.getZ()), Blocks.AIR.getDefaultState());
54 | }
55 | }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/FluidBlockMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandGamerules;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.block.Blocks;
6 | import net.minecraft.block.FluidBlock;
7 | import net.minecraft.block.LeveledCauldronBlock;
8 | import net.minecraft.util.math.BlockPos;
9 | import net.minecraft.util.math.Direction;
10 | import net.minecraft.world.World;
11 | import net.minecraft.world.WorldEvents;
12 | import org.spongepowered.asm.mixin.Mixin;
13 | import org.spongepowered.asm.mixin.injection.At;
14 | import org.spongepowered.asm.mixin.injection.Inject;
15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
16 |
17 | @Mixin(FluidBlock.class)
18 | public class FluidBlockMixin {
19 |
20 | @Inject(method = "receiveNeighborFluids", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/BlockState;isOf(Lnet/minecraft/block/Block;)Z", shift = At.Shift.AFTER))
21 | private void cauldronObsidian(World world, BlockPos pos, BlockState state, CallbackInfoReturnable cir) {
22 | if (world.getGameRules().getBoolean(SkyLandGamerules.WATER_CAULDRON)) {
23 | for (Direction direction : FluidBlock.FLOW_DIRECTIONS) {
24 | BlockPos blockPos = pos.offset(direction.getOpposite());
25 | BlockState blockState = world.getBlockState(blockPos);
26 | if (blockState.isOf(Blocks.WATER_CAULDRON) && ((LeveledCauldronBlock) blockState.getBlock()).isFull(
27 | blockState)) {
28 | if (world.getFluidState(pos).isStill()) {
29 | world.setBlockState(pos, Blocks.OBSIDIAN.getDefaultState());
30 | world.setBlockState(blockPos, Blocks.CAULDRON.getDefaultState());
31 | world.syncWorldEvent(WorldEvents.LAVA_EXTINGUISHED, pos, 0);
32 | }
33 | }
34 | }
35 | }
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/IntegratedServerLoaderMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 |
4 | import com.mojang.serialization.Lifecycle;
5 | import net.minecraft.client.MinecraftClient;
6 | import net.minecraft.client.gui.screen.world.CreateWorldScreen;
7 | import net.minecraft.server.integrated.IntegratedServerLoader;
8 | import net.minecraft.world.SaveProperties;
9 | import org.spongepowered.asm.mixin.Mixin;
10 | import org.spongepowered.asm.mixin.injection.At;
11 | import org.spongepowered.asm.mixin.injection.Inject;
12 | import org.spongepowered.asm.mixin.injection.Redirect;
13 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
14 |
15 | @Mixin(IntegratedServerLoader.class)
16 | public class IntegratedServerLoaderMixin {
17 |
18 | @Redirect(method = "start(Lnet/minecraft/client/gui/screen/Screen;Ljava/lang/String;ZZ)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/SaveProperties;getLifecycle()Lcom/mojang/serialization/Lifecycle;"), require = 1)
19 | private Lifecycle removeAdviceOnLoad(SaveProperties properties) {
20 | Lifecycle original = properties.getLifecycle();
21 | if (original == Lifecycle.stable() || original == Lifecycle.experimental()) {
22 | return Lifecycle.stable();
23 | } else {
24 | return original;
25 | }
26 | }
27 |
28 | @Inject(method = "tryLoad(Lnet/minecraft/client/MinecraftClient;Lnet/minecraft/client/gui/screen/world/CreateWorldScreen;Lcom/mojang/serialization/Lifecycle;Ljava/lang/Runnable;)V", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/MinecraftClient;setScreen(Lnet/minecraft/client/gui/screen/Screen;)V", ordinal = 0), cancellable = true)
29 | private static void removeAdviceOnCreation(MinecraftClient client, CreateWorldScreen parent, Lifecycle lifecycle,
30 | Runnable loader, CallbackInfo ci) {
31 | loader.run();
32 | ci.cancel();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/LeveledCauldronBlockMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.block.BlockState;
4 | import net.minecraft.block.Blocks;
5 | import net.minecraft.block.LeveledCauldronBlock;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.world.World;
8 | import net.minecraft.world.biome.Biome.Precipitation;
9 | import net.minecraft.world.biome.BiomeKeys;
10 | import net.minecraft.world.event.GameEvent;
11 | import org.spongepowered.asm.mixin.Mixin;
12 | import org.spongepowered.asm.mixin.injection.At;
13 | import org.spongepowered.asm.mixin.injection.Inject;
14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
15 |
16 | @Mixin(LeveledCauldronBlock.class)
17 | public class LeveledCauldronBlockMixin {
18 |
19 | @Inject(method = "precipitationTick", at = @At("HEAD"))
20 | public void precipitationTick(BlockState state, World world, BlockPos pos, Precipitation precipitation,
21 | CallbackInfo ci) {
22 | if (world.getBiome(pos).matchesKey(BiomeKeys.BASALT_DELTAS)
23 | && state.getBlock() == Blocks.POWDER_SNOW_CAULDRON) {
24 | BlockState blockState = state.cycle(LeveledCauldronBlock.LEVEL);
25 | world.setBlockState(pos, blockState);
26 | world.emitGameEvent(GameEvent.BLOCK_CHANGE, pos, GameEvent.Emitter.of(blockState));
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/MinecraftServerMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandChunkGenerator;
4 | import dev.dubhe.skyland.SkyLandStructures;
5 | import net.minecraft.server.MinecraftServer;
6 | import net.minecraft.server.world.ServerChunkManager;
7 | import net.minecraft.server.world.ServerWorld;
8 | import net.minecraft.util.math.BlockPos;
9 | import net.minecraft.util.math.ChunkPos;
10 | import net.minecraft.world.gen.chunk.ChunkGenerator;
11 | import net.minecraft.world.level.ServerWorldProperties;
12 | import org.spongepowered.asm.mixin.Mixin;
13 | import org.spongepowered.asm.mixin.injection.At;
14 | import org.spongepowered.asm.mixin.injection.Inject;
15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
16 | import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
17 |
18 | @Mixin(MinecraftServer.class)
19 | public class MinecraftServerMixin {
20 |
21 | @Inject(method = "setupSpawn", locals = LocalCapture.CAPTURE_FAILHARD, at = @At(value = "HEAD"), cancellable = true)
22 | private static void generateSpawnPlatform(ServerWorld world, ServerWorldProperties worldProperties,
23 | boolean bonusChest, boolean debugWorld, CallbackInfo ci) {
24 | ServerChunkManager chunkManager = world.getChunkManager();
25 | ChunkGenerator chunkGenerator = chunkManager.getChunkGenerator();
26 | if (!(chunkGenerator instanceof SkyLandChunkGenerator)) {
27 | return;
28 | }
29 |
30 | ChunkPos chunkPos = new ChunkPos(chunkManager.getNoiseConfig().getMultiNoiseSampler().findBestSpawnPosition());
31 | int spawnHeight = chunkGenerator.getSpawnHeight(world);
32 | BlockPos worldSpawn = chunkPos.getStartPos().add(8, spawnHeight, 8);
33 | worldProperties.setSpawnPos(worldSpawn, 0.0f);
34 |
35 | new SkyLandStructures.SpawnPlatform(worldSpawn).generate(world, world.random);
36 |
37 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(1024, 0, 0));
38 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(-1024, 0, 0));
39 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(0, 0, 1024));
40 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(0, 0, -1024));
41 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(724, 0, 724));
42 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(724, 0, -724));
43 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(-724, 0, 724));
44 | new SkyLandStructures.TheEndPortal(worldSpawn).generate(world, world.random, new BlockPos(-724, 0, -724));
45 |
46 | ci.cancel();
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/PatrolSpawnerMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandGamerules;
4 | import net.minecraft.entity.player.PlayerEntity;
5 | import net.minecraft.server.world.ServerWorld;
6 | import net.minecraft.tag.BiomeTags;
7 | import net.minecraft.util.math.BlockPos;
8 | import net.minecraft.util.math.random.Random;
9 | import net.minecraft.util.registry.RegistryEntry;
10 | import net.minecraft.world.Heightmap;
11 | import net.minecraft.world.biome.Biome;
12 | import net.minecraft.world.spawner.PatrolSpawner;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.Shadow;
15 | import org.spongepowered.asm.mixin.injection.At;
16 | import org.spongepowered.asm.mixin.injection.Inject;
17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
18 |
19 | @Mixin(PatrolSpawner.class)
20 | public abstract class PatrolSpawnerMixin {
21 |
22 | @Inject(method = "spawn",
23 | at = @At(
24 | value = "INVOKE",
25 | target = "Lnet/minecraft/server/world/ServerWorld;getBiome(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/util/registry/RegistryEntry;",
26 | shift = At.Shift.AFTER
27 | ),
28 | cancellable = true
29 | )
30 | private void atSpawn(ServerWorld world, boolean spawnMonsters, boolean spawnAnimals,
31 | CallbackInfoReturnable cir) {
32 | if (world.getGameRules().getBoolean(SkyLandGamerules.NETHER_PATROL)) {
33 | Random random = world.random;
34 | int i = world.getPlayers().size();
35 | PlayerEntity playerEntity = world.getPlayers().get(random.nextInt(i));
36 | int j = (24 + random.nextInt(24)) * (random.nextBoolean() ? -1 : 1);
37 | int k = (24 + random.nextInt(24)) * (random.nextBoolean() ? -1 : 1);
38 | BlockPos.Mutable mutable = playerEntity.getBlockPos().mutableCopy().move(j, 0, k);
39 | RegistryEntry registryEntry = world.getBiome(mutable);
40 | if (registryEntry.isIn(BiomeTags.IS_NETHER)) {
41 | int n = 0;
42 | int o = (int) Math.ceil(world.getLocalDifficulty(mutable).getLocalDifficulty()) + 1;
43 | for (int p = 0; p < o; ++p) {
44 | ++n;
45 | mutable.setY(world.getTopPosition(Heightmap.Type.MOTION_BLOCKING_NO_LEAVES, mutable).getY());
46 | if (p == 0) {
47 | if (!this.spawnPillager(world, mutable, random, true)) {
48 | break;
49 | }
50 | } else {
51 | this.spawnPillager(world, mutable, random, false);
52 | }
53 | mutable.setX(mutable.getX() + random.nextInt(5) - random.nextInt(5));
54 | mutable.setZ(mutable.getZ() + random.nextInt(5) - random.nextInt(5));
55 | }
56 | cir.setReturnValue(n);
57 | }
58 | }
59 | }
60 |
61 | @Shadow
62 | protected abstract boolean spawnPillager(ServerWorld world, BlockPos pos, Random random, boolean captain);
63 | }
64 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/PlayerInventoryMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.entity.player.PlayerInventory;
4 | import net.minecraft.item.ItemStack;
5 | import net.minecraft.util.collection.DefaultedList;
6 | import org.spongepowered.asm.mixin.Final;
7 | import org.spongepowered.asm.mixin.Mixin;
8 | import org.spongepowered.asm.mixin.Shadow;
9 | import org.spongepowered.asm.mixin.injection.At;
10 | import org.spongepowered.asm.mixin.injection.Inject;
11 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
12 |
13 | import java.util.List;
14 |
15 | @Mixin(PlayerInventory.class)
16 | public class PlayerInventoryMixin {
17 |
18 | @Shadow @Final private List> combinedInventory;
19 |
20 | @Inject(method = "dropAll", at = @At("HEAD"))
21 | private void drop(CallbackInfo ci){
22 | for (List list : this.combinedInventory) {
23 | for (int i = 0; i < list.size(); ++i) {
24 | ItemStack itemStack = (ItemStack)list.get(i);
25 | if (itemStack.isEmpty()) continue;
26 | ((PlayerInventory)(Object)this).player.dropItem(itemStack, false, false);
27 | list.set(i, ItemStack.EMPTY);
28 | }
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/SellItemFactoryAccessor.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.item.ItemStack;
4 | import net.minecraft.village.TradeOffers;
5 | import org.spongepowered.asm.mixin.Mixin;
6 | import org.spongepowered.asm.mixin.gen.Accessor;
7 |
8 | @Mixin(TradeOffers.SellItemFactory.class)
9 | public interface SellItemFactoryAccessor {
10 |
11 | @Accessor
12 | ItemStack getSell();
13 | }
14 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/ServerPlayerEntityMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.ComposterCoolDown;
4 | import dev.dubhe.skyland.SkyLandGamerules;
5 | import net.minecraft.block.BlockState;
6 | import net.minecraft.block.Blocks;
7 | import net.minecraft.block.ComposterBlock;
8 | import net.minecraft.item.ItemStack;
9 | import net.minecraft.item.Items;
10 | import net.minecraft.server.MinecraftServer;
11 | import net.minecraft.server.network.ServerPlayerEntity;
12 | import net.minecraft.server.world.ServerWorld;
13 | import net.minecraft.util.WorldSavePath;
14 | import net.minecraft.util.math.BlockPos;
15 | import org.spongepowered.asm.mixin.Final;
16 | import org.spongepowered.asm.mixin.Mixin;
17 | import org.spongepowered.asm.mixin.Shadow;
18 | import org.spongepowered.asm.mixin.injection.At;
19 | import org.spongepowered.asm.mixin.injection.Inject;
20 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
21 |
22 | import java.io.File;
23 | import java.io.IOException;
24 |
25 | @Mixin(ServerPlayerEntity.class)
26 | public abstract class ServerPlayerEntityMixin {
27 |
28 |
29 | @Shadow
30 | @Final
31 | public MinecraftServer server;
32 |
33 | @Inject(method = "onSpawn", at = @At("HEAD"))
34 | private void spawn(CallbackInfo ci) {
35 | File ojng = server.getSavePath(WorldSavePath.ROOT).resolve("skyland.ojng").toFile();
36 | if (!ojng.isFile()) {
37 | ((ServerPlayerEntity) (Object) this).giveItemStack(new ItemStack(Items.BONE_MEAL, 32));
38 | try {
39 | ojng.createNewFile();
40 | } catch (IOException e) {
41 | e.printStackTrace();
42 | }
43 | }
44 | }
45 |
46 | @Inject(method = "tick()V", at = @At("RETURN"))
47 | private void tick(CallbackInfo ci) {
48 |
49 | ServerPlayerEntity player = (ServerPlayerEntity) (Object) this;
50 | ServerWorld world = player.getWorld();
51 |
52 | if (!world.getGameRules().getBoolean(SkyLandGamerules.COMPOSTER_BONE_MEAL)) {
53 | return;
54 | }
55 |
56 | if ((ComposterCoolDown.cool_down == 0)) {
57 | if (player.isSneaking()) {
58 | if (!ComposterCoolDown.last_is_sneaking) {
59 | ComposterCoolDown.last_is_sneaking = true;
60 |
61 | BlockPos pos = player.getBlockPos();
62 |
63 | BlockState state = world.getBlockState(pos);
64 |
65 | if (state.getBlock() == Blocks.COMPOSTER) {
66 | int level = state.get(ComposterBlock.LEVEL);
67 | if (level < 7) {
68 | int new_level = level + 1;
69 | BlockState blockState = state.with(ComposterBlock.LEVEL, new_level);
70 | world.setBlockState(pos, blockState);
71 | if (player.getRandom().nextFloat() < 0.3) {
72 | player.getHungerManager().add(-1, -1);
73 | }
74 | if (new_level == 7) {
75 | world.createAndScheduleBlockTick(pos, blockState.getBlock(), 20);
76 | }
77 | ComposterCoolDown.cool_down = ComposterCoolDown.MAX_COOL_DOWN;
78 | }
79 | }
80 | }
81 | } else {
82 | ComposterCoolDown.last_is_sneaking = false;
83 | }
84 | }
85 | if (ComposterCoolDown.cool_down > 0) {
86 | ComposterCoolDown.cool_down = ComposterCoolDown.cool_down - 1;
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/ServerWorldMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.block.BlockState;
4 | import net.minecraft.block.Blocks;
5 | import net.minecraft.server.world.ServerWorld;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.ChunkPos;
8 | import net.minecraft.util.registry.RegistryEntry;
9 | import net.minecraft.world.Heightmap;
10 | import net.minecraft.world.biome.Biome;
11 | import net.minecraft.world.biome.BiomeKeys;
12 | import net.minecraft.world.chunk.WorldChunk;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.injection.At;
15 | import org.spongepowered.asm.mixin.injection.Inject;
16 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
17 |
18 | @Mixin(ServerWorld.class)
19 | public class ServerWorldMixin {
20 |
21 | @Inject(method = "tickChunk", at = @At("HEAD"))
22 | private void tickChunk(WorldChunk chunk, int randomTickSpeed, CallbackInfo ci) {
23 | BlockPos blockPos;
24 | ChunkPos chunkPos = chunk.getPos();
25 | int i = chunkPos.getStartX();
26 | int j = chunkPos.getStartZ();
27 | if (((ServerWorld) (Object) this).random.nextInt(64) == 0) {
28 | blockPos = ((ServerWorld) (Object) this).getTopPosition(Heightmap.Type.MOTION_BLOCKING,
29 | ((ServerWorld) (Object) this).getRandomPosInChunk(i, 0, j, 15));
30 | BlockPos blockPos2 = blockPos.down();
31 | RegistryEntry biome = ((ServerWorld) (Object) this).getBiome(blockPos);
32 | if (biome.matchesId(BiomeKeys.BASALT_DELTAS.getValue())) {
33 | BlockState blockState = ((ServerWorld) (Object) this).getBlockState(blockPos2);
34 | if(blockState.getBlock() == Blocks.CAULDRON || blockState.getBlock() == Blocks.POWDER_SNOW_CAULDRON){
35 | Biome.Precipitation precipitation = biome.value().getPrecipitation();
36 | blockState.getBlock()
37 | .precipitationTick(blockState, ((ServerWorld) (Object) this), blockPos2, precipitation);
38 | }
39 | }
40 | }
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/SlimeEntityMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.entity.EntityType;
4 | import net.minecraft.entity.SpawnReason;
5 | import net.minecraft.entity.mob.SlimeEntity;
6 | import net.minecraft.util.Identifier;
7 | import net.minecraft.util.math.BlockPos;
8 | import net.minecraft.util.math.random.Random;
9 | import net.minecraft.world.Difficulty;
10 | import net.minecraft.world.WorldAccess;
11 | import org.spongepowered.asm.mixin.Mixin;
12 | import org.spongepowered.asm.mixin.injection.At;
13 | import org.spongepowered.asm.mixin.injection.Inject;
14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
15 |
16 | @Mixin(SlimeEntity.class)
17 | public class SlimeEntityMixin {
18 |
19 | private static final Identifier BASALT_DELTAS = new Identifier("basalt_deltas");
20 |
21 | @Inject(method = "canSpawn(Lnet/minecraft/entity/EntityType;Lnet/minecraft/world/WorldAccess;Lnet/minecraft/entity/SpawnReason;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/random/Random;)Z", at = @At("RETURN"), cancellable = true)
22 | private static void canSpawnMixin(EntityType type, WorldAccess world, SpawnReason spawnReason,
23 | BlockPos pos, Random random, CallbackInfoReturnable cir) {
24 | if (cir.getReturnValue()) {
25 | return;
26 | }
27 | if (world.getDifficulty() != Difficulty.PEACEFUL) {
28 | if (world.getBiome(pos).matchesId(SlimeEntityMixin.BASALT_DELTAS)) {
29 | cir.setReturnValue(true);
30 | }
31 | }
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/SnowGolemEntityMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 |
4 | import dev.dubhe.skyland.SkyLandGamerules;
5 | import net.minecraft.block.BlockState;
6 | import net.minecraft.block.Blocks;
7 | import net.minecraft.entity.passive.SnowGolemEntity;
8 | import net.minecraft.util.math.BlockPos;
9 | import net.minecraft.util.math.MathHelper;
10 | import net.minecraft.world.World;
11 | import org.spongepowered.asm.mixin.Mixin;
12 | import org.spongepowered.asm.mixin.injection.At;
13 | import org.spongepowered.asm.mixin.injection.Inject;
14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
15 |
16 | @Mixin(SnowGolemEntity.class)
17 | public class SnowGolemEntityMixin {
18 |
19 | @Inject(method = "tickMovement()V", at = @At(value = "INVOKE", target = "Lnet/minecraft/block/Block;getDefaultState()Lnet/minecraft/block/BlockState;"))
20 | private void setIce(CallbackInfo ci) {
21 | World world = ((SnowGolemEntity) (Object) this).world;
22 | BlockState iceState = Blocks.ICE.getDefaultState();
23 | if (world.getGameRules().getBoolean(SkyLandGamerules.ICE_GOLEM)) {
24 | for (int l = 0; l < 4; ++l) {
25 | int i = MathHelper.floor(
26 | ((SnowGolemEntity) (Object) this).getX() + (double) ((float) (l % 2 * 2 - 1) * 0.25F));
27 | int j = MathHelper.floor(((SnowGolemEntity) (Object) this).getY());
28 | int k = MathHelper.floor(
29 | ((SnowGolemEntity) (Object) this).getZ() + (double) ((float) (l / 2 % 2 * 2 - 1) * 0.25F));
30 | BlockPos icePos = new BlockPos(i, j - 1, k);
31 | BlockState state = world.getBlockState(icePos);
32 | if (state.isOf(Blocks.WATER) && state.getFluidState().isStill() && iceState.canPlaceAt(world, icePos)) {
33 | world.setBlockState(icePos, iceState);
34 | }
35 | }
36 | }
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/SpawnHelperMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandGamerules;
4 | import net.minecraft.entity.SpawnGroup;
5 | import net.minecraft.server.world.ServerWorld;
6 | import net.minecraft.util.math.BlockPos;
7 | import net.minecraft.util.math.ChunkPos;
8 | import net.minecraft.world.SpawnHelper;
9 | import net.minecraft.world.World;
10 | import net.minecraft.world.chunk.Chunk;
11 | import net.minecraft.world.chunk.ChunkSection;
12 | import net.minecraft.world.chunk.WorldChunk;
13 | import org.spongepowered.asm.mixin.Mixin;
14 | import org.spongepowered.asm.mixin.Shadow;
15 | import org.spongepowered.asm.mixin.injection.At;
16 | import org.spongepowered.asm.mixin.injection.Inject;
17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
18 |
19 | @Mixin(SpawnHelper.class)
20 | public class SpawnHelperMixin {
21 |
22 | @Shadow
23 | public static void spawnEntitiesInChunk(SpawnGroup group, ServerWorld world, Chunk chunk, BlockPos pos,
24 | SpawnHelper.Checker checker, SpawnHelper.Runner runner) {
25 | }
26 |
27 | @Inject(method = "spawnEntitiesInChunk(Lnet/minecraft/entity/SpawnGroup;Lnet/minecraft/server/world/ServerWorld;Lnet/minecraft/world/chunk/WorldChunk;Lnet/minecraft/world/SpawnHelper$Checker;Lnet/minecraft/world/SpawnHelper$Runner;)V", at = @At("HEAD"), cancellable = true)
28 | private static void spawnEntities(SpawnGroup group, ServerWorld world, WorldChunk chunk,
29 | SpawnHelper.Checker checker, SpawnHelper.Runner runner, CallbackInfo ci) {
30 | if (world.getGameRules().getBoolean(SkyLandGamerules.LC)) {
31 | for (int i = chunk.getBottomY(); i < chunk.getTopY(); i += 16) {
32 | ChunkSection chunkSection = chunk.getSectionArray()[chunk.getSectionIndex(i)];
33 | if (chunkSection != null && !chunkSection.isEmpty()) {
34 | BlockPos blockPos = getRandomPosInChunk(world, chunk).add(0, i, 0);
35 | spawnEntitiesInChunk(group, world, chunk, blockPos, checker, runner);
36 | }
37 | }
38 | ci.cancel();
39 | }
40 | }
41 |
42 | private static BlockPos getRandomPosInChunk(World world, WorldChunk chunk) {
43 | ChunkPos chunkPos = chunk.getPos();
44 | int x = chunkPos.getStartX() + world.random.nextInt(16);
45 | int z = chunkPos.getStartZ() + world.random.nextInt(16);
46 | int y = world.random.nextInt(16) + 1;
47 | return new BlockPos(x, y, z);
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/TheEndBiomeCreatorMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.entity.EntityType;
4 | import net.minecraft.entity.SpawnGroup;
5 | import net.minecraft.sound.BiomeMoodSound;
6 | import net.minecraft.world.biome.Biome;
7 | import net.minecraft.world.biome.BiomeEffects;
8 | import net.minecraft.world.biome.GenerationSettings.Builder;
9 | import net.minecraft.world.biome.SpawnSettings;
10 | import net.minecraft.world.biome.TheEndBiomeCreator;
11 | import net.minecraft.world.gen.feature.DefaultBiomeFeatures;
12 | import org.spongepowered.asm.mixin.Mixin;
13 | import org.spongepowered.asm.mixin.injection.At;
14 | import org.spongepowered.asm.mixin.injection.Inject;
15 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
16 |
17 | @Mixin(TheEndBiomeCreator.class)
18 | public class TheEndBiomeCreatorMixin {
19 |
20 | @Inject(method = "createEndBiome", at = @At("HEAD"), cancellable = true)
21 | private static void createEndBiome(Builder builder, CallbackInfoReturnable cir) {
22 | SpawnSettings.Builder builder2 = new SpawnSettings.Builder();
23 | builder2.spawn(
24 | SpawnGroup.WATER_CREATURE,
25 | new SpawnSettings.SpawnEntry(EntityType.SQUID, 2, 1, 4)
26 | );
27 | DefaultBiomeFeatures.addEndMobs(builder2);
28 | Biome biome = new Biome.Builder()
29 | .precipitation(Biome.Precipitation.NONE)
30 | .temperature(0.5f)
31 | .downfall(0.5f)
32 | .effects(
33 | new BiomeEffects.Builder()
34 | .waterColor(4159204)
35 | .waterFogColor(329011)
36 | .fogColor(0xA080A0)
37 | .skyColor(0)
38 | .moodSound(BiomeMoodSound.CAVE)
39 | .build()
40 | )
41 | .spawnSettings(builder2.build())
42 | .generationSettings(builder.build()).build();
43 | cir.setReturnValue(biome);
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/TheNetherBiomeCreatorMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.client.sound.MusicType;
4 | import net.minecraft.entity.EntityType;
5 | import net.minecraft.entity.SpawnGroup;
6 | import net.minecraft.particle.ParticleTypes;
7 | import net.minecraft.sound.BiomeAdditionsSound;
8 | import net.minecraft.sound.BiomeMoodSound;
9 | import net.minecraft.sound.SoundEvents;
10 | import net.minecraft.util.math.MathHelper;
11 | import net.minecraft.world.biome.Biome;
12 | import net.minecraft.world.biome.BiomeEffects;
13 | import net.minecraft.world.biome.BiomeParticleConfig;
14 | import net.minecraft.world.biome.GenerationSettings;
15 | import net.minecraft.world.biome.SpawnSettings;
16 | import net.minecraft.world.biome.TheNetherBiomeCreator;
17 | import net.minecraft.world.gen.GenerationStep;
18 | import net.minecraft.world.gen.carver.ConfiguredCarvers;
19 | import net.minecraft.world.gen.feature.DefaultBiomeFeatures;
20 | import net.minecraft.world.gen.feature.MiscPlacedFeatures;
21 | import net.minecraft.world.gen.feature.NetherPlacedFeatures;
22 | import net.minecraft.world.gen.feature.OrePlacedFeatures;
23 | import net.minecraft.world.gen.feature.VegetationPlacedFeatures;
24 | import org.spongepowered.asm.mixin.Mixin;
25 | import org.spongepowered.asm.mixin.injection.At;
26 | import org.spongepowered.asm.mixin.injection.Inject;
27 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
28 |
29 | @Mixin(TheNetherBiomeCreator.class)
30 | public class TheNetherBiomeCreatorMixin {
31 |
32 | @Inject(method = "createSoulSandValley", at = @At("HEAD"), cancellable = true)
33 | private static void createSoulSandValley(CallbackInfoReturnable cir) {
34 | SpawnSettings spawnSettings = new SpawnSettings.Builder()
35 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.SKELETON, 20, 5, 5))
36 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.GHAST, 50, 4, 4))
37 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.ENDERMAN, 1, 4, 4))
38 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.STRIDER, 60, 1, 2))
39 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.WITCH, 1, 1, 1))
40 | .spawnCost(EntityType.SKELETON, 0.7, 0.15)
41 | .spawnCost(EntityType.GHAST, 0.7, 0.15)
42 | .spawnCost(EntityType.ENDERMAN, 0.7, 0.15)
43 | .spawnCost(EntityType.STRIDER, 0.7, 0.15)
44 | .spawnCost(EntityType.WITCH, 0.7, 0.15)
45 | .build();
46 | GenerationSettings.Builder builder = new GenerationSettings.Builder()
47 | .carver(GenerationStep.Carver.AIR, ConfiguredCarvers.NETHER_CAVE)
48 | .feature(GenerationStep.Feature.VEGETAL_DECORATION, MiscPlacedFeatures.SPRING_LAVA)
49 | .feature(GenerationStep.Feature.LOCAL_MODIFICATIONS, NetherPlacedFeatures.BASALT_PILLAR)
50 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.SPRING_OPEN)
51 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.PATCH_FIRE)
52 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.PATCH_SOUL_FIRE)
53 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.GLOWSTONE_EXTRA)
54 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.GLOWSTONE)
55 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.PATCH_CRIMSON_ROOTS)
56 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, OrePlacedFeatures.ORE_MAGMA)
57 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.SPRING_CLOSED)
58 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, OrePlacedFeatures.ORE_SOUL_SAND);
59 | DefaultBiomeFeatures.addNetherMineables(builder);
60 | cir.setReturnValue(
61 | new Biome.Builder()
62 | .precipitation(Biome.Precipitation.NONE)
63 | .temperature(2.0f).downfall(0.0f)
64 | .effects(new BiomeEffects.Builder()
65 | .waterColor(4159204)
66 | .waterFogColor(329011)
67 | .fogColor(1787717)
68 | .skyColor(getSkyColor())
69 | .particleConfig(new BiomeParticleConfig(ParticleTypes.ASH, 0.00625f))
70 | .loopSound(SoundEvents.AMBIENT_SOUL_SAND_VALLEY_LOOP)
71 | .moodSound(new BiomeMoodSound(SoundEvents.AMBIENT_SOUL_SAND_VALLEY_MOOD, 6000, 8, 2.0))
72 | .additionsSound(new BiomeAdditionsSound(SoundEvents.AMBIENT_SOUL_SAND_VALLEY_ADDITIONS, 0.0111))
73 | .music(MusicType.createIngameMusic(SoundEvents.MUSIC_NETHER_SOUL_SAND_VALLEY))
74 | .build())
75 | .spawnSettings(spawnSettings)
76 | .generationSettings(builder.build())
77 | .build()
78 | );
79 |
80 | }
81 |
82 | @Inject(method = "createBasaltDeltas", at = @At("HEAD"), cancellable = true)
83 | private static void createBasaltDeltas(CallbackInfoReturnable cir) {
84 | SpawnSettings spawnSettings = new SpawnSettings.Builder()
85 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.GHAST, 40, 1, 1))
86 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.MAGMA_CUBE, 100, 2, 5))
87 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.STRIDER, 60, 1, 2))
88 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.SLIME, 10, 2, 5))
89 | .build();
90 | GenerationSettings.Builder builder = new GenerationSettings.Builder()
91 | .carver(GenerationStep.Carver.AIR, ConfiguredCarvers.NETHER_CAVE)
92 | .feature(GenerationStep.Feature.SURFACE_STRUCTURES, NetherPlacedFeatures.DELTA)
93 | .feature(GenerationStep.Feature.SURFACE_STRUCTURES, NetherPlacedFeatures.SMALL_BASALT_COLUMNS)
94 | .feature(GenerationStep.Feature.SURFACE_STRUCTURES, NetherPlacedFeatures.LARGE_BASALT_COLUMNS)
95 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.BASALT_BLOBS)
96 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.BLACKSTONE_BLOBS)
97 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.SPRING_DELTA)
98 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.PATCH_FIRE)
99 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.PATCH_SOUL_FIRE)
100 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.GLOWSTONE_EXTRA)
101 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.GLOWSTONE)
102 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, VegetationPlacedFeatures.BROWN_MUSHROOM_NETHER)
103 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, VegetationPlacedFeatures.RED_MUSHROOM_NETHER)
104 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, OrePlacedFeatures.ORE_MAGMA)
105 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.SPRING_CLOSED_DOUBLE)
106 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, OrePlacedFeatures.ORE_GOLD_DELTAS)
107 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, OrePlacedFeatures.ORE_QUARTZ_DELTAS);
108 | DefaultBiomeFeatures.addAncientDebris(builder);
109 | cir.setReturnValue(
110 | new Biome.Builder()
111 | .precipitation(Biome.Precipitation.NONE)
112 | .temperature(2.0f)
113 | .downfall(0.0f)
114 | .effects(new BiomeEffects.Builder()
115 | .waterColor(4159204)
116 | .waterFogColor(329011)
117 | .fogColor(6840176)
118 | .skyColor(getSkyColor())
119 | .particleConfig(new BiomeParticleConfig(ParticleTypes.WHITE_ASH, 0.118093334f))
120 | .loopSound(SoundEvents.AMBIENT_BASALT_DELTAS_LOOP)
121 | .moodSound(new BiomeMoodSound(SoundEvents.AMBIENT_BASALT_DELTAS_MOOD, 6000, 8, 2.0))
122 | .additionsSound(new BiomeAdditionsSound(SoundEvents.AMBIENT_BASALT_DELTAS_ADDITIONS, 0.0111))
123 | .music(MusicType.createIngameMusic(SoundEvents.MUSIC_NETHER_BASALT_DELTAS)).build())
124 | .spawnSettings(spawnSettings)
125 | .generationSettings(builder.build())
126 | .build()
127 | );
128 | }
129 |
130 | @Inject(method = "createNetherWastes", at = @At("HEAD"), cancellable = true)
131 | private static void createNetherWastes(CallbackInfoReturnable cir){
132 | SpawnSettings spawnSettings = new SpawnSettings.Builder()
133 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.GHAST, 50, 4, 4))
134 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.ZOMBIFIED_PIGLIN, 100, 4, 4))
135 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.MAGMA_CUBE, 2, 4, 4))
136 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.ENDERMAN, 1, 4, 4))
137 | .spawn(SpawnGroup.MONSTER, new SpawnSettings.SpawnEntry(EntityType.PIGLIN, 15, 4, 4))
138 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.STRIDER, 60, 1, 2))
139 |
140 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.WOLF, 20, 4, 4))
141 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.COW, 20, 2, 4))
142 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.SHEEP, 20, 2, 4))
143 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.LLAMA, 20, 4, 6))
144 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.HORSE, 20, 2, 6))
145 | .spawn(SpawnGroup.CREATURE, new SpawnSettings.SpawnEntry(EntityType.DONKEY, 20, 1, 2))
146 |
147 | .build();
148 | GenerationSettings.Builder builder = new GenerationSettings.Builder()
149 | .carver(GenerationStep.Carver.AIR, ConfiguredCarvers.NETHER_CAVE)
150 | .feature(GenerationStep.Feature.VEGETAL_DECORATION, MiscPlacedFeatures.SPRING_LAVA);
151 | DefaultBiomeFeatures.addDefaultMushrooms(builder);
152 | builder
153 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.SPRING_OPEN)
154 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.PATCH_FIRE)
155 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.PATCH_SOUL_FIRE)
156 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.GLOWSTONE_EXTRA)
157 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.GLOWSTONE)
158 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, VegetationPlacedFeatures.BROWN_MUSHROOM_NETHER)
159 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, VegetationPlacedFeatures.RED_MUSHROOM_NETHER)
160 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, OrePlacedFeatures.ORE_MAGMA)
161 | .feature(GenerationStep.Feature.UNDERGROUND_DECORATION, NetherPlacedFeatures.SPRING_CLOSED);
162 | DefaultBiomeFeatures.addNetherMineables(builder);
163 | cir.setReturnValue(
164 | new Biome.Builder()
165 | .precipitation(Biome.Precipitation.NONE)
166 | .temperature(2.0f)
167 | .downfall(0.0f)
168 | .effects(new BiomeEffects.Builder()
169 | .waterColor(4159204)
170 | .waterFogColor(329011)
171 | .fogColor(0x330808)
172 | .skyColor(getSkyColor())
173 | .loopSound(SoundEvents.AMBIENT_NETHER_WASTES_LOOP)
174 | .moodSound(new BiomeMoodSound(SoundEvents.AMBIENT_NETHER_WASTES_MOOD, 6000, 8, 2.0))
175 | .additionsSound(new BiomeAdditionsSound(SoundEvents.AMBIENT_NETHER_WASTES_ADDITIONS, 0.0111))
176 | .music(MusicType.createIngameMusic(SoundEvents.MUSIC_NETHER_NETHER_WASTES)).build())
177 | .spawnSettings(spawnSettings)
178 | .generationSettings(builder.build())
179 | .build()
180 | );
181 | }
182 |
183 | private static int getSkyColor() {
184 | float temperature = MathHelper.clamp(2.0f / 3.0f, -1.0f, 1.0f);
185 | return MathHelper.hsvToRgb(0.62222224f - temperature * 0.05f, 0.5f + temperature * 0.1f, 1.0f);
186 | }
187 |
188 | }
189 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/WanderingTraderManagerMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandGamerules;
4 | import net.minecraft.block.BlockState;
5 | import net.minecraft.entity.EntityType;
6 | import net.minecraft.entity.SpawnReason;
7 | import net.minecraft.entity.passive.StriderEntity;
8 | import net.minecraft.entity.passive.WanderingTraderEntity;
9 | import net.minecraft.fluid.Fluids;
10 | import net.minecraft.server.network.ServerPlayerEntity;
11 | import net.minecraft.server.world.ServerWorld;
12 | import net.minecraft.tag.BiomeTags;
13 | import net.minecraft.util.math.BlockPos;
14 | import net.minecraft.util.math.random.Random;
15 | import net.minecraft.world.BlockView;
16 | import net.minecraft.world.Heightmap.Type;
17 | import net.minecraft.world.WanderingTraderManager;
18 | import net.minecraft.world.level.ServerWorldProperties;
19 | import net.minecraft.world.poi.PointOfInterestStorage;
20 | import net.minecraft.world.poi.PointOfInterestTypes;
21 | import org.jetbrains.annotations.Nullable;
22 | import org.spongepowered.asm.mixin.Final;
23 | import org.spongepowered.asm.mixin.Mixin;
24 | import org.spongepowered.asm.mixin.Shadow;
25 | import org.spongepowered.asm.mixin.injection.At;
26 | import org.spongepowered.asm.mixin.injection.Inject;
27 | import org.spongepowered.asm.mixin.injection.Redirect;
28 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
29 |
30 | import java.util.Optional;
31 |
32 | @Mixin(WanderingTraderManager.class)
33 | public abstract class WanderingTraderManagerMixin {
34 |
35 | @Shadow
36 | @Final
37 | private Random random;
38 |
39 | @Shadow
40 | @Final
41 | private ServerWorldProperties properties;
42 |
43 | @Redirect(method = "trySpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/random/Random;nextInt(I)I"))
44 | private int spawnX10(Random random, int value, ServerWorld world) {
45 | return world.getGameRules().getBoolean(SkyLandGamerules.CHIEFTAIN) ? 0 : random.nextInt(value);
46 | }
47 |
48 | @Inject(method = "trySpawn", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/world/ServerWorld;getRandomAlivePlayer()Lnet/minecraft/server/network/ServerPlayerEntity;", shift = At.Shift.AFTER), cancellable = true)
49 | private void spawn(ServerWorld world, CallbackInfoReturnable cir) {
50 | if (world.getGameRules().getBoolean(SkyLandGamerules.NETHER_TRADER)) {
51 | ServerPlayerEntity playerEntity = world.getRandomAlivePlayer();
52 | if (!world.getGameRules().getBoolean(SkyLandGamerules.CHIEFTAIN) && this.random.nextFloat() >= 0.1) {
53 | cir.setReturnValue(false);
54 | }
55 | if (playerEntity != null) {
56 | BlockPos blockPos = playerEntity.getBlockPos();
57 | PointOfInterestStorage pointOfInterestStorage = world.getPointOfInterestStorage();
58 | Optional optional = pointOfInterestStorage.getPosition(
59 | registryEntry -> registryEntry.matchesKey(PointOfInterestTypes.MEETING), pos -> true, blockPos,
60 | 48, PointOfInterestStorage.OccupationStatus.ANY);
61 | BlockPos blockPos2 = optional.orElse(blockPos);
62 | BlockPos blockPos3 = this.getNearbySpawnPos(world, blockPos2);
63 | if (blockPos3 != null && this.doesNotSuffocateAt(world, blockPos3)) {
64 | if (world.getBiome(blockPos3).isIn(BiomeTags.IS_NETHER)) {
65 | StriderEntity striderEntity = EntityType.STRIDER.spawn(world, null, null, null, blockPos3,
66 | SpawnReason.EVENT, false, false);
67 | WanderingTraderEntity wanderingTraderEntity = EntityType.WANDERING_TRADER.spawn(world, null,
68 | null, null, blockPos3, SpawnReason.EVENT, false, false);
69 | if (wanderingTraderEntity != null) {
70 | if (striderEntity != null) {
71 | striderEntity.saddle(null);
72 | wanderingTraderEntity.startRiding(striderEntity, true);
73 | }
74 | properties.setWanderingTraderId(wanderingTraderEntity.getUuid());
75 | wanderingTraderEntity.setDespawnDelay(48000);
76 | wanderingTraderEntity.setWanderTarget(blockPos2);
77 | wanderingTraderEntity.setPositionTarget(blockPos2, 16);
78 | cir.setReturnValue(true);
79 | }
80 | }
81 | }
82 | }
83 | }
84 | }
85 |
86 | @Nullable
87 | private BlockPos getNearbySpawnPos(ServerWorld world, BlockPos pos) {
88 | BlockPos blockPos = null;
89 |
90 | for (int i = 0; i < 10; ++i) {
91 | int j = pos.getX() + this.random.nextInt(48 * 2) - 48;
92 | int k = pos.getZ() + this.random.nextInt(48 * 2) - 48;
93 | int l = world.getTopY(Type.WORLD_SURFACE, j, k);
94 | BlockPos blockPos2 = new BlockPos(j, l, k);
95 | BlockPos blockPos3 = new BlockPos(j, l - 1, k);
96 | BlockState blockState = world.getBlockState(blockPos3);
97 | if (blockState.getFluidState().isOf(Fluids.LAVA) && blockState.getFluidState().isStill()) {
98 | blockPos = blockPos2;
99 | break;
100 | }
101 | }
102 |
103 | return blockPos;
104 | }
105 |
106 | @Shadow
107 | protected abstract boolean doesNotSuffocateAt(BlockView world, BlockPos pos);
108 | }
109 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/WaterCreatureEntityMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import net.minecraft.block.Blocks;
4 | import net.minecraft.entity.EntityType;
5 | import net.minecraft.entity.SpawnReason;
6 | import net.minecraft.entity.mob.WaterCreatureEntity;
7 | import net.minecraft.tag.FluidTags;
8 | import net.minecraft.util.math.BlockPos;
9 | import net.minecraft.util.math.random.Random;
10 | import net.minecraft.world.WorldAccess;
11 | import org.spongepowered.asm.mixin.Mixin;
12 | import org.spongepowered.asm.mixin.injection.At;
13 | import org.spongepowered.asm.mixin.injection.Inject;
14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
15 |
16 | @Mixin(WaterCreatureEntity.class)
17 | public class WaterCreatureEntityMixin {
18 |
19 | @Inject(method = "canSpawn(Lnet/minecraft/entity/EntityType;Lnet/minecraft/world/WorldAccess;Lnet/minecraft/entity/SpawnReason;Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/math/random/Random;)Z", at = @At("RETURN"), cancellable = true)
20 | private static void canSpawn(EntityType extends WaterCreatureEntity> type, WorldAccess world, SpawnReason reason,
21 | BlockPos pos, Random random, CallbackInfoReturnable cir){
22 | boolean bl = world.getFluidState(pos).isIn(FluidTags.WATER);
23 | while (world.getFluidState(pos).isIn(FluidTags.WATER)){
24 | pos = pos.down();
25 | }
26 | boolean bl2 = world.getBlockState(pos).isOf(Blocks.BRAIN_CORAL_BLOCK) ||
27 | world.getBlockState(pos).isOf(Blocks.BUBBLE_CORAL_BLOCK) ||
28 | world.getBlockState(pos).isOf(Blocks.FIRE_CORAL_BLOCK) ||
29 | world.getBlockState(pos).isOf(Blocks.BUBBLE_CORAL_BLOCK) ||
30 | world.getBlockState(pos).isOf(Blocks.TUBE_CORAL_BLOCK);
31 | cir.setReturnValue(bl && bl2);
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/WorldPresetsRegistrarMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandMod;
4 | import dev.dubhe.skyland.SkyLandChunkGenerator;
5 | import net.minecraft.structure.StructureSet;
6 | import net.minecraft.tag.BlockTags;
7 | import net.minecraft.util.Identifier;
8 | import net.minecraft.util.math.intprovider.ConstantIntProvider;
9 | import net.minecraft.util.math.noise.DoublePerlinNoiseSampler;
10 | import net.minecraft.util.registry.BuiltinRegistries;
11 | import net.minecraft.util.registry.Registry;
12 | import net.minecraft.util.registry.RegistryEntry;
13 | import net.minecraft.util.registry.RegistryKey;
14 | import net.minecraft.world.biome.Biome;
15 | import net.minecraft.world.biome.source.BiomeSource;
16 | import net.minecraft.world.biome.source.MultiNoiseBiomeSource;
17 | import net.minecraft.world.biome.source.TheEndBiomeSource;
18 | import net.minecraft.world.dimension.DimensionOptions;
19 | import net.minecraft.world.dimension.DimensionType;
20 | import net.minecraft.world.gen.WorldPreset;
21 | import net.minecraft.world.gen.chunk.ChunkGeneratorSettings;
22 | import org.spongepowered.asm.mixin.Final;
23 | import org.spongepowered.asm.mixin.Mixin;
24 | import org.spongepowered.asm.mixin.Shadow;
25 | import org.spongepowered.asm.mixin.injection.At;
26 | import org.spongepowered.asm.mixin.injection.Inject;
27 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
28 |
29 | import java.util.Map;
30 | import java.util.OptionalLong;
31 |
32 | @Mixin(targets = "net.minecraft.world.gen.WorldPresets$Registrar")
33 | public class WorldPresetsRegistrarMixin {
34 |
35 | @Final
36 | @Shadow
37 | private Registry worldPresetRegistry;
38 | @Final
39 | @Shadow
40 | private Registry biomeRegistry;
41 | @Final
42 | @Shadow
43 | private Registry structureSetRegistry;
44 | @Final
45 | @Shadow
46 | private Registry chunkGeneratorSettingsRegistry;
47 | @Final
48 | @Shadow
49 | private Registry noiseParametersRegistry;
50 | @Final
51 | @Shadow
52 | private RegistryEntry theNetherDimensionType;
53 | @Final
54 | @Shadow
55 | private Registry dimensionTypeRegistry;
56 | @Final
57 | @Shadow
58 | private RegistryEntry theEndDimensionType;
59 |
60 | private static final DimensionType overNether = new DimensionType(OptionalLong.of(18000L), false, true, true, false,
61 | 1.0, false, true, 0, 256, 128, BlockTags.INFINIBURN_NETHER,
62 | net.minecraft.world.dimension.DimensionTypes.THE_NETHER_ID, 0.1F,
63 | new DimensionType.MonsterSettings(true, true, ConstantIntProvider.create(11), 15));
64 |
65 | private static final RegistryKey OVER_NETHER = RegistryKey.of(Registry.DIMENSION_TYPE_KEY,
66 | new Identifier("over_nether"));
67 |
68 | @Inject(method = "initAndGetDefault", at = @At("RETURN"))
69 | private void register(CallbackInfoReturnable> cir) {
70 | BuiltinRegistries.add(dimensionTypeRegistry, OVER_NETHER, overNether);
71 | DimensionOptions overworld = this.createSkyDimensionOptions(
72 | this.dimensionTypeRegistry.getOrCreateEntry(OVER_NETHER),
73 | MultiNoiseBiomeSource.Preset.NETHER.getBiomeSource(this.biomeRegistry), ChunkGeneratorSettings.NETHER);
74 | DimensionOptions nether = this.createSkyDimensionOptions(this.theNetherDimensionType,
75 | MultiNoiseBiomeSource.Preset.NETHER.getBiomeSource(this.biomeRegistry), ChunkGeneratorSettings.NETHER);
76 | DimensionOptions end = this.createSkyDimensionOptions(this.theEndDimensionType,
77 | new TheEndBiomeSource(this.biomeRegistry), ChunkGeneratorSettings.END);
78 | BuiltinRegistries.add(this.worldPresetRegistry, SkyLandMod.SKYLAND, new WorldPreset(
79 | Map.of(DimensionOptions.OVERWORLD, overworld, DimensionOptions.NETHER, nether, DimensionOptions.END,
80 | end)));
81 | }
82 |
83 | private DimensionOptions createSkyDimensionOptions(RegistryEntry type, BiomeSource biomes,
84 | RegistryKey key) {
85 | return new DimensionOptions(type,
86 | new SkyLandChunkGenerator(this.structureSetRegistry, this.noiseParametersRegistry, biomes,
87 | this.chunkGeneratorSettingsRegistry.getOrCreateEntry(key)));
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/mixin/ZombieEntityMixin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.mixin;
2 |
3 | import dev.dubhe.skyland.SkyLandGamerules;
4 | import net.minecraft.entity.EntityType;
5 | import net.minecraft.entity.LivingEntity;
6 | import net.minecraft.entity.SpawnReason;
7 | import net.minecraft.entity.SpawnRestriction;
8 | import net.minecraft.entity.attribute.EntityAttributeModifier;
9 | import net.minecraft.entity.attribute.EntityAttributes;
10 | import net.minecraft.entity.damage.DamageSource;
11 | import net.minecraft.entity.mob.ZombieEntity;
12 | import net.minecraft.entity.mob.ZombieVillagerEntity;
13 | import net.minecraft.server.world.ServerWorld;
14 | import net.minecraft.util.math.BlockPos;
15 | import net.minecraft.util.math.MathHelper;
16 | import net.minecraft.util.math.random.Random;
17 | import net.minecraft.world.Difficulty;
18 | import net.minecraft.world.GameRules;
19 | import net.minecraft.world.SpawnHelper;
20 | import net.minecraft.world.World;
21 | import org.spongepowered.asm.mixin.Mixin;
22 | import org.spongepowered.asm.mixin.injection.At;
23 | import org.spongepowered.asm.mixin.injection.Inject;
24 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
25 |
26 | import java.util.Objects;
27 |
28 | @Mixin(ZombieEntity.class)
29 | public class ZombieEntityMixin {
30 |
31 | protected final Random random = Random.create();
32 |
33 | @Inject(method = "damage", at = @At(value = "INVOKE", target = "Lnet/minecraft/entity/mob/ZombieEntity;getTarget()Lnet/minecraft/entity/LivingEntity;", shift = At.Shift.AFTER), cancellable = true)
34 | private void zombieVillager(DamageSource source, float amount, CallbackInfoReturnable cir) {
35 | ZombieEntity zombie = (ZombieEntity) (Object) this;
36 | World world = zombie.world;
37 | if (world.getGameRules().getBoolean(SkyLandGamerules.VILLAGER_REINFORCEMENTS)) {
38 | LivingEntity livingEntity = zombie.getTarget();
39 | if (livingEntity == null && source.getAttacker() instanceof LivingEntity) {
40 | livingEntity = (LivingEntity) source.getAttacker();
41 | }
42 | if (livingEntity != null && world.getDifficulty() == Difficulty.HARD && (double) this.random.nextFloat() < (
43 | zombie.getAttributeValue(EntityAttributes.ZOMBIE_SPAWN_REINFORCEMENTS) * 2.0)
44 | && world.getGameRules().getBoolean(GameRules.DO_MOB_SPAWNING)
45 | && world instanceof ServerWorld serverWorld) {
46 | int i = MathHelper.floor(zombie.getX());
47 | int j = MathHelper.floor(zombie.getY());
48 | int k = MathHelper.floor(zombie.getZ());
49 | ZombieVillagerEntity zombieVillager = new ZombieVillagerEntity(EntityType.ZOMBIE_VILLAGER, serverWorld);
50 | for (int l = 0; l < 50; ++l) {
51 | int m = i + MathHelper.nextInt(random, 7, 40) * MathHelper.nextInt(this.random, -1, 1);
52 | int n = j + MathHelper.nextInt(random, 7, 40) * MathHelper.nextInt(this.random, -1, 1);
53 | int o = k + MathHelper.nextInt(random, 7, 40) * MathHelper.nextInt(this.random, -1, 1);
54 | BlockPos blockPos = new BlockPos(m, n, o);
55 | EntityType> entityType = zombieVillager.getType();
56 | SpawnRestriction.Location location = SpawnRestriction.getLocation(entityType);
57 | if (!SpawnHelper.canSpawn(location, world, blockPos, entityType) || !SpawnRestriction.canSpawn(
58 | entityType, serverWorld, SpawnReason.REINFORCEMENT, blockPos, world.random)) {
59 | continue;
60 | }
61 | zombieVillager.setPosition(m, n, o);
62 | if (world.isPlayerInRange(m, n, o, 7.0) || !world.doesNotIntersectEntities(zombieVillager)
63 | || !world.isSpaceEmpty(zombieVillager) || world.containsFluid(
64 | zombieVillager.getBoundingBox())) {
65 | continue;
66 | }
67 | zombieVillager.setTarget(livingEntity);
68 | zombieVillager.initialize(serverWorld, world.getLocalDifficulty(zombieVillager.getBlockPos()),
69 | SpawnReason.REINFORCEMENT, null, null);
70 | serverWorld.spawnEntityAndPassengers(zombieVillager);
71 | Objects.requireNonNull(zombie.getAttributeInstance(EntityAttributes.ZOMBIE_SPAWN_REINFORCEMENTS))
72 | .addPersistentModifier(
73 | new EntityAttributeModifier("Zombie reinforcement caller charge", -0.05f,
74 | EntityAttributeModifier.Operation.ADDITION));
75 | Objects.requireNonNull(
76 | zombieVillager.getAttributeInstance(EntityAttributes.ZOMBIE_SPAWN_REINFORCEMENTS))
77 | .addPersistentModifier(
78 | new EntityAttributeModifier("Zombie reinforcement callee charge", -0.05f,
79 | EntityAttributeModifier.Operation.ADDITION));
80 | break;
81 | }
82 | }
83 | }
84 | cir.setReturnValue(true);
85 | }
86 | }
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/plugin/ComposterCoolDownProvider.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.plugin;
2 |
3 | import dev.dubhe.skyland.ComposterCoolDown;
4 | import dev.dubhe.skyland.SkyLandMod;
5 | import net.minecraft.block.Blocks;
6 | import net.minecraft.text.Text;
7 | import net.minecraft.util.Identifier;
8 | import snownee.jade.api.BlockAccessor;
9 | import snownee.jade.api.IBlockComponentProvider;
10 | import snownee.jade.api.ITooltip;
11 | import snownee.jade.api.config.IPluginConfig;
12 |
13 | public enum ComposterCoolDownProvider implements IBlockComponentProvider {
14 | INSTANCE;
15 |
16 | @Override
17 | public void appendTooltip(ITooltip iTooltip, BlockAccessor blockAccessor, IPluginConfig iPluginConfig) {
18 | if (blockAccessor.getBlock() == Blocks.COMPOSTER) {
19 | if (ComposterCoolDown.cool_down > 0) {
20 | iTooltip.add(Text.translatable("skyland.tooltip.cool_down", ComposterCoolDown.cool_down));
21 | } else {
22 | iTooltip.add(Text.translatable("skyland.tooltip.ready"));
23 | }
24 | }
25 | }
26 |
27 | @Override
28 | public Identifier getUid() {
29 | return new Identifier(SkyLandMod.MOD_ID, "composter_cool_down");
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/java/dev/dubhe/skyland/plugin/ComposterPlugin.java:
--------------------------------------------------------------------------------
1 | package dev.dubhe.skyland.plugin;
2 |
3 | import net.minecraft.block.ComposterBlock;
4 | import snownee.jade.api.IWailaClientRegistration;
5 | import snownee.jade.api.IWailaCommonRegistration;
6 | import snownee.jade.api.IWailaPlugin;
7 |
8 | public class ComposterPlugin implements IWailaPlugin {
9 |
10 | @Override
11 | public void register(IWailaCommonRegistration registration) {
12 | IWailaPlugin.super.register(registration);
13 | }
14 |
15 | @Override
16 | public void registerClient(IWailaClientRegistration registration) {
17 | IWailaPlugin.super.registerClient(registration);
18 | registration.registerBlockComponent(ComposterCoolDownProvider.INSTANCE, ComposterBlock.class);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/src/main/resources/assets/skyland/lang/en_us.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator.skyland.skyland": "SkyLand",
3 | "gamerule.qnmdLC": "qnmdLC",
4 | "gamerule.chieftainMode": "Chieftain Mode",
5 | "gamerule.waterCauldron": "Water Cauldron Turn lava into Obsidian",
6 | "gamerule.netherTrader": "Nether Trader",
7 | "gamerule.iceGolem": "Snow golem can turn water into ice",
8 | "gamerule.anvilHandle": "Anvil Handle",
9 | "gamerule.netherPatrol": "Nether Patrol",
10 | "gamerule.villagerReinforcements": "Villager Reinforcements",
11 | "gamerule.killDragonSpawnShulker": "Kill Dragon Spawn Shulker",
12 | "gamerule.killDragonDropElytra": "Kill Dragon Drop Elytra",
13 | "gamerule.composterBoneMeal": "Squat down in a composter to get bone meal",
14 | "gamerule.memoryFoodLevel": "Memories of satiety before death",
15 | "gamerule.respawnMinFoodLevel": "Minimum satiety after respawn",
16 |
17 | "skyland.command.gamerule_set_succeed": "SkyLand gamerules set to %s succeed",
18 |
19 | "advancement.skyland.ancient_debris.title": "Netherite ingot",
20 | "advancement.skyland.ancient_debris.desc": "When have Hero Of The Village effect, the toolsmith will have a chance to throw Ancient Debris to the player",
21 | "advancement.skyland.bedrock_layer.title": "Bedrock layer",
22 | "advancement.skyland.bedrock_layer.desc": "Increased chance of spawning monsters on low Y platforms",
23 | "advancement.skyland.better_wood.title": "Better wood",
24 | "advancement.skyland.better_wood.desc": "The wandering Trader will ride a strider to have a chance to generate on the lava (the generation mechanism is the same as the vanilla, but requires lava)",
25 | "advancement.skyland.blast_furnace.title": "Blast furnace",
26 | "advancement.skyland.blast_furnace.desc": "Trade from piglins to get what you need to craft a blast furnace",
27 | "advancement.skyland.breed_villagers.title": "Breed villagers",
28 | "advancement.skyland.breed_villagers.desc": "Emeralds obtained from raids buy bread and apples from villagers to breed villagers",
29 | "advancement.skyland.bulk_lava.title": "Lava batching",
30 | "advancement.skyland.bulk_lava.desc": "Basalt can be washed in a cauldron to obtain Dripstone Block, which will drop Pointed Dripstone cones when smashed by an anvil.",
31 | "advancement.skyland.composter.title": "Composter!",
32 | "advancement.skyland.composter.desc": "Compost in a composter to get Bone Meal",
33 | "advancement.skyland.coral_fan.title": "Coral",
34 | "advancement.skyland.coral_fan.desc": "Use bone meal on the side of the coral block to make it grow a coral fan, and use bone meal on the top to grow coral",
35 | "advancement.skyland.elytra.title": "Damaged elytra",
36 | "advancement.skyland.elytra.desc": "When killing an ender dragon, elytra will drop at the location where the dragon died",
37 | "advancement.skyland.gold_ingot.title": "Gold_ingot!",
38 | "advancement.skyland.gold_ingot.desc": "Killing zombified piglin has a chance to get gold nuggets and gold ingots",
39 | "advancement.skyland.ice.title": "Artificial Ice",
40 | "advancement.skyland.ice.desc": "Snow golems standing on water will turn the water under their feet into ice",
41 | "advancement.skyland.kill_wrong.title": "Kill wrong(っ °Д °;)っ",
42 | "advancement.skyland.kill_wrong.desc": "Zombie reinforcements from zombified piglins will spawn zombie villagers",
43 | "advancement.skyland.kill_zombified_piglin.title": "Kill Zombified piglin",
44 | "advancement.skyland.kill_zombified_piglin.desc": "Build a spawning platform to kill Zombified piglin",
45 | "advancement.skyland.lava_bucket.title": "Lava Bucket",
46 | "advancement.skyland.lava_bucket.desc": "When have Hero Of The Village effect, the leatherworker will have a chance to throw Lava Bucket to the player",
47 | "advancement.skyland.netherrack.title": "Netherrack",
48 | "advancement.skyland.netherrack.desc": "Netherrack can be obtained by firing nether wart blocks in a blast furnace",
49 | "advancement.skyland.respawn.title": "Respawn",
50 | "advancement.skyland.respawn.desc": "There is no bed in the nether, can use the respawn anchor to revive",
51 | "advancement.skyland.root.title": "Nether Skyblock",
52 | "advancement.skyland.root.desc": "Start your Nether Skyblock journey\nUse the §b/skyland gamerule true§a command to open the desired rule before starting",
53 | "advancement.skyland.save_villager.title": "Save the villagers",
54 | "advancement.skyland.save_villager.desc": "There is only one apple to save the villagers (be careful to back up the world to avoid saving foolish villagers)",
55 | "advancement.skyland.shulker_box.title": "Shulker Box",
56 | "advancement.skyland.shulker_box.desc": "After killing the resurrected ender dragon, shulkers will spawn above the altar",
57 | "advancement.skyland.slime.title": "Slime",
58 | "advancement.skyland.slime.desc": "Slimes and magma cubes spawn together in the Basalt Delta biome",
59 | "advancement.skyland.the_end.title": "The End?",
60 | "advancement.skyland.the_end.desc": "With the initial platform as the center and a radius of 1024, 8 end portal frames will be generated.",
61 | "advancement.skyland.village_hero.title": "Village hero",
62 | "advancement.skyland.village_hero.desc": "Gain Bad Omen and Hero Of The Village.\nLooting squads spawn inside Blackrock fortress structures",
63 | "advancement.skyland.water.title": "Water source",
64 | "advancement.skyland.water.desc": "Water can be placed in the end",
65 | "advancement.skyland.weakness.title": "Weakness",
66 | "advancement.skyland.weakness.desc": "There is a very low chance for witches to spawn in Soul Sand Valley",
67 | "advancement.skyland.wood.title": "Wood!",
68 | "advancement.skyland.wood.desc": "Use bone meal to ripen Crimson Fungus to obtain wood",
69 |
70 | "skyland.tooltip.cool_down": "Cool down: %d",
71 | "skyland.tooltip.ready": "Ready",
72 | "config.jade.plugin_skyland.composter_cool_down": "Composter cool down"
73 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/skyland/lang/zh_cn.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator.skyland.skyland": "空岛",
3 | "gamerule.qnmdLC": "忽略LC值影响",
4 | "gamerule.chieftainMode": "非酋模式",
5 | "gamerule.waterCauldron": "储水炼药锅将熔岩变为黑曜石",
6 | "gamerule.netherTrader": "下界游商",
7 | "gamerule.iceGolem": "雪傀儡可以将水变为冰",
8 | "gamerule.anvilHandle": "铁砧处理",
9 | "gamerule.netherPatrol": "下界灾厄巡逻队",
10 | "gamerule.villagerReinforcements": "村民增援",
11 | "gamerule.killDragonSpawnShulker": "龙亡贝诞",
12 | "gamerule.killDragonDropElytra": "战龙夺翅",
13 | "gamerule.composterBoneMeal": "在堆肥桶下蹲获得骨粉",
14 | "gamerule.memoryFoodLevel": "记忆死亡前的饱食度",
15 | "gamerule.respawnMinFoodLevel": "重生后的最低饱食度",
16 |
17 | "skyland.command.gamerule_set_succeed": "SkyLand 规则设置到 %s 成功",
18 |
19 | "advancement.skyland.ancient_debris.title": "下界合金",
20 | "advancement.skyland.ancient_debris.desc": "拥有村庄英雄状态效果时,工具匠会有概率丢远古残骸给玩家",
21 | "advancement.skyland.bedrock_layer.title": "基岩层",
22 | "advancement.skyland.bedrock_layer.desc": "在低Y的平台生成怪物的概率提升",
23 | "advancement.skyland.better_wood.title": "更好的木头",
24 | "advancement.skyland.better_wood.desc": "游商会骑着炽足兽在熔岩上生成概率生成(生成机制原版一样,不过需要熔岩)",
25 | "advancement.skyland.blast_furnace.title": "高炉",
26 | "advancement.skyland.blast_furnace.desc": "向猪灵交易获得所需的东西来合成高炉",
27 | "advancement.skyland.breed_villagers.title": "繁殖村民",
28 | "advancement.skyland.breed_villagers.desc": "袭击获得的绿宝石向村民购买面包与苹果来繁殖村民",
29 | "advancement.skyland.bulk_lava.title": "熔岩批量化",
30 | "advancement.skyland.bulk_lava.desc": "玄武岩在炼药锅里洗涤能获得滴水石块,滴水石块被铁砧砸会掉落滴水石锥",
31 | "advancement.skyland.composter.title": "堆肥桶!",
32 | "advancement.skyland.composter.desc": "在堆肥桶中堆肥可以获得骨粉",
33 | "advancement.skyland.coral_fan.title": "珊瑚",
34 | "advancement.skyland.coral_fan.desc": "对着珊瑚块侧面使用骨粉使之生长出珊瑚扇,对其顶面使用骨粉生长出珊瑚",
35 | "advancement.skyland.elytra.title": "损坏的翅膀",
36 | "advancement.skyland.elytra.desc": "击杀末影龙时,鞘翅会在龙死亡的位置掉落",
37 | "advancement.skyland.gold_ingot.title": "金锭!",
38 | "advancement.skyland.gold_ingot.desc": "击杀僵尸猪灵会有概率获得金粒和金锭",
39 | "advancement.skyland.ice.title": "人工冰",
40 | "advancement.skyland.ice.desc": "雪傀儡站在水上会将脚下的水变为冰",
41 | "advancement.skyland.kill_wrong.title": "杀错了(っ °Д °;)っ",
42 | "advancement.skyland.kill_wrong.desc": "僵尸猪灵触发的僵尸增援会生成僵尸村民",
43 | "advancement.skyland.kill_zombified_piglin.title": "击杀僵尸猪灵",
44 | "advancement.skyland.kill_zombified_piglin.desc": "搭建刷怪平台杀死僵尸猪灵",
45 | "advancement.skyland.lava_bucket.title": "熔岩桶",
46 | "advancement.skyland.lava_bucket.desc": "拥有村庄英雄状态效果时,皮匠会有概率丢熔岩桶给玩家",
47 | "advancement.skyland.netherrack.title": "下界岩",
48 | "advancement.skyland.netherrack.desc": "在高炉里烧制下界疣块可以获得下界岩",
49 | "advancement.skyland.respawn.title": "重生",
50 | "advancement.skyland.respawn.desc": "虽然下界不能使用床但是能使用重生锚来重生",
51 | "advancement.skyland.root.title": "Nether Skyblock",
52 | "advancement.skyland.root.desc": "开始你的 Nether Skyblock 之旅\n在开始之前使用 §b/skyland gamerule true§a 命令打开需要的规则",
53 | "advancement.skyland.save_villager.title": "拯救村民",
54 | "advancement.skyland.save_villager.desc": "只有一个苹果来救村民(注意备份存档免救到傻子村民)",
55 | "advancement.skyland.shulker_box.title": "潜影盒",
56 | "advancement.skyland.shulker_box.desc": "击杀复活后的末影龙后,潜影贝会生成在返回传送门上方",
57 | "advancement.skyland.slime.title": "史莱姆",
58 | "advancement.skyland.slime.desc": "在玄武岩三角洲群系史莱姆和岩浆怪会一同生成",
59 | "advancement.skyland.the_end.title": "末地?",
60 | "advancement.skyland.the_end.desc": "在以初始平台为圆心,半径1024,会固定生成8个末地传送门框架",
61 | "advancement.skyland.village_hero.title": "村庄英雄",
62 | "advancement.skyland.village_hero.desc": "获得不祥之兆和村庄英雄。\n在堡垒遗迹结构内会生成劫掠者",
63 | "advancement.skyland.water.title": "水源",
64 | "advancement.skyland.water.desc": "在末地可以放置水出来",
65 | "advancement.skyland.weakness.title": "虚弱",
66 | "advancement.skyland.weakness.desc": "在灵魂沙峡谷会有很低的概率生成女巫",
67 | "advancement.skyland.wood.title": "木头!",
68 | "advancement.skyland.wood.desc": "用骨粉催熟绯红菌获得木头",
69 |
70 | "skyland.tooltip.cool_down": "冷却: %d",
71 | "skyland.tooltip.ready": "就绪",
72 | "config.jade.plugin_skyland.composter_cool_down": "堆肥桶冷却"
73 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/skyland/lang/zh_hk.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator.skyland.skyland": "空島",
3 | "gamerule.qnmdLC": "忽略LC值影響",
4 | "gamerule.chieftainMode": "非酋模式",
5 | "gamerule.waterCauldron": "儲水煉藥鍋將熔岩變爲黑曜石",
6 | "gamerule.netherTrader": "地獄游商",
7 | "gamerule.iceGolem": "雪傀儡可以將水變為冰",
8 | "gamerule.anvilHandle": "鐵砧處理",
9 | "gamerule.netherPatrol": "地獄掠奪者巡邏隊",
10 | "gamerule.villagerReinforcements": "村民增援",
11 | "gamerule.killDragonSpawnShulker": "龍亡貝誕",
12 | "gamerule.killDragonDropElytra": "戰龍奪翅",
13 | "gamerule.composterBoneMeal": "在堆肥桶下蹲獲得骨粉",
14 | "gamerule.memoryFoodLevel": "記憶死亡前的飽食度",
15 | "gamerule.respawnMinFoodLevel": "重生後的最低飽食度",
16 |
17 | "skyland.command.gamerule_set_succeed": "SkyLand 規則設置到 %s 成功",
18 |
19 |
20 | "advancement.skyland.ancient_debris.title": "獄髓",
21 | "advancement.skyland.ancient_debris.desc": "擁有村莊英雄狀態效果時,工具匠會有概率給予玩家遠古遺骸",
22 | "advancement.skyland.bedrock_layer.title": "基岩層",
23 | "advancement.skyland.bedrock_layer.desc": "在低Y的平臺生成怪物的概率提升",
24 | "advancement.skyland.better_wood.title": "更好的木頭",
25 | "advancement.skyland.better_wood.desc": "流浪商人會騎著熾足獸在熔岩上生成(生成機制于原版相同,但是需要熔岩)",
26 | "advancement.skyland.blast_furnace.title": "高爐",
27 | "advancement.skyland.blast_furnace.desc": "于豬布林交易以獲取合成高爐的材料",
28 | "advancement.skyland.breed_villagers.title": "繁殖村民",
29 | "advancement.skyland.breed_villagers.desc": "用突襲事件中獲取的綠寶石向村民購買麵包于蘋果來繁殖村民",
30 | "advancement.skyland.bulk_lava.title": "熔岩批量化",
31 | "advancement.skyland.bulk_lava.desc": "玄武岩在鍋釜中洗滌能獲取鐘乳石方塊,鐘乳石方塊被鐵砧砸能獲取鐘乳石簇",
32 | "advancement.skyland.composter.title": "堆肥桶!",
33 | "advancement.skyland.composter.desc": "在堆肥桶中堆肥可以獲得骨粉",
34 | "advancement.skyland.coral_fan.title": "珊瑚",
35 | "advancement.skyland.coral_fan.desc": "對著珊瑚塊側面使用骨粉使之生長出珊瑚扇,對其頂面使用骨粉生長出珊瑚",
36 | "advancement.skyland.elytra.title": "損壞的翅膀",
37 | "advancement.skyland.elytra.desc": "擊殺終界龍时,鞘翅會在龍死亡的位置掉落",
38 | "advancement.skyland.gold_ingot.title": "金錠!",
39 | "advancement.skyland.gold_ingot.desc": "擊殺殭屍化豬布林會有概率獲得金粒和金錠",
40 | "advancement.skyland.ice.title": "人工冰",
41 | "advancement.skyland.ice.desc": "雪人站在水上會將脚下的水變成冰",
42 | "advancement.skyland.kill_wrong.title": "殺錯了(っ °Д °;)っ",
43 | "advancement.skyland.kill_wrong.desc": "僵屍化豬布林觸發的僵屍增援會生成殭屍村民",
44 | "advancement.skyland.kill_zombified_piglin.title": "擊殺僵屍化豬布林",
45 | "advancement.skyland.kill_zombified_piglin.desc": "搭建刷怪平臺殺死僵屍化豬布林",
46 | "advancement.skyland.lava_bucket.title": "熔岩桶",
47 | "advancement.skyland.lava_bucket.desc": "擁有村莊英雄狀態效果時,皮匠有概率丟熔岩桶給玩家",
48 | "advancement.skyland.netherrack.title": "地獄岩",
49 | "advancement.skyland.netherrack.desc": "在高爐裏燒製地獄疙瘩塊可以獲得地獄岩",
50 | "advancement.skyland.respawn.title": "重生",
51 | "advancement.skyland.respawn.desc": "雖然地獄無法使用床,但你可以使用重生錨來重生",
52 | "advancement.skyland.root.title": "Nether Skyblock",
53 | "advancement.skyland.root.desc": "開始你的 Nether Skyblock 之旅\n在此之前 §b/skyland gamerule true§a 命令打開需要的游戲規則",
54 | "advancement.skyland.save_villager.title": "拯救村民",
55 | "advancement.skyland.save_villager.desc": "只有一個蘋果可以用來救村民(記得備份存檔以免救到傻子)",
56 | "advancement.skyland.shulker_box.title": "界伏盒",
57 | "advancement.skyland.shulker_box.desc": "擊殺復活后的終界龍后,界伏蚌会生成在終界池的上方",
58 | "advancement.skyland.slime.title": "史萊姆",
59 | "advancement.skyland.slime.desc": "在玄武岩三角洲史萊姆會和岩漿怪一同生成",
60 | "advancement.skyland.the_end.title": "終界?",
61 | "advancement.skyland.the_end.desc": "在以初始平臺為圓心,1024為半徑的位置上,會固定生成8個終界傳送門框架",
62 | "advancement.skyland.village_hero.title": "村莊英雄",
63 | "advancement.skyland.village_hero.desc": "獲得获得不祥之兆和村莊英雄。\n在堡壘遺跡結構内會生成掠奪者",
64 | "advancement.skyland.water.title": "水源",
65 | "advancement.skyland.water.desc": "在終界可以放置水出来",
66 | "advancement.skyland.weakness.title": "虛弱",
67 | "advancement.skyland.weakness.desc": "在靈魂沙峽谷會有很低的概率生成女巫",
68 | "advancement.skyland.wood.title": "木頭!",
69 | "advancement.skyland.wood.desc": "用骨粉催熟緋紅蕈菇獲得木頭",
70 |
71 | "skyland.tooltip.cool_down": "冷卻: %d",
72 | "skyland.tooltip.ready": "就緒",
73 | "config.jade.plugin_skyland.composter_cool_down": "堆肥桶冷卻"
74 | }
--------------------------------------------------------------------------------
/src/main/resources/assets/skyland/lang/zh_tw.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator.skyland.skyland": "空島",
3 | "gamerule.qnmdLC": "忽略LC值影響",
4 | "gamerule.chieftainMode": "非酋模式",
5 | "gamerule.waterCauldron": "儲水煉藥鍋將熔岩變爲黑曜石",
6 | "gamerule.netherTrader": "地獄游商",
7 | "gamerule.iceGolem": "雪傀儡可以將水變為冰",
8 | "gamerule.anvilHandle": "鐵砧處理",
9 | "gamerule.netherPatrol": "地獄掠奪者巡邏隊",
10 | "gamerule.villagerReinforcements": "村民增援",
11 | "gamerule.killDragonSpawnShulker": "龍亡貝誕",
12 | "gamerule.killDragonDropElytra": "戰龍奪翅",
13 | "gamerule.composterBoneMeal": "在堆肥桶下蹲獲得骨粉",
14 | "gamerule.memoryFoodLevel": "記憶死亡前的飽食度",
15 | "gamerule.respawnMinFoodLevel": "重生後的最低飽食度",
16 |
17 | "skyland.command.gamerule_set_succeed": "SkyLand 規則設置到 %s 成功",
18 |
19 |
20 | "advancement.skyland.ancient_debris.title": "獄髓",
21 | "advancement.skyland.ancient_debris.desc": "擁有村莊英雄狀態效果時,工具匠會有概率給予玩家遠古遺骸",
22 | "advancement.skyland.bedrock_layer.title": "基岩層",
23 | "advancement.skyland.bedrock_layer.desc": "在低Y的平臺生成怪物的概率提升",
24 | "advancement.skyland.better_wood.title": "更好的木頭",
25 | "advancement.skyland.better_wood.desc": "流浪商人會騎著熾足獸在熔岩上生成(生成機制于原版相同,但是需要熔岩)",
26 | "advancement.skyland.blast_furnace.title": "高爐",
27 | "advancement.skyland.blast_furnace.desc": "于豬布林交易以獲取合成高爐的材料",
28 | "advancement.skyland.breed_villagers.title": "繁殖村民",
29 | "advancement.skyland.breed_villagers.desc": "用突襲事件中獲取的綠寶石向村民購買麵包于蘋果來繁殖村民",
30 | "advancement.skyland.bulk_lava.title": "熔岩批量化",
31 | "advancement.skyland.bulk_lava.desc": "玄武岩在鍋釜中洗滌能獲取鐘乳石方塊,鐘乳石方塊被鐵砧砸能獲取鐘乳石簇",
32 | "advancement.skyland.composter.title": "堆肥桶!",
33 | "advancement.skyland.composter.desc": "在堆肥桶中堆肥可以獲得骨粉",
34 | "advancement.skyland.coral_fan.title": "珊瑚",
35 | "advancement.skyland.coral_fan.desc": "對著珊瑚塊側面使用骨粉使之生長出珊瑚扇,對其頂面使用骨粉生長出珊瑚",
36 | "advancement.skyland.elytra.title": "損壞的翅膀",
37 | "advancement.skyland.elytra.desc": "擊殺終界龍时,鞘翅會在龍死亡的位置掉落",
38 | "advancement.skyland.gold_ingot.title": "金錠!",
39 | "advancement.skyland.gold_ingot.desc": "擊殺殭屍化豬布林會有概率獲得金粒和金錠",
40 | "advancement.skyland.ice.title": "人工冰",
41 | "advancement.skyland.ice.desc": "雪人站在水上會將脚下的水變成冰",
42 | "advancement.skyland.kill_wrong.title": "殺錯了(っ °Д °;)っ",
43 | "advancement.skyland.kill_wrong.desc": "僵屍化豬布林觸發的僵屍增援會生成殭屍村民",
44 | "advancement.skyland.kill_zombified_piglin.title": "擊殺僵屍化豬布林",
45 | "advancement.skyland.kill_zombified_piglin.desc": "搭建刷怪平臺殺死僵屍化豬布林",
46 | "advancement.skyland.lava_bucket.title": "熔岩桶",
47 | "advancement.skyland.lava_bucket.desc": "擁有村莊英雄狀態效果時,皮匠有概率丟熔岩桶給玩家",
48 | "advancement.skyland.netherrack.title": "地獄岩",
49 | "advancement.skyland.netherrack.desc": "在高爐裏燒製地獄疙瘩塊可以獲得地獄岩",
50 | "advancement.skyland.respawn.title": "重生",
51 | "advancement.skyland.respawn.desc": "雖然地獄無法使用床,但你可以使用重生錨來重生",
52 | "advancement.skyland.root.title": "Nether Skyblock",
53 | "advancement.skyland.root.desc": "開始你的 Nether Skyblock 之旅\n在此之前 §b/skyland gamerule true§a 命令打開需要的游戲規則",
54 | "advancement.skyland.save_villager.title": "拯救村民",
55 | "advancement.skyland.save_villager.desc": "只有一個蘋果可以用來救村民(記得備份存檔以免救到傻子)",
56 | "advancement.skyland.shulker_box.title": "界伏盒",
57 | "advancement.skyland.shulker_box.desc": "擊殺復活后的終界龍后,界伏蚌会生成在終界池的上方",
58 | "advancement.skyland.slime.title": "史萊姆",
59 | "advancement.skyland.slime.desc": "在玄武岩三角洲史萊姆會和岩漿怪一同生成",
60 | "advancement.skyland.the_end.title": "終界?",
61 | "advancement.skyland.the_end.desc": "在以初始平臺為圓心,1024為半徑的位置上,會固定生成8個終界傳送門框架",
62 | "advancement.skyland.village_hero.title": "村莊英雄",
63 | "advancement.skyland.village_hero.desc": "獲得获得不祥之兆和村莊英雄。\n在堡壘遺跡結構内會生成掠奪者",
64 | "advancement.skyland.water.title": "水源",
65 | "advancement.skyland.water.desc": "在終界可以放置水出来",
66 | "advancement.skyland.weakness.title": "虛弱",
67 | "advancement.skyland.weakness.desc": "在靈魂沙峽谷會有很低的概率生成女巫",
68 | "advancement.skyland.wood.title": "木頭!",
69 | "advancement.skyland.wood.desc": "用骨粉催熟緋紅蕈菇獲得木頭",
70 |
71 | "skyland.tooltip.cool_down": "冷卻: %d",
72 | "skyland.tooltip.ready": "就緒",
73 | "config.jade.plugin_skyland.composter_cool_down": "堆肥桶冷卻"
74 | }
--------------------------------------------------------------------------------
/src/main/resources/data/minecraft/loot_tables/blocks/powder_snow.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:block",
3 | "pools": [
4 | {
5 | "rolls": 1.0,
6 | "bonus_rolls": 0.0,
7 | "entries": [
8 | {
9 | "type": "minecraft:item",
10 | "name": "minecraft:snowball"
11 | }
12 | ],
13 | "conditions": [
14 | {
15 | "condition": "minecraft:survives_explosion"
16 | }
17 | ]
18 | }
19 | ]
20 | }
--------------------------------------------------------------------------------
/src/main/resources/data/minecraft/tags/mineable/shovel.json:
--------------------------------------------------------------------------------
1 | {
2 | "replace": false,
3 | "values": [
4 | "minecraft:clay",
5 | "minecraft:dirt",
6 | "minecraft:coarse_dirt",
7 | "minecraft:podzol",
8 | "minecraft:farmland",
9 | "minecraft:grass_block",
10 | "minecraft:gravel",
11 | "minecraft:mycelium",
12 | "minecraft:sand",
13 | "minecraft:red_sand",
14 | "minecraft:snow_block",
15 | "minecraft:snow",
16 | "minecraft:soul_sand",
17 | "minecraft:dirt_path",
18 | "minecraft:white_concrete_powder",
19 | "minecraft:orange_concrete_powder",
20 | "minecraft:magenta_concrete_powder",
21 | "minecraft:light_blue_concrete_powder",
22 | "minecraft:yellow_concrete_powder",
23 | "minecraft:lime_concrete_powder",
24 | "minecraft:pink_concrete_powder",
25 | "minecraft:gray_concrete_powder",
26 | "minecraft:light_gray_concrete_powder",
27 | "minecraft:cyan_concrete_powder",
28 | "minecraft:purple_concrete_powder",
29 | "minecraft:blue_concrete_powder",
30 | "minecraft:brown_concrete_powder",
31 | "minecraft:green_concrete_powder",
32 | "minecraft:red_concrete_powder",
33 | "minecraft:black_concrete_powder",
34 | "minecraft:soul_soil",
35 | "minecraft:rooted_dirt",
36 | "minecraft:powder_snow"
37 | ]
38 | }
--------------------------------------------------------------------------------
/src/main/resources/data/minecraft/tags/worldgen/world_preset/normal.json:
--------------------------------------------------------------------------------
1 | {
2 | "values": [
3 | "minecraft:normal",
4 | "minecraft:flat",
5 | "minecraft:large_biomes",
6 | "minecraft:amplified",
7 | "minecraft:single_biome_surface",
8 | "skyland:skyland"
9 | ]
10 | }
--------------------------------------------------------------------------------
/src/main/resources/data/minecraft/worldgen/structure/bastion_remnant.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "minecraft:jigsaw",
3 | "biomes": "#minecraft:has_structure/bastion_remnant",
4 | "max_distance_from_center": 80,
5 | "size": 6,
6 | "spawn_overrides": {
7 | "monster": {
8 | "bounding_box": "full",
9 | "spawns": [
10 | {
11 | "type": "minecraft:pillager",
12 | "maxCount": 1,
13 | "minCount": 1,
14 | "weight": 1
15 | },
16 | {
17 | "type": "minecraft:piglin",
18 | "maxCount": 5,
19 | "minCount": 2,
20 | "weight": 20
21 | },
22 | {
23 | "type": "minecraft:zombified_piglin",
24 | "maxCount": 4,
25 | "minCount": 2,
26 | "weight": 10
27 | }
28 | ]
29 | }
30 | },
31 | "start_height": {
32 | "absolute": 33
33 | },
34 | "start_pool": "minecraft:bastion/starts",
35 | "step": "surface_structures",
36 | "use_expansion_hack": false
37 | }
--------------------------------------------------------------------------------
/src/main/resources/data/skyland/structures/spawn_platform.nbt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nether-Power/Nether-Sky-Block/d155f0f4b3898cd11a1a218cf6d359662c9c8c92/src/main/resources/data/skyland/structures/spawn_platform.nbt
--------------------------------------------------------------------------------
/src/main/resources/data/skyland/structures/the_end_portal.nbt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nether-Power/Nether-Sky-Block/d155f0f4b3898cd11a1a218cf6d359662c9c8c92/src/main/resources/data/skyland/structures/the_end_portal.nbt
--------------------------------------------------------------------------------
/src/main/resources/fabric.mod.json:
--------------------------------------------------------------------------------
1 | {
2 | "schemaVersion": 1,
3 | "id": "skyland",
4 | "version": "${version}",
5 | "name": "NetherSkyBlock",
6 | "description": "A Mod for Minecraft Nether SkyBlock",
7 | "authors": [
8 | "Nether-Power"
9 | ],
10 | "contact": {
11 | "sources": "https://github.com/XXiuBai/Nether_Sky_Block",
12 | "issues": "https://github.com/XXiuBai/Nether_Sky_Block/issues"
13 | },
14 | "license": "LGPL-3.0-or-later",
15 | "icon": "pack.png",
16 | "environment": "*",
17 | "entrypoints": {
18 | "main": [
19 | "dev.dubhe.skyland.SkyLandMod"
20 | ],
21 | "fabric-datagen": [
22 | "dev.dubhe.skyland.data.SkyLandDataGenerator"
23 | ],
24 | "jade": [
25 | "dev.dubhe.skyland.plugin.ComposterPlugin"
26 | ]
27 | },
28 | "mixins": [
29 | "skyland.mixins.json"
30 | ],
31 | "accessWidener": "skyland.accesswidener",
32 | "depends": {
33 | "minecraft": ">=1.19",
34 | "fabricloader": "*",
35 | "fabric": "*"
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/resources/pack.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Nether-Power/Nether-Sky-Block/d155f0f4b3898cd11a1a218cf6d359662c9c8c92/src/main/resources/pack.png
--------------------------------------------------------------------------------
/src/main/resources/skyland.accesswidener:
--------------------------------------------------------------------------------
1 | accessWidener v1 named
2 | extendable class net/minecraft/world/gen/chunk/NoiseChunkGenerator
3 |
4 | accessible class net/minecraft/village/TradeOffers$SellItemFactory
5 |
--------------------------------------------------------------------------------
/src/main/resources/skyland.mixins.json:
--------------------------------------------------------------------------------
1 | {
2 | "required": true,
3 | "package": "dev.dubhe.skyland.mixin",
4 | "compatibilityLevel": "JAVA_17",
5 | "mixins": [
6 | "BoneMealItemMixin",
7 | "CauldronBlockMixin",
8 | "ChunkGeneratorsMixin",
9 | "EnderDragonFightMixin",
10 | "FallingBlockEntityMixin",
11 | "FluidBlockMixin",
12 | "LeveledCauldronBlockMixin",
13 | "MinecraftServerMixin",
14 | "PatrolSpawnerMixin",
15 | "PlayerInventoryMixin",
16 | "SellItemFactoryAccessor",
17 | "ServerPlayerEntityMixin",
18 | "ServerWorldMixin",
19 | "SlimeEntityMixin",
20 | "SnowGolemEntityMixin",
21 | "SpawnHelperMixin",
22 | "TheEndBiomeCreatorMixin",
23 | "TheNetherBiomeCreatorMixin",
24 | "WanderingTraderManagerMixin",
25 | "WaterCreatureEntityMixin",
26 | "WorldPresetsRegistrarMixin",
27 | "ZombieEntityMixin"
28 | ],
29 | "client": [
30 | "IntegratedServerLoaderMixin"
31 | ],
32 | "injectors": {
33 | "defaultRequire": 1
34 | }
35 | }
36 |
--------------------------------------------------------------------------------