Compare commits
70 Commits
Author | SHA1 | Date | |
---|---|---|---|
5381263113 | |||
263466eed3 | |||
10bfbdb53d | |||
162df5c962 | |||
3f06723a1f | |||
700b970a04 | |||
3bfe235d97 | |||
48fef73096 | |||
504a52597d | |||
55808ca049 | |||
e5aa71f751 | |||
0664de5de5 | |||
4d0e4b6411 | |||
114c3a03d2 | |||
6b3445e1f6 | |||
14f254af3d | |||
8a23afeed0 | |||
8ca4986714 | |||
fb3ba1411f | |||
3b91e3daf8 | |||
acf08c7fa6 | |||
5552fe5cd8 | |||
d381beff16 | |||
ff50bd3851 | |||
76f316f7bd | |||
df3c1dcffd | |||
d2d33c6159 | |||
f40e44e366 | |||
4ebae792ac | |||
3fe89d2d95 | |||
b44ca31175 | |||
9d1cad6223 | |||
373f0ad8d3 | |||
1c033d5a0d | |||
1dbbd55376 | |||
019c588add | |||
5e24602ca8 | |||
ee78088250 | |||
c592b9e9af | |||
db54bdf2ad | |||
a3be3712d4 | |||
998e514cd9 | |||
4bc4821543 | |||
5a4cd89d68 | |||
df7826d584 | |||
6d8376b8a9 | |||
3a173b25d1 | |||
dca3e4718d | |||
815fd3d7a7 | |||
b22deba559 | |||
a8b12d9d5c | |||
7dac950cca | |||
738037137d | |||
2f262b9cf4 | |||
e431ddb057 | |||
f106b485fb | |||
27cdf09bc2 | |||
8cf31594e0 | |||
963900a65d | |||
516d7909f1 | |||
cf3376ec90 | |||
07d1d44f52 | |||
b88132eb29 | |||
bbfad9303a | |||
abc16c2bbb | |||
c1e935764d | |||
eabca94f00 | |||
8448acca6a | |||
dd228acf79 | |||
e2cfd1d656 |
4
.gitignore
vendored
4
.gitignore
vendored
@ -22,4 +22,6 @@ bin/
|
|||||||
|
|
||||||
# fabric
|
# fabric
|
||||||
|
|
||||||
run/
|
run/
|
||||||
|
|
||||||
|
remappedSrc/
|
115
API.md
Normal file
115
API.md
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
# API
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
1. Add Dependency to Gradle
|
||||||
|
```gradle
|
||||||
|
repositories {
|
||||||
|
maven { url 'https://maven.thebrokenrail.com' }
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
modImplementation 'com.thebrokenrail:sorcerycraft:VERSION'
|
||||||
|
// VERSION = "<Mod Version>+<MC Version>", for example "1.2.4+20w12a"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
2. Add Dependency to ```fabric.mod.json```
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"depends": {
|
||||||
|
"sorcerycraft": "1.2.x"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
3. Create a class extending ```com.thebrokenrail.sorcerycraft.spell.api.Spell```
|
||||||
|
```java
|
||||||
|
public class ExampleSpell extends Spell {
|
||||||
|
public ExampleSpell(Identifier id, int level) {
|
||||||
|
super(id, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Entity target, Entity source, Entity attacker) {
|
||||||
|
// OPTIONAL
|
||||||
|
// Called when ExampleSpell hits an entity
|
||||||
|
// Override this if you want the spell to affect entities
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(World world, BlockHitResult hitResult) {
|
||||||
|
// OPTIONAL
|
||||||
|
// Called when ExampleSpell hits a block
|
||||||
|
// Override this if you want the spell to affect blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getXPCost() {
|
||||||
|
// REQUIRED
|
||||||
|
// Return the amount of levels required to make ExampleSpell in a Casting Table
|
||||||
|
switch (getLevel()) {
|
||||||
|
case 0: {
|
||||||
|
return 4;
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
return 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemCost() {
|
||||||
|
// REQUIRED
|
||||||
|
// Return the item(s) required to make ExampleSpell in a Casting Table
|
||||||
|
// Return ItemStack.EMPTY if an item is not required
|
||||||
|
switch (getLevel()) {
|
||||||
|
case 0: {
|
||||||
|
return new ItemStack(Items.SUGAR_CANE);
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
return new ItemStack(Items.BOOK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLevel() {
|
||||||
|
// REQUIRED
|
||||||
|
// Return ExampleSpell's maximum level
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getTranslation() {
|
||||||
|
// OPTIONAL
|
||||||
|
// Return a custom display name for ExampleSpell
|
||||||
|
// Override this only if you want a custom display name
|
||||||
|
return new LiteralText("Example " + (getLevel() + 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
4. Register the spell in your ModInitializer
|
||||||
|
```java
|
||||||
|
public class ExampleMod implements ModInitializer {
|
||||||
|
public static final Identifier EXAMPLE_SPELL = SpellRegistry.register(new Identifier("modid", "example_spell"), ExampleSpell.class);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
5. Add Spell Translation (skip this if you have overridden ```Spell.getTranslation()``)
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"spell.modid.example_spell": "Example"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Useful Methods
|
||||||
|
- ```(non-static) Spell.getLevel()```
|
||||||
|
- ```(non-static) Spell.getID()```
|
||||||
|
- ```(static) SpellRegistry.register()```
|
||||||
|
|
||||||
|
## API Stability
|
||||||
|
APIs are only guaranteed to be stable in the ```com.thebrokenrail.sorcerycraft.api``` package, it is unrecommended to rely on any SorceryCraft classes outside of this package.
|
||||||
|
|
||||||
|
## Spell Levels
|
||||||
|
Spell levels are 0-indexed, if you have a level 1 Example Spell, ```Spell.getLevel()``` wil return 0, and if it is level 2 ```Spell.getLevel()``` wil return 1, ```Spell.getMaxSpell()``` should be the maximum-acceptable value of ```Spell.getLevel() + 1```, so if Example Spell has levels 1-2, ```Spell.getMaxLevel()``` should return 2.
|
||||||
|
|
||||||
|
## JavaDoc
|
||||||
|
[View JavaDoc](https://jenkins.thebrokenrail.com/job/SorceryCraft/job/master/JavaDoc/)
|
156
CHANGELOG.md
156
CHANGELOG.md
@ -1,4 +1,156 @@
|
|||||||
### Changelog
|
# Changelog
|
||||||
|
|
||||||
|
**1.2.9**
|
||||||
|
* Fix Dedicated Server Crash
|
||||||
|
|
||||||
|
**1.2.8**
|
||||||
|
* Register Loot Table Function
|
||||||
|
|
||||||
|
**1.2.7**
|
||||||
|
* Fix Cooling Spell Bug
|
||||||
|
|
||||||
|
**1.2.6**
|
||||||
|
* Fix Potential Client-Server De-sync Bug
|
||||||
|
|
||||||
|
**1.2.5**
|
||||||
|
* Fix Casting Table Bug
|
||||||
|
|
||||||
|
**1.2.4**
|
||||||
|
* Optimize Packets
|
||||||
|
* Allow Command Blocks to use ```/spell``` Command
|
||||||
|
* Namespace Statistics
|
||||||
|
|
||||||
|
**1.2.3**
|
||||||
|
* Tweak Cooling Spell
|
||||||
|
* Tweak Versioning
|
||||||
|
|
||||||
|
**1.2.2**
|
||||||
|
* Allow ```/spell``` command to work with multiple players
|
||||||
|
|
||||||
|
**1.2.1**
|
||||||
|
* Fix Launching Without ModMenu
|
||||||
|
|
||||||
|
**1.2**
|
||||||
|
* Update Mappings
|
||||||
|
* Update API (More Consistent Package Names)
|
||||||
|
* Fix Bug When Casting Spell
|
||||||
|
|
||||||
|
**1.1.21**
|
||||||
|
* Update Mappings
|
||||||
|
* Tweak Teleport and Flame Spells
|
||||||
|
|
||||||
|
**1.1.20**
|
||||||
|
* Update to 20w12a
|
||||||
|
|
||||||
|
**1.1.19**
|
||||||
|
* Update API Docs
|
||||||
|
* Allow Setting Custom Display name for Spell
|
||||||
|
|
||||||
|
**1.1.18**
|
||||||
|
* Fix Crash When Using Dedicated Server
|
||||||
|
|
||||||
|
**1.1.17**
|
||||||
|
* Update Mappings
|
||||||
|
* Add Spell-related Advancements
|
||||||
|
|
||||||
|
**1.1.16**
|
||||||
|
* Consistent Gradle Project Name
|
||||||
|
|
||||||
|
**1.1.15**
|
||||||
|
* Build JavaDoc Jar
|
||||||
|
|
||||||
|
**1.1.14**
|
||||||
|
* Update Config Lang
|
||||||
|
|
||||||
|
**1.1.13**
|
||||||
|
* Update Mappings
|
||||||
|
* Improve ```/spell``` command
|
||||||
|
|
||||||
|
**1.1.12**
|
||||||
|
* Update Mappings
|
||||||
|
* Add Config Screen
|
||||||
|
* Clarify Terms
|
||||||
|
|
||||||
|
**1.1.11**
|
||||||
|
* Update Mappings
|
||||||
|
* Add Lightning Spell
|
||||||
|
|
||||||
|
**1.1.10**
|
||||||
|
* Update to 20w11a
|
||||||
|
* Enhance Flame Spell
|
||||||
|
|
||||||
|
**1.1.9**
|
||||||
|
* Fix Scrolling Bug
|
||||||
|
|
||||||
|
**1.1.8**
|
||||||
|
* Tweak Casting Table UI
|
||||||
|
|
||||||
|
**1.1.7**
|
||||||
|
* Improve JavaDoc
|
||||||
|
* Update Mappings
|
||||||
|
* Tweak Spell Texture
|
||||||
|
|
||||||
|
**1.1.6**
|
||||||
|
* Add Spell-related Statistics
|
||||||
|
|
||||||
|
**1.1.5**
|
||||||
|
* Tweak Spell Particles
|
||||||
|
|
||||||
|
**1.1.4**
|
||||||
|
* Tweak Casting Table Texture
|
||||||
|
* Tweak Casting Table Recipe
|
||||||
|
* Update Mappings
|
||||||
|
|
||||||
|
**1.1.3**
|
||||||
|
* Fix Shift-Clicking in Casting Table
|
||||||
|
|
||||||
|
**1.1.2**
|
||||||
|
* Update Casting Table Texture
|
||||||
|
* Generate Spells in Pillager Outposts and Woodland Mansions
|
||||||
|
|
||||||
|
**1.1.1**
|
||||||
|
* Add a unique texture for the Spell
|
||||||
|
|
||||||
|
**1.1**
|
||||||
|
* API is now stable
|
||||||
|
* Fix ```/spell``` suggestions
|
||||||
|
|
||||||
|
**1.0.14**
|
||||||
|
* Update Spell API
|
||||||
|
|
||||||
|
**1.0.13**
|
||||||
|
* Rename ```SpellRegistry.registerSpell``` to ```SpellRegistry.register```
|
||||||
|
|
||||||
|
**1.0.12**
|
||||||
|
* Update Mappings
|
||||||
|
* Add API Docs
|
||||||
|
|
||||||
|
**1.0.11**
|
||||||
|
* Allow Spells to Affect Blocks
|
||||||
|
* Add Cooling Spell
|
||||||
|
|
||||||
|
**1.0.10**
|
||||||
|
* Add Issues Link
|
||||||
|
|
||||||
|
**1.0.9**
|
||||||
|
* Update Particles
|
||||||
|
|
||||||
|
**1.0.8**
|
||||||
|
* Update to 20w10a
|
||||||
|
* Add the ```/spell learn```, ```/spell add```, and ```/spell remove``` commands
|
||||||
|
* Use CurseForge
|
||||||
|
|
||||||
|
**1.0.7**
|
||||||
|
* Play Failure Sound when Inward Spell Fails
|
||||||
|
|
||||||
|
**1.0.6**
|
||||||
|
* Namespace PlayerEntity Mixin
|
||||||
|
|
||||||
|
**1.0.5**
|
||||||
|
* Clean up code
|
||||||
|
|
||||||
|
**1.0.4**
|
||||||
|
* Migrate old worlds to new ID system
|
||||||
|
|
||||||
**1.0.3**
|
**1.0.3**
|
||||||
* Tweak Loot Tables
|
* Tweak Loot Tables
|
||||||
@ -13,5 +165,5 @@
|
|||||||
**1.0.1**
|
**1.0.1**
|
||||||
* Add Teleport Spell
|
* Add Teleport Spell
|
||||||
|
|
||||||
**1.0.0**
|
**1.0**
|
||||||
* Initial Release
|
* Initial Release
|
23
Jenkinsfile
vendored
23
Jenkinsfile
vendored
@ -7,11 +7,32 @@ pipeline {
|
|||||||
stages {
|
stages {
|
||||||
stage('Build') {
|
stage('Build') {
|
||||||
steps {
|
steps {
|
||||||
sh './gradlew build'
|
sh './gradlew build javadoc'
|
||||||
}
|
}
|
||||||
post {
|
post {
|
||||||
success {
|
success {
|
||||||
archiveArtifacts artifacts: 'build/libs/*', fingerprint: true
|
archiveArtifacts artifacts: 'build/libs/*', fingerprint: true
|
||||||
|
|
||||||
|
publishHTML target: [
|
||||||
|
allowMissing: false,
|
||||||
|
alwaysLinkToLastBuild: false,
|
||||||
|
keepAll: false,
|
||||||
|
reportDir: 'build/docs/javadoc',
|
||||||
|
reportFiles: 'index.html',
|
||||||
|
reportName: 'JavaDoc'
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stage('Publish') {
|
||||||
|
when {
|
||||||
|
expression {
|
||||||
|
return sh(returnStdout: true, script: 'git tag --contains').trim().length() > 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
steps {
|
||||||
|
withCredentials([string(credentialsId: 'curseforge_key', variable: 'CURSEFORGE_KEY')]) {
|
||||||
|
sh './gradlew -Pcurseforge.api_key="${CURSEFORGE_KEY}" curseforge publish'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
46
README.md
46
README.md
@ -1,13 +1,13 @@
|
|||||||
# SorceryCraft
|
# SorceryCraft
|
||||||
Cast Spells in Minecraft!
|
Cast Spells in Minecraft!
|
||||||
|
|
||||||
This mod supports the Minecraft 1.16 snapshots.
|
This mod currently supports the Minecraft 1.16 snapshots.
|
||||||
|
|
||||||
## What are Spells?
|
## What are Spells?
|
||||||
Spells are found throughout the world in chests. When you pick up a Spell you will learn it, one you learn a Spell you can apply it to a blank or existing Spell in the Casting Table. You can cast Spells by right-clicking. There is also a 30% chance the spell will rebound and hit you instead, unless the "Steadfast" Spell is applied.
|
Spells are found throughout the world in chests. When you pick up a Spell you will "discover" it, once you "discover" a spell you can apply it to a blank or existing spell in the Casting Table. You can cast spells by right-clicking. There is also a 30% chance (by default) that the spell will rebound and hit you instead, unless the "Steadfast" spell is applied.
|
||||||
|
|
||||||
## What's a Casting Table?
|
## What's a Casting Table?
|
||||||
You can apply Spells to blank or existing Spells in the Casting Table. Doing so will require a certain amount of levels, and sometimes may require an item.
|
You can apply Spells to blank or existing spells in the Casting Table. Doing so will require a certain amount of levels, and may require an item.
|
||||||
|
|
||||||
## Crafting
|
## Crafting
|
||||||
#### Blank Spell
|
#### Blank Spell
|
||||||
@ -29,7 +29,7 @@ You can apply Spells to blank or existing Spells in the Casting Table. Doing so
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
#### Casting table
|
#### Casting Table
|
||||||
<table>
|
<table>
|
||||||
<tr>
|
<tr>
|
||||||
<td>Lapis Lazuli</td>
|
<td>Lapis Lazuli</td>
|
||||||
@ -56,6 +56,38 @@ You can apply Spells to blank or existing Spells in the Casting Table. Doing so
|
|||||||
| Heal | 2 | Heals target. |
|
| Heal | 2 | Heals target. |
|
||||||
| Dissolve | 1 | Removes target's status effects. |
|
| Dissolve | 1 | Removes target's status effects. |
|
||||||
| Levitate | 2 | Gives target the Levitation effect. |
|
| Levitate | 2 | Gives target the Levitation effect. |
|
||||||
| Steadfast | 1 | Prevents Spell from rebounding. |
|
| Steadfast | 1 | Prevents the spell from failing. This spell does nothing on its own. |
|
||||||
| Teleport | 2 | Teleports target to random location. |
|
| Teleport | 3 | Teleports the target to a random location. |
|
||||||
| Inward | 1 | Causes the Spell to target the player. If the Spell fails instead of rebounding, it will just do nothing. |
|
| Inward | 1 | Causes the spell to target the caster. If the spell fails instead of rebounding, it will just do nothing. This spell does nothing on its own. |
|
||||||
|
| Cooling | 1 | Extinguish the target if they are on fire. |
|
||||||
|
| Lightning | 1 | Strikes the target with lightning. |
|
||||||
|
|
||||||
|
## ```/spell``` Command
|
||||||
|
This command requires OP permissions.
|
||||||
|
|
||||||
|
#### ```/spell forget <player>```
|
||||||
|
This command clears all known spells from the given player.
|
||||||
|
|
||||||
|
#### ```/spell forget <player> <spell-id>```
|
||||||
|
This command clears the specified spell from the given player.
|
||||||
|
|
||||||
|
#### ```/spell list <player>```
|
||||||
|
This lists all the spells the given player knows.
|
||||||
|
|
||||||
|
#### ```/spell discover <player>```
|
||||||
|
This adds all spells to the specified player's discovered spells list.
|
||||||
|
|
||||||
|
#### ```/spell discover <player> <spell-id> <level>```
|
||||||
|
This adds the specified spell to the specified player's discovered spells list.
|
||||||
|
|
||||||
|
#### ```/spell apply <player> <spell-id> <level>```
|
||||||
|
This adds the specified spell to the item in the specified player's main hand.
|
||||||
|
|
||||||
|
#### ```/spell remove <player> <spell-id>```
|
||||||
|
This removes the specified spell from the item in the specified player's main hand.
|
||||||
|
|
||||||
|
## API
|
||||||
|
[View API](API.md)
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
[View Changelog](CHANGELOG.md)
|
92
build.gradle
92
build.gradle
@ -1,5 +1,7 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'fabric-loom' version '0.2.6-SNAPSHOT'
|
id 'fabric-loom' version '0.4-SNAPSHOT'
|
||||||
|
id 'com.matthewprenger.cursegradle' version '1.4.0'
|
||||||
|
id 'maven-publish'
|
||||||
}
|
}
|
||||||
|
|
||||||
compileJava {
|
compileJava {
|
||||||
@ -8,32 +10,44 @@ compileJava {
|
|||||||
}
|
}
|
||||||
|
|
||||||
archivesBaseName = project.archives_base_name
|
archivesBaseName = project.archives_base_name
|
||||||
version = project.mod_version as Object
|
def mod_version = project.mod_version as Object
|
||||||
|
version = "${mod_version}+${project.minecraft_version}"
|
||||||
group = project.maven_group as Object
|
group = project.maven_group as Object
|
||||||
|
|
||||||
minecraft {
|
minecraft {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
jcenter()
|
||||||
|
maven {
|
||||||
|
url "https://dl.bintray.com/shedaniel/autoconfig1u/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||||
mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2"
|
mappings "net.fabricmc:yarn:${project.minecraft_version}+build.${project.yarn_build}:v2"
|
||||||
modCompile "net.fabricmc:fabric-loader:${project.loader_version}"
|
modImplementation "net.fabricmc:fabric-loader:${project.fabric_loader_version}"
|
||||||
|
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}"
|
||||||
|
|
||||||
modCompile "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
|
modImplementation "me.shedaniel.cloth:config-2:${project.cloth_config_version}"
|
||||||
|
include "me.shedaniel.cloth:config-2:${project.cloth_config_version}"
|
||||||
|
modImplementation "me.sargunvohra.mcmods:autoconfig1u:${project.auto_config_version}"
|
||||||
|
include "me.sargunvohra.mcmods:autoconfig1u:${project.auto_config_version}"
|
||||||
|
modImplementation "io.github.prospector:modmenu:${project.mod_menu_version}"
|
||||||
}
|
}
|
||||||
|
|
||||||
processResources {
|
processResources {
|
||||||
inputs.property "version", version
|
inputs.property 'version', project.version
|
||||||
inputs.property "modid", archivesBaseName
|
inputs.property 'name', rootProject.name
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
include "fabric.mod.json"
|
include 'fabric.mod.json'
|
||||||
expand "version": version
|
expand 'version': project.version, 'name': rootProject.name
|
||||||
expand "modid": archivesBaseName
|
|
||||||
}
|
}
|
||||||
|
|
||||||
from(sourceSets.main.resources.srcDirs) {
|
from(sourceSets.main.resources.srcDirs) {
|
||||||
exclude "fabric.mod.json"
|
exclude 'fabric.mod.json'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,17 +55,69 @@ processResources {
|
|||||||
// this fixes some edge cases with special characters not displaying correctly
|
// this fixes some edge cases with special characters not displaying correctly
|
||||||
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
// see http://yodaconditions.net/blog/fix-for-java-file-encoding-problems-with-gradle.html
|
||||||
tasks.withType(JavaCompile) {
|
tasks.withType(JavaCompile) {
|
||||||
options.encoding = "UTF-8"
|
options.encoding = 'UTF-8'
|
||||||
}
|
}
|
||||||
|
|
||||||
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
// Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
|
||||||
// if it is present.
|
// if it is present.
|
||||||
// If you remove this task, sources will not be generated.
|
// If you remove this task, sources will not be generated.
|
||||||
task sourcesJar(type: Jar, dependsOn: classes) {
|
task sourcesJar(type: Jar, dependsOn: classes) {
|
||||||
classifier "sources"
|
classifier 'sources'
|
||||||
from sourceSets.main.allSource
|
from sourceSets.main.allSource
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task javadocJar(type: Jar, dependsOn: javadoc) {
|
||||||
|
classifier 'javadoc'
|
||||||
|
from javadoc.destinationDir
|
||||||
|
}
|
||||||
|
|
||||||
|
artifacts {
|
||||||
|
archives sourcesJar
|
||||||
|
archives javadocJar
|
||||||
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
from "LICENSE"
|
from "LICENSE"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
publishing {
|
||||||
|
publications {
|
||||||
|
mavenJava(MavenPublication) {
|
||||||
|
artifactId archivesBaseName
|
||||||
|
|
||||||
|
artifact(remapJar) {
|
||||||
|
builtBy remapJar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
repositories {
|
||||||
|
maven {
|
||||||
|
url '/data/maven'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (project.hasProperty('curseforge.api_key')) {
|
||||||
|
curseforge {
|
||||||
|
apiKey = project.getProperty('curseforge.api_key')
|
||||||
|
project {
|
||||||
|
id = project.curseforge_id
|
||||||
|
changelog = 'A changelog can be found at https://gitea.thebrokenrail.com/TheBrokenRail/SorceryCraft/src/branch/master/CHANGELOG.md'
|
||||||
|
releaseType = 'release'
|
||||||
|
addGameVersion project.simple_minecraft_version
|
||||||
|
addGameVersion 'Fabric'
|
||||||
|
mainArtifact(remapJar) {
|
||||||
|
displayName = "SorceryCraft v${mod_version} for ${project.minecraft_version}"
|
||||||
|
}
|
||||||
|
afterEvaluate {
|
||||||
|
uploadTask.dependsOn('remapJar')
|
||||||
|
}
|
||||||
|
relations {
|
||||||
|
requiredDependency 'fabric-api'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
options {
|
||||||
|
forgeGradleIntegration = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,15 +3,20 @@ org.gradle.jvmargs = -Xmx1G
|
|||||||
|
|
||||||
# Fabric Properties
|
# Fabric Properties
|
||||||
# check these on https://fabricmc.net/use
|
# check these on https://fabricmc.net/use
|
||||||
minecraft_version = 20w09a
|
minecraft_version = 1.16.4
|
||||||
yarn_mappings = 20w09a+build.6
|
curseforge_id = 365308
|
||||||
loader_version = 0.7.8+build.184
|
simple_minecraft_version = 1.16.4
|
||||||
|
yarn_build = 7
|
||||||
|
fabric_loader_version = 0.10.8
|
||||||
|
|
||||||
# Mod Properties
|
# Mod Properties
|
||||||
mod_version = 1.0.3
|
mod_version = 1.2.9
|
||||||
maven_group = com.thebrokenrail
|
maven_group = com.thebrokenrail
|
||||||
archives_base_name = sorcerycraft
|
archives_base_name = sorcerycraft
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
|
# currently not on the main fabric site, check on the maven: https://maven.fabricmc.net/net/fabricmc/fabric-api/fabric-api
|
||||||
fabric_version = 0.4.33+build.301-1.16
|
fabric_api_version = 0.28.1+1.16
|
||||||
|
cloth_config_version = 4.8.3
|
||||||
|
auto_config_version = 3.3.1
|
||||||
|
mod_menu_version = 1.14.13+build.19
|
||||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
#Sat Feb 29 21:58:32 EST 2020
|
#Sat Feb 29 21:58:32 EST 2020
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.2.2-all.zip
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
@ -8,3 +8,5 @@ pluginManagement {
|
|||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rootProject.name = 'SorceryCraft'
|
||||||
|
32
src/main/java/com/thebrokenrail/sorcerycraft/ModConfig.java
Normal file
32
src/main/java/com/thebrokenrail/sorcerycraft/ModConfig.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft;
|
||||||
|
|
||||||
|
import me.sargunvohra.mcmods.autoconfig1u.ConfigData;
|
||||||
|
import me.sargunvohra.mcmods.autoconfig1u.annotation.Config;
|
||||||
|
import me.sargunvohra.mcmods.autoconfig1u.annotation.ConfigEntry;
|
||||||
|
|
||||||
|
import java.lang.annotation.ElementType;
|
||||||
|
import java.lang.annotation.Retention;
|
||||||
|
import java.lang.annotation.RetentionPolicy;
|
||||||
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
@Config(name = SorceryCraft.NAMESPACE)
|
||||||
|
public class ModConfig implements ConfigData {
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target({ElementType.FIELD})
|
||||||
|
public @interface UsePercentage {
|
||||||
|
double min();
|
||||||
|
|
||||||
|
double max();
|
||||||
|
}
|
||||||
|
|
||||||
|
@UsePercentage(min = 0, max = 1)
|
||||||
|
public double failureChance = 0.3;
|
||||||
|
|
||||||
|
@ConfigEntry.Gui.CollapsibleObject(startExpanded = true)
|
||||||
|
public LimitCastingTable limitCastingTable = new LimitCastingTable();
|
||||||
|
|
||||||
|
public static class LimitCastingTable {
|
||||||
|
public boolean creative = false;
|
||||||
|
public boolean survival = true;
|
||||||
|
}
|
||||||
|
}
|
@ -1,36 +1,32 @@
|
|||||||
package com.thebrokenrail.sorcerycraft;
|
package com.thebrokenrail.sorcerycraft;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.advancement.CreateSpellCriterion;
|
||||||
|
import com.thebrokenrail.sorcerycraft.advancement.DiscoverAllSpellsCriterion;
|
||||||
import com.thebrokenrail.sorcerycraft.block.CastingTableBlock;
|
import com.thebrokenrail.sorcerycraft.block.CastingTableBlock;
|
||||||
import com.thebrokenrail.sorcerycraft.block.CastingTableContainer;
|
|
||||||
import com.thebrokenrail.sorcerycraft.client.block.CastingTableScreen;
|
|
||||||
import com.thebrokenrail.sorcerycraft.client.entity.SpellEntityRenderer;
|
|
||||||
import com.thebrokenrail.sorcerycraft.command.SpellCommand;
|
import com.thebrokenrail.sorcerycraft.command.SpellCommand;
|
||||||
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
||||||
import com.thebrokenrail.sorcerycraft.item.SpellItem;
|
import com.thebrokenrail.sorcerycraft.item.SpellItem;
|
||||||
|
import com.thebrokenrail.sorcerycraft.mixin.CriteriaRegistryHook;
|
||||||
import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket;
|
import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket;
|
||||||
import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket;
|
import com.thebrokenrail.sorcerycraft.spell.util.RandomSpellLootTableFunction;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.RandomSpellLootTableFunction;
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.Spells;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.Spells;
|
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import me.sargunvohra.mcmods.autoconfig1u.serializer.GsonConfigSerializer;
|
||||||
import net.fabricmc.api.ModInitializer;
|
import net.fabricmc.api.ModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
|
import net.fabricmc.fabric.api.client.itemgroup.FabricItemGroupBuilder;
|
||||||
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
|
|
||||||
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
|
|
||||||
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
|
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
|
||||||
import net.fabricmc.fabric.api.entity.FabricEntityTypeBuilder;
|
import net.fabricmc.fabric.api.entity.FabricEntityTypeBuilder;
|
||||||
import net.fabricmc.fabric.api.loot.v1.FabricLootPoolBuilder;
|
import net.fabricmc.fabric.api.loot.v1.FabricLootPoolBuilder;
|
||||||
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
|
import net.fabricmc.fabric.api.loot.v1.event.LootTableLoadingCallback;
|
||||||
import net.fabricmc.fabric.api.registry.CommandRegistry;
|
import net.fabricmc.fabric.api.registry.CommandRegistry;
|
||||||
import net.fabricmc.fabric.impl.networking.ClientSidePacketRegistryImpl;
|
|
||||||
import net.fabricmc.fabric.impl.networking.ServerSidePacketRegistryImpl;
|
import net.fabricmc.fabric.impl.networking.ServerSidePacketRegistryImpl;
|
||||||
import net.minecraft.block.DispenserBlock;
|
import net.minecraft.block.DispenserBlock;
|
||||||
import net.minecraft.block.dispenser.ProjectileDispenserBehavior;
|
import net.minecraft.block.dispenser.ProjectileDispenserBehavior;
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.entity.EntityCategory;
|
|
||||||
import net.minecraft.entity.EntityDimensions;
|
import net.minecraft.entity.EntityDimensions;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.SpawnGroup;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.projectile.Projectile;
|
import net.minecraft.entity.projectile.ProjectileEntity;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemGroup;
|
import net.minecraft.item.ItemGroup;
|
||||||
@ -38,10 +34,12 @@ import net.minecraft.item.ItemStack;
|
|||||||
import net.minecraft.loot.BinomialLootTableRange;
|
import net.minecraft.loot.BinomialLootTableRange;
|
||||||
import net.minecraft.loot.LootTables;
|
import net.minecraft.loot.LootTables;
|
||||||
import net.minecraft.loot.entry.ItemEntry;
|
import net.minecraft.loot.entry.ItemEntry;
|
||||||
|
import net.minecraft.loot.function.LootFunctionType;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvent;
|
import net.minecraft.sound.SoundEvent;
|
||||||
import net.minecraft.sound.SoundEvents;
|
import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.stat.StatFormatter;
|
||||||
|
import net.minecraft.stat.Stats;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.math.BlockPointer;
|
import net.minecraft.util.math.BlockPointer;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@ -51,13 +49,18 @@ import net.minecraft.world.World;
|
|||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
public class SorceryCraft implements ModInitializer {
|
||||||
public static final String NAMESPACE = "sorcerycraft";
|
public static final String NAMESPACE = "sorcerycraft";
|
||||||
|
|
||||||
public static SpellItem SPELL_ITEM;
|
public static SpellItem SPELL_ITEM;
|
||||||
|
|
||||||
public static CastingTableBlock CASTING_TABLE_BLOCK;
|
public static CastingTableBlock CASTING_TABLE_BLOCK;
|
||||||
public static BlockItem CASTING_TABLE_BLOCK_ITEM;
|
public static BlockItem CASTING_TABLE_BLOCK_ITEM;
|
||||||
|
|
||||||
public static ItemGroup ITEM_GROUP;
|
public static ItemGroup ITEM_GROUP;
|
||||||
|
|
||||||
public static EntityType<SpellEntity> SPELL_ENTITY;
|
public static EntityType<SpellEntity> SPELL_ENTITY;
|
||||||
|
|
||||||
public static final Identifier[] LOOT_TABLES = new Identifier[]{
|
public static final Identifier[] LOOT_TABLES = new Identifier[]{
|
||||||
LootTables.SIMPLE_DUNGEON_CHEST,
|
LootTables.SIMPLE_DUNGEON_CHEST,
|
||||||
LootTables.END_CITY_TREASURE_CHEST,
|
LootTables.END_CITY_TREASURE_CHEST,
|
||||||
@ -66,10 +69,22 @@ public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
|||||||
LootTables.SHIPWRECK_TREASURE_CHEST,
|
LootTables.SHIPWRECK_TREASURE_CHEST,
|
||||||
LootTables.DESERT_PYRAMID_CHEST,
|
LootTables.DESERT_PYRAMID_CHEST,
|
||||||
LootTables.JUNGLE_TEMPLE_CHEST,
|
LootTables.JUNGLE_TEMPLE_CHEST,
|
||||||
LootTables.STRONGHOLD_LIBRARY_CHEST
|
LootTables.STRONGHOLD_LIBRARY_CHEST,
|
||||||
|
LootTables.PILLAGER_OUTPOST_CHEST,
|
||||||
|
LootTables.WOODLAND_MANSION_CHEST,
|
||||||
|
LootTables.BURIED_TREASURE_CHEST,
|
||||||
|
LootTables.FISHING_TREASURE_GAMEPLAY
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final double SPELL_FAILURE_CHANCE = 0.3d;
|
public static Identifier INTERACT_WITH_CASTING_TABLE_STAT;
|
||||||
|
public static Identifier CAST_SPELL_STAT;
|
||||||
|
|
||||||
|
public static DiscoverAllSpellsCriterion DISCOVER_ALL_SPELLS_CRITERION;
|
||||||
|
public static CreateSpellCriterion CREATE_SPELL_CRITERION;
|
||||||
|
|
||||||
|
public static ModConfig getConfig() {
|
||||||
|
return AutoConfig.getConfigHolder(ModConfig.class).getConfig();
|
||||||
|
}
|
||||||
|
|
||||||
private boolean isSelectedLootTable(Identifier lootTable) {
|
private boolean isSelectedLootTable(Identifier lootTable) {
|
||||||
for (Identifier id : LOOT_TABLES) {
|
for (Identifier id : LOOT_TABLES) {
|
||||||
@ -82,8 +97,11 @@ public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
|
//noinspection InstantiationOfUtilityClass
|
||||||
new Spells();
|
new Spells();
|
||||||
|
|
||||||
|
AutoConfig.register(ModConfig.class, GsonConfigSerializer::new);
|
||||||
|
|
||||||
ITEM_GROUP = FabricItemGroupBuilder.create(
|
ITEM_GROUP = FabricItemGroupBuilder.create(
|
||||||
new Identifier(NAMESPACE, "spells"))
|
new Identifier(NAMESPACE, "spells"))
|
||||||
.icon(() -> new ItemStack(SPELL_ITEM))
|
.icon(() -> new ItemStack(SPELL_ITEM))
|
||||||
@ -93,7 +111,7 @@ public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
|||||||
CASTING_TABLE_BLOCK_ITEM = new BlockItem(CASTING_TABLE_BLOCK, new Item.Settings().group(ITEM_GROUP));
|
CASTING_TABLE_BLOCK_ITEM = new BlockItem(CASTING_TABLE_BLOCK, new Item.Settings().group(ITEM_GROUP));
|
||||||
SPELL_ITEM = new SpellItem();
|
SPELL_ITEM = new SpellItem();
|
||||||
|
|
||||||
SPELL_ENTITY = FabricEntityTypeBuilder.create(EntityCategory.MISC, (EntityType.EntityFactory<SpellEntity>) SpellEntity::new).size(EntityDimensions.fixed(0.25f, 0.25f)).build();
|
SPELL_ENTITY = FabricEntityTypeBuilder.create(SpawnGroup.MISC, (EntityType.EntityFactory<SpellEntity>) SpellEntity::new).size(EntityDimensions.fixed(0.25f, 0.25f)).build();
|
||||||
|
|
||||||
Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "spell"), SPELL_ITEM);
|
Registry.register(Registry.ITEM, new Identifier(NAMESPACE, "spell"), SPELL_ITEM);
|
||||||
Registry.register(Registry.BLOCK, new Identifier(NAMESPACE, "casting_table"), CASTING_TABLE_BLOCK);
|
Registry.register(Registry.BLOCK, new Identifier(NAMESPACE, "casting_table"), CASTING_TABLE_BLOCK);
|
||||||
@ -103,28 +121,28 @@ public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
|||||||
ContainerProviderRegistry.INSTANCE.registerFactory(new Identifier(NAMESPACE, "casting_table"), (syncId, identifier, player, buf) -> {
|
ContainerProviderRegistry.INSTANCE.registerFactory(new Identifier(NAMESPACE, "casting_table"), (syncId, identifier, player, buf) -> {
|
||||||
final World world = player.world;
|
final World world = player.world;
|
||||||
final BlockPos pos = buf.readBlockPos();
|
final BlockPos pos = buf.readBlockPos();
|
||||||
return Objects.requireNonNull(world.getBlockState(pos).createContainerFactory(player.world, pos)).createMenu(syncId, player.inventory, player);
|
return Objects.requireNonNull(world.getBlockState(pos).createScreenHandlerFactory(player.world, pos)).createMenu(syncId, player.inventory, player);
|
||||||
});
|
});
|
||||||
|
|
||||||
CommandRegistry.INSTANCE.register(false, SpellCommand::register);
|
CommandRegistry.INSTANCE.register(false, SpellCommand::register);
|
||||||
|
|
||||||
ServerSidePacketRegistryImpl.INSTANCE.register(new Identifier(NAMESPACE, "select_spell"), SelectSpellC2SPacket::handle);
|
ServerSidePacketRegistryImpl.INSTANCE.register(new Identifier(NAMESPACE, "select_spell"), SelectSpellC2SPacket::handle);
|
||||||
ClientSidePacketRegistryImpl.INSTANCE.register(new Identifier(NAMESPACE, "update_known_spells"), UpdateKnownSpellsS2CPacket::handle);
|
|
||||||
|
|
||||||
LootTableLoadingCallback.EVENT.register((resourceManager, lootManager, id, supplier, setter) -> {
|
LootTableLoadingCallback.EVENT.register((resourceManager, lootManager, id, supplier, setter) -> {
|
||||||
if (isSelectedLootTable(id)) {
|
if (isSelectedLootTable(id)) {
|
||||||
FabricLootPoolBuilder poolBuilder = FabricLootPoolBuilder.builder()
|
FabricLootPoolBuilder poolBuilder = FabricLootPoolBuilder.builder()
|
||||||
.withRolls(new BinomialLootTableRange(2, 0.5f))
|
.rolls(new BinomialLootTableRange(2, 0.5f))
|
||||||
.withEntry(ItemEntry.builder(SPELL_ITEM))
|
.withEntry(ItemEntry.builder(SPELL_ITEM).build())
|
||||||
.withFunction(new RandomSpellLootTableFunction.Builder());
|
.withFunction(new RandomSpellLootTableFunction.Builder().build());
|
||||||
|
|
||||||
supplier.withPool(poolBuilder);
|
supplier.withPool(poolBuilder.build());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Registry.register(Registry.LOOT_FUNCTION_TYPE, new Identifier(NAMESPACE, "random_spell"), new LootFunctionType(new RandomSpellLootTableFunction.Factory()));
|
||||||
|
|
||||||
DispenserBlock.registerBehavior(SorceryCraft.SPELL_ITEM, new ProjectileDispenserBehavior() {
|
DispenserBlock.registerBehavior(SorceryCraft.SPELL_ITEM, new ProjectileDispenserBehavior() {
|
||||||
@Override
|
@Override
|
||||||
protected Projectile createProjectile(World position, Position stack, ItemStack itemStack) {
|
protected ProjectileEntity createProjectile(World position, Position stack, ItemStack itemStack) {
|
||||||
SpellEntity entity = new SpellEntity(position, stack.getX(), stack.getY(), stack.getZ());
|
SpellEntity entity = new SpellEntity(position, stack.getX(), stack.getY(), stack.getZ());
|
||||||
entity.setItem(itemStack);
|
entity.setItem(itemStack);
|
||||||
return entity;
|
return entity;
|
||||||
@ -135,24 +153,32 @@ public class SorceryCraft implements ModInitializer, ClientModInitializer {
|
|||||||
playSpellSound(pointer);
|
playSpellSound(pointer);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
INTERACT_WITH_CASTING_TABLE_STAT = registerStat("interact_with_casting_table");
|
||||||
|
CAST_SPELL_STAT = registerStat("cast_spell");
|
||||||
|
|
||||||
|
DISCOVER_ALL_SPELLS_CRITERION = CriteriaRegistryHook.callRegister(new DiscoverAllSpellsCriterion());
|
||||||
|
CREATE_SPELL_CRITERION = CriteriaRegistryHook.callRegister(new CreateSpellCriterion());
|
||||||
|
}
|
||||||
|
|
||||||
|
private Identifier registerStat(String name) {
|
||||||
|
Identifier statID = new Identifier(NAMESPACE, name);
|
||||||
|
Registry.register(Registry.CUSTOM_STAT, statID, statID);
|
||||||
|
Stats.CUSTOM.getOrCreateStat(statID, StatFormatter.DEFAULT);
|
||||||
|
return statID;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final SoundEvent SPELL_SOUND_EFFECT = SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE;
|
private static final SoundEvent SPELL_SOUND_EFFECT = SoundEvents.BLOCK_ENCHANTMENT_TABLE_USE;
|
||||||
|
|
||||||
|
public static void playSpellSound(World world, BlockPos pos) {
|
||||||
|
world.playSound(null, pos, SPELL_SOUND_EFFECT, SoundCategory.BLOCKS, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
public static void playSpellSound(BlockPointer block) {
|
public static void playSpellSound(BlockPointer block) {
|
||||||
block.getWorld().playSound(null, block.getBlockPos(), SPELL_SOUND_EFFECT, SoundCategory.BLOCKS, 1.0f, 1.0f);
|
playSpellSound(block.getWorld(), block.getBlockPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void playSpellSound(PlayerEntity player) {
|
public static void playSpellSound(PlayerEntity player) {
|
||||||
player.playSound(SPELL_SOUND_EFFECT, SoundCategory.PLAYERS, 1.0f, 1.0f);
|
player.playSound(SPELL_SOUND_EFFECT, SoundCategory.PLAYERS, 1.0f, 1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onInitializeClient() {
|
|
||||||
EntityRendererRegistry.INSTANCE.register(SPELL_ENTITY, (entityRenderDispatcher, context) -> new SpellEntityRenderer(entityRenderDispatcher));
|
|
||||||
ScreenProviderRegistry.INSTANCE.<CastingTableContainer>registerFactory(new Identifier(NAMESPACE, "casting_table"), (container) -> {
|
|
||||||
assert MinecraftClient.getInstance().player != null;
|
|
||||||
return new CastingTableScreen(container, MinecraftClient.getInstance().player.inventory, new TranslatableText("block." + SorceryCraft.NAMESPACE + ".casting_table"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.advancement;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import net.minecraft.advancement.criterion.AbstractCriterion;
|
||||||
|
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
|
||||||
|
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer;
|
||||||
|
import net.minecraft.predicate.entity.EntityPredicate;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class CreateSpellCriterion extends AbstractCriterion<CreateSpellCriterion.Conditions> {
|
||||||
|
private static final Identifier ID = new Identifier(SorceryCraft.NAMESPACE, "create_spell");
|
||||||
|
|
||||||
|
public CreateSpellCriterion() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Conditions conditionsFromJson(JsonObject obj, EntityPredicate.Extended playerPredicate, AdvancementEntityPredicateDeserializer predicateDeserializer) {
|
||||||
|
return new CreateSpellCriterion.Conditions(playerPredicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Identifier getId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trigger(ServerPlayerEntity player) {
|
||||||
|
test(player, (conditions) -> true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Conditions extends AbstractCriterionConditions {
|
||||||
|
public Conditions(EntityPredicate.Extended player) {
|
||||||
|
super(ID, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.advancement;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
|
||||||
|
import net.minecraft.advancement.criterion.AbstractCriterion;
|
||||||
|
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
|
||||||
|
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer;
|
||||||
|
import net.minecraft.predicate.entity.EntityPredicate;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class DiscoverAllSpellsCriterion extends AbstractCriterion<DiscoverAllSpellsCriterion.Conditions> {
|
||||||
|
private static final Identifier ID = new Identifier(SorceryCraft.NAMESPACE, "discover_all_spells");
|
||||||
|
|
||||||
|
public DiscoverAllSpellsCriterion() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Identifier getId() {
|
||||||
|
return ID;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected DiscoverAllSpellsCriterion.Conditions conditionsFromJson(JsonObject obj, EntityPredicate.Extended playerPredicate, AdvancementEntityPredicateDeserializer predicateDeserializer) {
|
||||||
|
return new DiscoverAllSpellsCriterion.Conditions(playerPredicate);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void trigger(ServerPlayerEntity player) {
|
||||||
|
test(player, (conditions) -> {
|
||||||
|
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||||
|
Map<Identifier, Integer> spells = spellPlayer.getDiscoveredSpells();
|
||||||
|
Spell[] maxSpells = SpellRegistry.getMaxSpells();
|
||||||
|
boolean match = true;
|
||||||
|
for (Spell spell : maxSpells) {
|
||||||
|
if (!spells.containsKey(spell.getID()) || spells.get(spell.getID()) < (spell.getLevel() - 1)) {
|
||||||
|
match = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return match;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Conditions extends AbstractCriterionConditions {
|
||||||
|
public Conditions(EntityPredicate.Extended player) {
|
||||||
|
super(ID, player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,17 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.block;
|
package com.thebrokenrail.sorcerycraft.block;
|
||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellServerPlayerEntity;
|
||||||
import net.fabricmc.fabric.api.block.FabricBlockSettings;
|
import net.fabricmc.fabric.api.block.FabricBlockSettings;
|
||||||
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
|
import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.Material;
|
import net.minecraft.block.Material;
|
||||||
import net.minecraft.container.BlockContext;
|
|
||||||
import net.minecraft.container.NameableContainerFactory;
|
|
||||||
import net.minecraft.container.SimpleNamedContainerFactory;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.screen.NamedScreenHandlerFactory;
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext;
|
||||||
|
import net.minecraft.screen.SimpleNamedScreenHandlerFactory;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
@ -28,12 +30,18 @@ public class CastingTableBlock extends Block {
|
|||||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||||
if (!world.isClient()) {
|
if (!world.isClient()) {
|
||||||
ContainerProviderRegistry.INSTANCE.openContainer(new Identifier(SorceryCraft.NAMESPACE, "casting_table"), player, (buf) -> buf.writeBlockPos(pos));
|
ContainerProviderRegistry.INSTANCE.openContainer(new Identifier(SorceryCraft.NAMESPACE, "casting_table"), player, (buf) -> buf.writeBlockPos(pos));
|
||||||
|
player.incrementStat(SorceryCraft.INTERACT_WITH_CASTING_TABLE_STAT);
|
||||||
}
|
}
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NameableContainerFactory createContainerFactory(BlockState state, World world, BlockPos pos) {
|
public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) {
|
||||||
return new SimpleNamedContainerFactory((i, playerInventory, playerEntity) -> new CastingTableContainer(i, playerInventory, BlockContext.create(world, pos)), new TranslatableText("container." + SorceryCraft.NAMESPACE + ".casting_table"));
|
return new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> {
|
||||||
|
if (!playerEntity.getEntityWorld().isClient()) {
|
||||||
|
((SpellServerPlayerEntity) playerEntity).sync();
|
||||||
|
}
|
||||||
|
return new CastingTableScreenHandler(i, playerInventory, ScreenHandlerContext.create(world, pos));
|
||||||
|
}, new TranslatableText("container." + SorceryCraft.NAMESPACE + ".casting_table"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.client;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.ModConfig;
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import io.github.prospector.modmenu.api.ConfigScreenFactory;
|
||||||
|
import io.github.prospector.modmenu.api.ModMenuApi;
|
||||||
|
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
|
import net.minecraft.client.gui.screen.Screen;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
public class ModMenu implements ModMenuApi {
|
||||||
|
@Override
|
||||||
|
public String getModId() {
|
||||||
|
return SorceryCraft.NAMESPACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ConfigScreenFactory<?> getModConfigScreenFactory() {
|
||||||
|
return (ConfigScreenFactory<Screen>) screen -> AutoConfig.getConfigScreen(ModConfig.class, screen).get();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.client;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.ModConfig;
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.client.entity.SpellEntityRenderer;
|
||||||
|
import com.thebrokenrail.sorcerycraft.client.gui.CastingTableScreen;
|
||||||
|
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
|
||||||
|
import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket;
|
||||||
|
import me.sargunvohra.mcmods.autoconfig1u.AutoConfig;
|
||||||
|
import me.sargunvohra.mcmods.autoconfig1u.gui.registry.GuiRegistry;
|
||||||
|
import me.sargunvohra.mcmods.autoconfig1u.util.Utils;
|
||||||
|
import me.shedaniel.clothconfig2.api.ConfigEntryBuilder;
|
||||||
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
|
import net.fabricmc.fabric.api.client.rendereregistry.v1.EntityRendererRegistry;
|
||||||
|
import net.fabricmc.fabric.api.client.screen.ScreenProviderRegistry;
|
||||||
|
import net.fabricmc.fabric.impl.networking.ClientSidePacketRegistryImpl;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
public class SorceryCraftClient implements ClientModInitializer {
|
||||||
|
@Override
|
||||||
|
public void onInitializeClient() {
|
||||||
|
GuiRegistry guiRegistry = AutoConfig.getGuiRegistry(ModConfig.class);
|
||||||
|
guiRegistry.registerAnnotationProvider((s, field, config, defaults, guiRegistryAccess) -> {
|
||||||
|
ModConfig.UsePercentage bounds = field.getAnnotation(ModConfig.UsePercentage.class);
|
||||||
|
return Collections.singletonList(ConfigEntryBuilder.create().startIntSlider(new TranslatableText(s), MathHelper.ceil(Utils.getUnsafely(field, config, 0.0) * 100), MathHelper.ceil(bounds.min() * 100), MathHelper.ceil(bounds.max() * 100)).setDefaultValue(() -> MathHelper.ceil((double) Utils.getUnsafely(field, defaults) * 100)).setSaveConsumer((newValue) -> Utils.setUnsafely(field, config, newValue / 100d)).setTextGetter(integer -> new LiteralText(String.format("%d%%", integer))).build());
|
||||||
|
}, field -> field.getType() == Double.TYPE || field.getType() == Double.class, ModConfig.UsePercentage.class);
|
||||||
|
|
||||||
|
EntityRendererRegistry.INSTANCE.register(SorceryCraft.SPELL_ENTITY, (entityRenderDispatcher, context) -> new SpellEntityRenderer(entityRenderDispatcher));
|
||||||
|
ScreenProviderRegistry.INSTANCE.<CastingTableScreenHandler>registerFactory(new Identifier(SorceryCraft.NAMESPACE, "casting_table"), (container) -> {
|
||||||
|
assert MinecraftClient.getInstance().player != null;
|
||||||
|
return new CastingTableScreen(container, MinecraftClient.getInstance().player.inventory, new TranslatableText("block." + SorceryCraft.NAMESPACE + ".casting_table"));
|
||||||
|
});
|
||||||
|
|
||||||
|
ClientSidePacketRegistryImpl.INSTANCE.register(new Identifier(SorceryCraft.NAMESPACE, "update_known_spells"), UpdateKnownSpellsS2CPacket::handle);
|
||||||
|
}
|
||||||
|
}
|
@ -1,236 +0,0 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.client.block;
|
|
||||||
|
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
|
||||||
import com.thebrokenrail.sorcerycraft.block.CastingTableContainer;
|
|
||||||
import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket;
|
|
||||||
import com.thebrokenrail.sorcerycraft.spell.Spell;
|
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
|
||||||
import net.fabricmc.api.EnvType;
|
|
||||||
import net.fabricmc.api.Environment;
|
|
||||||
import net.minecraft.client.font.TextRenderer;
|
|
||||||
import net.minecraft.client.gui.screen.ingame.ContainerScreen;
|
|
||||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
|
||||||
public class CastingTableScreen extends ContainerScreen<CastingTableContainer> {
|
|
||||||
private static final Identifier TEXTURE = new Identifier("textures/gui/container/villager2.png");
|
|
||||||
private int selectedIndex;
|
|
||||||
private int indexStartOffset;
|
|
||||||
private boolean scrolling;
|
|
||||||
|
|
||||||
public CastingTableScreen(CastingTableContainer container, PlayerInventory inventory, Text title) {
|
|
||||||
super(container, inventory, title);
|
|
||||||
containerWidth = 276;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void drawForeground(int mouseX, int mouseY) {
|
|
||||||
int j = containerHeight - 94;
|
|
||||||
font.draw(title.asFormattedString(), (float) (49 + this.containerWidth / 2 - font.getStringWidth(title.asFormattedString()) / 2), 6.0F, 4210752);
|
|
||||||
font.draw(playerInventory.getDisplayName().asFormattedString(), 107.0F, (float) j, 4210752);
|
|
||||||
String spells = new TranslatableText("container." + SorceryCraft.NAMESPACE + ".spells").getString();
|
|
||||||
font.draw(spells, (float) (5 - font.getStringWidth(spells) / 2 + 48), 6.0F, 4210752);
|
|
||||||
renderXPCost();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void drawBackground(float delta, int mouseX, int mouseY) {
|
|
||||||
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
|
||||||
assert minecraft != null;
|
|
||||||
minecraft.getTextureManager().bindTexture(TEXTURE);
|
|
||||||
int i = (width - containerWidth) / 2;
|
|
||||||
int j = (height - containerHeight) / 2;
|
|
||||||
blit(i, j, this.getBlitOffset(), 0.0F, 0.0F, containerWidth, containerHeight, 256, 512);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void render(int mouseX, int mouseY, float delta) {
|
|
||||||
renderBackground();
|
|
||||||
super.render(mouseX, mouseY, delta);
|
|
||||||
drawMouseoverTooltip(mouseX, mouseY);
|
|
||||||
|
|
||||||
renderScrollbar();
|
|
||||||
renderItems();
|
|
||||||
|
|
||||||
for (WidgetButtonPage button : buttons) {
|
|
||||||
if (button.isHovered()) {
|
|
||||||
button.renderToolTip(mouseX, mouseY);
|
|
||||||
}
|
|
||||||
button.visible = button.index < container.getRecipes().length;
|
|
||||||
if (button.visible) {
|
|
||||||
Spell spell = container.getRecipes()[button.getIndex() + indexStartOffset];
|
|
||||||
button.setMessage(SpellTag.getTranslatedSpell(spell.getID(), spell.getLevel()).getString());
|
|
||||||
button.setFocused((button.getIndex() + indexStartOffset) == selectedIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderScrollbar() {
|
|
||||||
Spell[] spells = container.getRecipes();
|
|
||||||
assert minecraft != null;
|
|
||||||
minecraft.getTextureManager().bindTexture(TEXTURE);
|
|
||||||
int i = (width - containerWidth) / 2;
|
|
||||||
int j = (height - containerHeight) / 2;
|
|
||||||
int k = spells.length + 1 - 7;
|
|
||||||
|
|
||||||
if (k > 1) {
|
|
||||||
int l = 139 - (27 + (k - 1) * 139 / k);
|
|
||||||
int m = 1 + l / k + 139 / k;
|
|
||||||
int o = Math.min(113, indexStartOffset * m);
|
|
||||||
if (this.indexStartOffset == k - 1) {
|
|
||||||
o = 113;
|
|
||||||
}
|
|
||||||
|
|
||||||
blit(i + 94, j + 18 + o, getBlitOffset(), 0.0F, 199.0F, 6, 27, 256, 512);
|
|
||||||
} else {
|
|
||||||
blit(i + 94, j + 18, getBlitOffset(), 6.0F, 199.0F, 6, 27, 256, 512);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderItems() {
|
|
||||||
int i = (width - containerWidth) / 2;
|
|
||||||
int j = (height - containerHeight) / 2;
|
|
||||||
int k = j + 16 + 1;
|
|
||||||
|
|
||||||
Spell[] spells = container.getRecipes();
|
|
||||||
for (int x = 0; x < spells.length; x++) {
|
|
||||||
if (!canScroll(spells.length) || (x >= indexStartOffset && x < 7 + indexStartOffset)) {
|
|
||||||
ItemStack itemStack = spells[x].getItemCost();
|
|
||||||
itemRenderer.zOffset = 100.0F;
|
|
||||||
int n = k + 2;
|
|
||||||
|
|
||||||
itemRenderer.renderGuiItem(itemStack, i + 5 + 68, n);
|
|
||||||
itemRenderer.renderGuiItemOverlay(font, itemStack, i + 5 + 68, n);
|
|
||||||
itemRenderer.zOffset = 0.0F;
|
|
||||||
k += 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void renderXPCost() {
|
|
||||||
if (container.getRecipes().length > 0) {
|
|
||||||
int i = container.getRecipes()[selectedIndex].getXPCost();
|
|
||||||
int j = 8453920;
|
|
||||||
assert minecraft != null;
|
|
||||||
assert minecraft.player != null;
|
|
||||||
String string = new TranslatableText("container.repair.cost", i).getString();
|
|
||||||
if (!container.canTakeResult(playerInventory.player)) {
|
|
||||||
j = 16736352;
|
|
||||||
}
|
|
||||||
|
|
||||||
int x2 = containerWidth - 8;
|
|
||||||
int x1 = x2 - font.getStringWidth(string);
|
|
||||||
fill(x1, 65, x2, 77, 1325400064);
|
|
||||||
font.drawWithShadow(string, (float) x1, 67.0F, j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canScroll(int listSize) {
|
|
||||||
return listSize > 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mouseScrolled(double d, double e, double amount) {
|
|
||||||
int i = container.getRecipes().length;
|
|
||||||
if (this.canScroll(i)) {
|
|
||||||
int j = i - 7;
|
|
||||||
indexStartOffset = (int) ((double) indexStartOffset - amount);
|
|
||||||
indexStartOffset = MathHelper.clamp(indexStartOffset, 0, j);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
|
||||||
int i = container.getRecipes().length;
|
|
||||||
if (scrolling) {
|
|
||||||
int j = y + 18;
|
|
||||||
int k = j + 139;
|
|
||||||
int l = i - 7;
|
|
||||||
float f = ((float) mouseY - (float) j - 13.5F) / ((float) (k - j) - 27.0F);
|
|
||||||
f = f * (float) l + 0.5F;
|
|
||||||
indexStartOffset = MathHelper.clamp((int) f, 0, l);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
|
||||||
scrolling = false;
|
|
||||||
int i = (width - containerWidth) / 2;
|
|
||||||
int j = (height - containerHeight) / 2;
|
|
||||||
if (this.canScroll(container.getRecipes().length) && mouseX > (double) (i + 94) && mouseX < (double) (i + 94 + 6) && mouseY > (double) (j + 18) && mouseY <= (double) (j + 18 + 139 + 1)) {
|
|
||||||
scrolling = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.mouseClicked(mouseX, mouseY, button);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void syncRecipeIndex() {
|
|
||||||
container.setIndex(selectedIndex);
|
|
||||||
assert minecraft != null;
|
|
||||||
SelectSpellC2SPacket.send(minecraft, selectedIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private final WidgetButtonPage[] buttons = new WidgetButtonPage[7];
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void init() {
|
|
||||||
super.init();
|
|
||||||
int i = (width - containerWidth) / 2;
|
|
||||||
int j = (height - containerHeight) / 2;
|
|
||||||
int k = j + 16 + 2;
|
|
||||||
|
|
||||||
for (int l = 0; l < 7; ++l) {
|
|
||||||
buttons[l] = addButton(new WidgetButtonPage(i + 5, k, l, (buttonWidget) -> {
|
|
||||||
selectedIndex = ((WidgetButtonPage) buttonWidget).getIndex() + indexStartOffset;
|
|
||||||
syncRecipeIndex();
|
|
||||||
}));
|
|
||||||
k += 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
|
||||||
private class WidgetButtonPage extends ButtonWidget {
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
public WidgetButtonPage(int i, int j, int k, PressAction pressAction) {
|
|
||||||
super(i, j, 89, 20, "", pressAction);
|
|
||||||
index = k;
|
|
||||||
visible = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setFocused(boolean state) {
|
|
||||||
super.setFocused(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getIndex() {
|
|
||||||
return this.index;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void renderToolTip(int mouseX, int mouseY) {
|
|
||||||
if (isHovered && container.getRecipes().length > index + indexStartOffset && mouseX > this.x + 65) {
|
|
||||||
ItemStack itemStack = container.getRecipes()[index + indexStartOffset].getItemCost();
|
|
||||||
if (!itemStack.isEmpty()) {
|
|
||||||
renderTooltip(itemStack, mouseX, mouseY);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void drawCenteredString(TextRenderer textRenderer, String str, int ignored, int y, int color) {
|
|
||||||
drawString(textRenderer, str, x + 5, y, color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +1,20 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.client.entity;
|
package com.thebrokenrail.sorcerycraft.client.entity;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
||||||
import net.fabricmc.api.EnvType;
|
import net.fabricmc.api.EnvType;
|
||||||
import net.fabricmc.api.Environment;
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
import net.minecraft.client.render.entity.EntityRenderDispatcher;
|
||||||
import net.minecraft.client.render.entity.EntityRenderer;
|
import net.minecraft.client.render.entity.EntityRenderer;
|
||||||
import net.minecraft.container.PlayerContainer;
|
|
||||||
import net.minecraft.entity.AreaEffectCloudEntity;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
@Environment(EnvType.CLIENT)
|
@Environment(EnvType.CLIENT)
|
||||||
public class SpellEntityRenderer extends EntityRenderer<AreaEffectCloudEntity> {
|
public class SpellEntityRenderer extends EntityRenderer<SpellEntity> {
|
||||||
public SpellEntityRenderer(EntityRenderDispatcher entityRenderDispatcher) {
|
public SpellEntityRenderer(EntityRenderDispatcher entityRenderDispatcher) {
|
||||||
super(entityRenderDispatcher);
|
super(entityRenderDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Identifier getTexture(AreaEffectCloudEntity areaEffectCloudEntity) {
|
public Identifier getTexture(SpellEntity spellEntity) {
|
||||||
return PlayerContainer.BLOCK_ATLAS_TEXTURE;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,231 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.client.gui;
|
||||||
|
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
|
||||||
|
import com.thebrokenrail.sorcerycraft.packet.SelectSpellC2SPacket;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
|
import net.minecraft.client.gui.screen.ingame.HandledScreen;
|
||||||
|
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
public class CastingTableScreen extends HandledScreen<CastingTableScreenHandler> {
|
||||||
|
private static final Identifier TEXTURE = new Identifier("textures/gui/container/villager2.png");
|
||||||
|
private int selectedIndex = 0;
|
||||||
|
private int indexStartOffset = 0;
|
||||||
|
private boolean scrolling = false;
|
||||||
|
|
||||||
|
public CastingTableScreen(CastingTableScreenHandler container, PlayerInventory inventory, Text title) {
|
||||||
|
super(container, inventory, title);
|
||||||
|
backgroundWidth = 276;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawForeground(MatrixStack matrixStack, int i, int j) {
|
||||||
|
int titleY = backgroundHeight - 94;
|
||||||
|
textRenderer.draw(matrixStack, title, (float) (49 + this.backgroundWidth / 2 - textRenderer.getWidth(title) / 2), 6.0F, 4210752);
|
||||||
|
textRenderer.draw(matrixStack, playerInventory.getDisplayName(), 107.0F, (float) titleY, 4210752);
|
||||||
|
Text spells = new TranslatableText("container." + SorceryCraft.NAMESPACE + ".spells");
|
||||||
|
textRenderer.draw(matrixStack, spells, (float) (5 - textRenderer.getWidth(spells) / 2 + 48), 6.0F, 4210752);
|
||||||
|
renderXPCost(matrixStack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void resetIndex() {
|
||||||
|
selectedIndex = 0;
|
||||||
|
indexStartOffset = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void drawBackground(MatrixStack matrixStack, float delta, int mouseX, int mouseY) {
|
||||||
|
RenderSystem.color4f(1.0F, 1.0F, 1.0F, 1.0F);
|
||||||
|
assert client != null;
|
||||||
|
client.getTextureManager().bindTexture(TEXTURE);
|
||||||
|
int i = (width - backgroundWidth) / 2;
|
||||||
|
int j = (height - backgroundHeight) / 2;
|
||||||
|
drawTexture(matrixStack, i, j, getZOffset(), 0.0F, 0.0F, backgroundWidth, backgroundHeight, 256, 512);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrixStack, int mouseX, int mouseY, float delta) {
|
||||||
|
renderBackground(matrixStack);
|
||||||
|
super.render(matrixStack, mouseX, mouseY, delta);
|
||||||
|
drawMouseoverTooltip(matrixStack, mouseX, mouseY);
|
||||||
|
|
||||||
|
renderScrollbar(matrixStack);
|
||||||
|
renderItems();
|
||||||
|
|
||||||
|
for (WidgetButtonPage button : buttons) {
|
||||||
|
if (button.isHovered()) {
|
||||||
|
button.renderToolTip(matrixStack, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
button.visible = button.index < handler.getRecipes().length;
|
||||||
|
if (button.visible) {
|
||||||
|
Spell spell = handler.getRecipes()[button.getIndex() + indexStartOffset];
|
||||||
|
button.setMessage(SpellHelper.getTranslatedSpell(spell.getID(), spell.getLevel()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderScrollbar(MatrixStack matrixStack) {
|
||||||
|
Spell[] spells = handler.getRecipes();
|
||||||
|
assert client != null;
|
||||||
|
client.getTextureManager().bindTexture(TEXTURE);
|
||||||
|
int i = (width - backgroundWidth) / 2;
|
||||||
|
int j = (height - backgroundHeight) / 2;
|
||||||
|
int k = spells.length - 7;
|
||||||
|
|
||||||
|
if (k > 0) {
|
||||||
|
int modifier = (int) (((float) indexStartOffset / k) * (1 + 139 - 27));
|
||||||
|
drawTexture(matrixStack, i + 94, j + 18 + modifier, getZOffset(), 0.0F, 199.0F, 6, 27, 256, 512);
|
||||||
|
} else {
|
||||||
|
drawTexture(matrixStack, i + 94, j + 18, getZOffset(), 6.0F, 199.0F, 6, 27, 256, 512);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderItems() {
|
||||||
|
int i = (width - backgroundWidth) / 2;
|
||||||
|
int j = (height - backgroundHeight) / 2;
|
||||||
|
int k = j + 16 + 1;
|
||||||
|
|
||||||
|
Spell[] spells = handler.getRecipes();
|
||||||
|
for (int x = 0; x < spells.length; x++) {
|
||||||
|
if (!canScroll(spells.length) || (x >= indexStartOffset && x < 7 + indexStartOffset)) {
|
||||||
|
ItemStack itemStack = spells[x].getItemCost();
|
||||||
|
itemRenderer.zOffset = 100.0F;
|
||||||
|
int y = k + 2;
|
||||||
|
|
||||||
|
itemRenderer.renderInGuiWithOverrides(itemStack, i + 5 + 68, y);
|
||||||
|
itemRenderer.renderGuiItemOverlay(textRenderer, itemStack, i + 5 + 68, y);
|
||||||
|
itemRenderer.zOffset = 0.0F;
|
||||||
|
k += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void renderXPCost(MatrixStack matrixStack) {
|
||||||
|
if (handler.getRecipes().length > 0) {
|
||||||
|
int cost = handler.getRecipes()[selectedIndex].getXPCost();
|
||||||
|
int color = 8453920;
|
||||||
|
assert client != null;
|
||||||
|
assert client.player != null;
|
||||||
|
Text string = new TranslatableText("container.repair.cost", cost);
|
||||||
|
if (!handler.canTakeResult(playerInventory.player)) {
|
||||||
|
color = 16736352;
|
||||||
|
}
|
||||||
|
|
||||||
|
int x2 = backgroundWidth - 8;
|
||||||
|
int x1 = x2 - textRenderer.getWidth(string);
|
||||||
|
fill(matrixStack, x1, 65, x2, 77, 1325400064);
|
||||||
|
textRenderer.drawWithShadow(matrixStack, string, (float) x1, 67.0F, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canScroll(int listSize) {
|
||||||
|
return listSize > 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseScrolled(double d, double e, double amount) {
|
||||||
|
int i = handler.getRecipes().length;
|
||||||
|
if (canScroll(i)) {
|
||||||
|
int j = i - 7;
|
||||||
|
indexStartOffset = (int) ((double) indexStartOffset - amount);
|
||||||
|
indexStartOffset = MathHelper.clamp(indexStartOffset, 0, j);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseDragged(double mouseX, double mouseY, int button, double deltaX, double deltaY) {
|
||||||
|
int i = handler.getRecipes().length;
|
||||||
|
if (scrolling) {
|
||||||
|
int j = y + 18;
|
||||||
|
int k = j + 139;
|
||||||
|
int l = i - 7;
|
||||||
|
float f = ((float) mouseY - (float) j - 13.5F) / ((float) (k - j) - 27.0F);
|
||||||
|
f = f * (float) l + 0.5F;
|
||||||
|
indexStartOffset = MathHelper.clamp((int) f, 0, l);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return super.mouseDragged(mouseX, mouseY, button, deltaX, deltaY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||||
|
scrolling = false;
|
||||||
|
int i = (width - backgroundWidth) / 2;
|
||||||
|
int j = (height - backgroundHeight) / 2;
|
||||||
|
if (canScroll(handler.getRecipes().length) && mouseX > (double) (i + 94) && mouseX < (double) (i + 94 + 6) && mouseY > (double) (j + 18) && mouseY <= (double) (j + 18 + 139 + 1)) {
|
||||||
|
scrolling = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return super.mouseClicked(mouseX, mouseY, button);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void syncRecipeIndex() {
|
||||||
|
handler.setIndex(selectedIndex);
|
||||||
|
assert client != null;
|
||||||
|
SelectSpellC2SPacket.send(client, selectedIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
private final WidgetButtonPage[] buttons = new WidgetButtonPage[7];
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void init() {
|
||||||
|
super.init();
|
||||||
|
int i = (width - backgroundWidth) / 2;
|
||||||
|
int j = (height - backgroundHeight) / 2;
|
||||||
|
int k = j + 16 + 2;
|
||||||
|
|
||||||
|
for (int l = 0; l < 7; ++l) {
|
||||||
|
buttons[l] = addButton(new WidgetButtonPage(i + 5, k, l, (buttonWidget) -> {
|
||||||
|
selectedIndex = ((WidgetButtonPage) buttonWidget).getIndex() + indexStartOffset;
|
||||||
|
syncRecipeIndex();
|
||||||
|
}));
|
||||||
|
k += 20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
public class WidgetButtonPage extends ButtonWidget {
|
||||||
|
final int index;
|
||||||
|
|
||||||
|
public WidgetButtonPage(int i, int j, int k, PressAction pressAction) {
|
||||||
|
super(i, j, 89, 20, new LiteralText(""), pressAction);
|
||||||
|
index = k;
|
||||||
|
visible = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void render(MatrixStack matrixStack, int mouseX, int mouseY, float delta) {
|
||||||
|
active = (index + CastingTableScreen.this.indexStartOffset) != CastingTableScreen.this.selectedIndex;
|
||||||
|
super.render(matrixStack, mouseX, mouseY, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndex() {
|
||||||
|
return this.index;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renderToolTip(MatrixStack matrixStack, int mouseX, int mouseY) {
|
||||||
|
if (hovered && handler.getRecipes().length > index + indexStartOffset && mouseX > this.x + 65) {
|
||||||
|
ItemStack itemStack = handler.getRecipes()[index + indexStartOffset].getItemCost();
|
||||||
|
if (!itemStack.isEmpty()) {
|
||||||
|
renderTooltip(matrixStack, itemStack, mouseX, mouseY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.command;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.StringReader;
|
||||||
|
import com.mojang.brigadier.arguments.ArgumentType;
|
||||||
|
import com.mojang.brigadier.context.CommandContext;
|
||||||
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
|
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
import com.mojang.brigadier.suggestion.Suggestions;
|
||||||
|
import com.mojang.brigadier.suggestion.SuggestionsBuilder;
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
|
import net.minecraft.command.CommandSource;
|
||||||
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
public class SpellArgumentType implements ArgumentType<Identifier> {
|
||||||
|
private static final Collection<String> EXAMPLES = Arrays.asList("sorcerycraft:heal_spell", "sorcerycraft:damage_spell");
|
||||||
|
public static final DynamicCommandExceptionType NOT_FOUND_EXCEPTION = new DynamicCommandExceptionType((object) -> new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.unknown_spell", object));
|
||||||
|
|
||||||
|
public SpellArgumentType() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static SpellArgumentType spell() {
|
||||||
|
return new SpellArgumentType();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Identifier getSpell(CommandContext<ServerCommandSource> context, String name) throws CommandSyntaxException {
|
||||||
|
return validate(context.getArgument(name, Identifier.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Identifier validate(Identifier identifier) throws CommandSyntaxException {
|
||||||
|
Spell testSpell = SpellRegistry.getSpell(identifier, 0);
|
||||||
|
if (testSpell == null) {
|
||||||
|
throw NOT_FOUND_EXCEPTION.create(identifier);
|
||||||
|
}
|
||||||
|
return identifier;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public <S> CompletableFuture<Suggestions> listSuggestions(CommandContext<S> context, SuggestionsBuilder builder) {
|
||||||
|
return CommandSource.suggestIdentifiers(Arrays.asList(SpellRegistry.getSpellsID()), builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Identifier parse(StringReader stringReader) throws CommandSyntaxException {
|
||||||
|
return validate(Identifier.fromCommandInput(stringReader));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Collection<String> getExamples() {
|
||||||
|
return EXAMPLES;
|
||||||
|
}
|
||||||
|
}
|
@ -1,47 +1,175 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.command;
|
package com.thebrokenrail.sorcerycraft.command;
|
||||||
|
|
||||||
import com.mojang.brigadier.CommandDispatcher;
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import com.mojang.brigadier.arguments.IntegerArgumentType;
|
||||||
|
import com.mojang.brigadier.exceptions.DynamicCommandExceptionType;
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity;
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
import net.minecraft.command.arguments.EntityArgumentType;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
|
||||||
|
import net.minecraft.command.argument.EntityArgumentType;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.Texts;
|
||||||
import net.minecraft.text.TranslatableText;
|
import net.minecraft.text.TranslatableText;
|
||||||
import net.minecraft.util.Formatting;
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class SpellCommand {
|
public class SpellCommand {
|
||||||
|
private static final DynamicCommandExceptionType NOT_HOLDING_SPELL_EXCEPTION = new DynamicCommandExceptionType(object -> new TranslatableText("command."+ SorceryCraft.NAMESPACE + ".spell.not_holding_spell", object));
|
||||||
|
|
||||||
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
|
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
|
||||||
dispatcher.register(CommandManager.literal("spell")
|
dispatcher.register(CommandManager.literal("spell")
|
||||||
.requires(source -> source.hasPermissionLevel(4))
|
.requires(source -> source.hasPermissionLevel(2))
|
||||||
.then(CommandManager.literal("list")
|
.then(CommandManager.literal("list")
|
||||||
.then(CommandManager.argument("player", EntityArgumentType.player())
|
.then(CommandManager.argument("player", EntityArgumentType.players())
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
PlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
|
int i = 0;
|
||||||
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.listing_spells", player.getDisplayName()), false);
|
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
|
||||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
for (PlayerEntity player : players) {
|
||||||
Map<Identifier, Integer> spells = spellPlayer.getSpells();
|
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||||
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
Map<Identifier, Integer> spellMap = spellPlayer.getDiscoveredSpells();
|
||||||
ctx.getSource().sendFeedback(SpellTag.getTranslatedSpell(entry.getKey(), entry.getValue()).formatted(Formatting.YELLOW), false);
|
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.listing_spells", player.getDisplayName(), Texts.join(spellMap.entrySet(), spell -> SpellHelper.getTranslatedSpell(spell.getKey(), spell.getValue()))), false);
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
return 0;
|
return i;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.then(CommandManager.literal("clear")
|
.then(CommandManager.literal("forget")
|
||||||
.then(CommandManager.argument("player", EntityArgumentType.player())
|
.then(CommandManager.argument("player", EntityArgumentType.players())
|
||||||
.executes(ctx -> {
|
.executes(ctx -> {
|
||||||
PlayerEntity player = EntityArgumentType.getPlayer(ctx, "player");
|
int i = 0;
|
||||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
|
||||||
spellPlayer.setSpells(new HashMap<>());
|
for (PlayerEntity player : players) {
|
||||||
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.cleared_spells", player.getDisplayName()), true);
|
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||||
return 1;
|
Map<Identifier, Integer> spells = spellPlayer.getDiscoveredSpells();
|
||||||
|
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
||||||
|
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(entry.getKey(), entry.getValue())), true);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
spellPlayer.setDiscoveredSpells(new HashMap<>());
|
||||||
|
}
|
||||||
|
return i;
|
||||||
})
|
})
|
||||||
|
.then(CommandManager.argument("spell", SpellArgumentType.spell())
|
||||||
|
.executes(ctx -> {
|
||||||
|
int i = 0;
|
||||||
|
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
|
||||||
|
for (PlayerEntity player : players) {
|
||||||
|
Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
|
||||||
|
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||||
|
Map<Identifier, Integer> spells = spellPlayer.getDiscoveredSpells();
|
||||||
|
if (spells.containsKey(spell)) {
|
||||||
|
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(spell, spells.get(spell))), true);
|
||||||
|
spells.remove(spell);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
spellPlayer.setDiscoveredSpells(spells);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("discover")
|
||||||
|
.then(CommandManager.argument("player", EntityArgumentType.players())
|
||||||
|
.executes(ctx -> {
|
||||||
|
int i = 0;
|
||||||
|
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
|
||||||
|
for (PlayerEntity player : players) {
|
||||||
|
Map<Identifier, Integer> spellMap = new HashMap<>();
|
||||||
|
Spell[] maxSpells = SpellRegistry.getMaxSpells();
|
||||||
|
for (Spell spell : maxSpells) {
|
||||||
|
spellMap.put(spell.getID(), spell.getLevel());
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
SpellHelper.learnSpells(player, spellMap);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
})
|
||||||
|
.then(CommandManager.argument("spell", SpellArgumentType.spell())
|
||||||
|
.then(CommandManager.argument("level", IntegerArgumentType.integer())
|
||||||
|
.executes(ctx -> {
|
||||||
|
int i = 0;
|
||||||
|
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
|
||||||
|
for (PlayerEntity player : players) {
|
||||||
|
Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
|
||||||
|
int level = IntegerArgumentType.getInteger(ctx, "level") - 1;
|
||||||
|
Map<Identifier, Integer> spellMap = new HashMap<>();
|
||||||
|
spellMap.put(spell, level);
|
||||||
|
i++;
|
||||||
|
SpellHelper.learnSpells(player, spellMap);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("apply")
|
||||||
|
.then(CommandManager.argument("player", EntityArgumentType.players())
|
||||||
|
.then(CommandManager.argument("spell", SpellArgumentType.spell())
|
||||||
|
.then(CommandManager.argument("level", IntegerArgumentType.integer())
|
||||||
|
.executes(ctx -> {
|
||||||
|
int i = 0;
|
||||||
|
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
|
||||||
|
for (PlayerEntity player : players) {
|
||||||
|
Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
|
||||||
|
int level = IntegerArgumentType.getInteger(ctx, "level") - 1;
|
||||||
|
|
||||||
|
ItemStack stack = player.getMainHandStack();
|
||||||
|
|
||||||
|
if (stack.getItem() != SorceryCraft.SPELL_ITEM) {
|
||||||
|
throw NOT_HOLDING_SPELL_EXCEPTION.create(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Identifier, Integer> spellMap = SpellHelper.getSpells(stack);
|
||||||
|
spellMap.put(spell, level);
|
||||||
|
i++;
|
||||||
|
SpellHelper.setSpells(stack, spellMap);
|
||||||
|
|
||||||
|
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.applied_spell", SpellHelper.getTranslatedSpell(spell, level)), true);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
})
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.then(CommandManager.literal("remove")
|
||||||
|
.then(CommandManager.argument("player", EntityArgumentType.players())
|
||||||
|
.then(CommandManager.argument("spell", SpellArgumentType.spell())
|
||||||
|
.executes(ctx -> {
|
||||||
|
int i = 0;
|
||||||
|
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
|
||||||
|
for (PlayerEntity player : players) {
|
||||||
|
Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
|
||||||
|
|
||||||
|
ItemStack stack = player.getMainHandStack();
|
||||||
|
|
||||||
|
if (stack.getItem() != SorceryCraft.SPELL_ITEM) {
|
||||||
|
throw NOT_HOLDING_SPELL_EXCEPTION.create(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Identifier, Integer> spellMap = SpellHelper.getSpells(stack);
|
||||||
|
if (spellMap.containsKey(spell)) {
|
||||||
|
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.removed_spell", SpellHelper.getTranslatedSpell(spell, spellMap.get(spell))), true);
|
||||||
|
spellMap.remove(spell);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
SpellHelper.setSpells(stack, spellMap);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
})
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
@ -1,28 +1,34 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.entity;
|
package com.thebrokenrail.sorcerycraft.entity;
|
||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.Spell;
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellRegistry;
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.Spells;
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.Spells;
|
||||||
import net.fabricmc.api.EnvType;
|
|
||||||
import net.fabricmc.api.Environment;
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.thrown.ThrownItemEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.entity.projectile.thrown.ThrownItemEntity;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.network.Packet;
|
import net.minecraft.network.Packet;
|
||||||
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
|
import net.minecraft.network.packet.s2c.play.EntitySpawnS2CPacket;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvents;
|
import net.minecraft.sound.SoundEvents;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
import net.minecraft.util.hit.EntityHitResult;
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
import net.minecraft.util.hit.HitResult;
|
import net.minecraft.util.hit.HitResult;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
public class SpellEntity extends ThrownItemEntity {
|
public class SpellEntity extends ThrownItemEntity {
|
||||||
public SpellEntity(EntityType<SpellEntity> entityType, World world) {
|
public SpellEntity(EntityType<SpellEntity> entityType, World world) {
|
||||||
super(entityType, world);
|
super(entityType, world);
|
||||||
@ -32,75 +38,78 @@ public class SpellEntity extends ThrownItemEntity {
|
|||||||
super(SorceryCraft.SPELL_ENTITY, owner, world);
|
super(SorceryCraft.SPELL_ENTITY, owner, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean firstTick = true;
|
|
||||||
|
|
||||||
public SpellEntity(World world, double x, double y, double z) {
|
public SpellEntity(World world, double x, double y, double z) {
|
||||||
super(SorceryCraft.SPELL_ENTITY, x, y, z, world);
|
super(SorceryCraft.SPELL_ENTITY, x, y, z, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SpellEntity(World world) {
|
||||||
|
super(SorceryCraft.SPELL_ENTITY, world);
|
||||||
|
}
|
||||||
|
|
||||||
private boolean didSpellSucceed(Map<Identifier, Integer> spells) {
|
private boolean didSpellSucceed(Map<Identifier, Integer> spells) {
|
||||||
return Math.random() > SorceryCraft.SPELL_FAILURE_CHANCE || spells.containsKey(Spells.STEADFAST_SPELL);
|
return Math.random() > SorceryCraft.getConfig().failureChance || spells.containsKey(Spells.STEADFAST_SPELL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCollision(HitResult hitResult) {
|
protected void onCollision(HitResult hitResult) {
|
||||||
Map<Identifier, Integer> spells = SpellTag.getSpells(getItem());
|
super.onCollision(hitResult);
|
||||||
if (!spells.containsKey(Spells.INWARD_SPELL)) {
|
if (!getEntityWorld().isClient()) {
|
||||||
if (hitResult.getType() == HitResult.Type.BLOCK) {
|
Map<Identifier, Integer> spells = SpellHelper.getSpells(getItem());
|
||||||
remove();
|
if (!spells.containsKey(Spells.INWARD_SPELL)) {
|
||||||
} else if (hitResult.getType() == HitResult.Type.ENTITY) {
|
|
||||||
Entity entity = ((EntityHitResult) hitResult).getEntity();
|
|
||||||
|
|
||||||
boolean success = didSpellSucceed(spells);
|
boolean success = didSpellSucceed(spells);
|
||||||
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
||||||
Spell spell = SpellRegistry.getSpell(entry.getKey(), entry.getValue());
|
Spell spell = SpellRegistry.getSpell(entry);
|
||||||
if (spell != null) {
|
if (spell != null) {
|
||||||
if (success) {
|
if (success) {
|
||||||
spell.execute(entity, this, getOwner());
|
if (hitResult.getType() == HitResult.Type.BLOCK) {
|
||||||
|
BlockHitResult blockHitResult = (BlockHitResult) hitResult;
|
||||||
|
spell.execute(getEntityWorld(), this, getOwner(), blockHitResult);
|
||||||
|
} else if (hitResult.getType() == HitResult.Type.ENTITY) {
|
||||||
|
Entity entity = ((EntityHitResult) hitResult).getEntity();
|
||||||
|
spell.execute(world, this, getOwner(), entity);
|
||||||
|
}
|
||||||
} else if (getOwner() != null) {
|
} else if (getOwner() != null) {
|
||||||
getOwner().playSound(SoundEvents.ENCHANT_THORNS_HIT, 1.0f, 1.0f);
|
if (getOwner() instanceof PlayerEntity) {
|
||||||
spell.execute(getOwner(), this, getOwner());
|
PlayerEntity player = (PlayerEntity) getOwner();
|
||||||
|
player.playSound(SoundEvents.ENCHANT_THORNS_HIT, SoundCategory.PLAYERS, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
|
spell.execute(world, this, getOwner(), getOwner());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
remove();
|
remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
@Environment(EnvType.CLIENT)
|
|
||||||
public void handleStatus(byte status) {
|
|
||||||
if (status == 0) {
|
|
||||||
for (int i = 0; i < 12; i++) {
|
|
||||||
getEntityWorld().addParticle(ParticleTypes.WITCH, getX(), getY(), getZ(), 0.0d, 0.0d, 0.0d);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.tick();
|
super.tick();
|
||||||
if (firstTick) {
|
if (!getEntityWorld().isClient()) {
|
||||||
firstTick = false;
|
Map<Identifier, Integer> spells = SpellHelper.getSpells(getItem());
|
||||||
Map<Identifier, Integer> spells = SpellTag.getSpells(getItem());
|
|
||||||
if (spells.containsKey(Spells.INWARD_SPELL)) {
|
if (spells.containsKey(Spells.INWARD_SPELL)) {
|
||||||
if (getOwner() != null) {
|
if (getOwner() != null) {
|
||||||
boolean success = didSpellSucceed(spells);
|
boolean success = didSpellSucceed(spells);
|
||||||
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
||||||
Spell spell = SpellRegistry.getSpell(entry.getKey(), entry.getValue());
|
Spell spell = SpellRegistry.getSpell(entry);
|
||||||
if (spell != null && success) {
|
if (spell != null) {
|
||||||
spell.execute(getOwner(), this, getOwner());
|
if (success) {
|
||||||
|
spell.execute(world, this, getOwner(), getOwner());
|
||||||
|
} else if (getOwner() instanceof PlayerEntity) {
|
||||||
|
PlayerEntity player = (PlayerEntity) getOwner();
|
||||||
|
player.playSound(SoundEvents.ENCHANT_THORNS_HIT, SoundCategory.PLAYERS, 1.0f, 1.0f);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
remove();
|
remove();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!getEntityWorld().isClient()) {
|
List<ServerPlayerEntity> viewers = Objects.requireNonNull(getServer()).getPlayerManager().getPlayerList();
|
||||||
getEntityWorld().sendEntityStatus(this, (byte) 0);
|
for (ServerPlayerEntity viewer : viewers) {
|
||||||
|
((ServerWorld) getEntityWorld()).spawnParticles(viewer, ParticleTypes.WITCH, true, getX(), getY(), getZ(), 8, 0.1d, 0.1d, 0.1d, 0d);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,60 +1,50 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.block;
|
package com.thebrokenrail.sorcerycraft.gui;
|
||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.Spell;
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellRegistry;
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
import net.minecraft.container.BlockContext;
|
|
||||||
import net.minecraft.container.Container;
|
|
||||||
import net.minecraft.container.ContainerType;
|
|
||||||
import net.minecraft.container.Slot;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerInventory;
|
import net.minecraft.entity.player.PlayerInventory;
|
||||||
import net.minecraft.inventory.BasicInventory;
|
|
||||||
import net.minecraft.inventory.CraftingResultInventory;
|
import net.minecraft.inventory.CraftingResultInventory;
|
||||||
import net.minecraft.inventory.Inventory;
|
import net.minecraft.inventory.Inventory;
|
||||||
|
import net.minecraft.inventory.SimpleInventory;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
|
import net.minecraft.screen.ScreenHandlerContext;
|
||||||
|
import net.minecraft.screen.ScreenHandlerType;
|
||||||
|
import net.minecraft.screen.slot.Slot;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.BiConsumer;
|
||||||
|
|
||||||
public class CastingTableContainer extends Container {
|
public class CastingTableScreenHandler extends ScreenHandler {
|
||||||
private final Inventory inventory;
|
private final Inventory inventory;
|
||||||
private final Inventory result;
|
private final Inventory result;
|
||||||
private final Spell[] spells;
|
private Spell[] spells = new Spell[0];
|
||||||
private final BlockContext context;
|
private final ScreenHandlerContext context;
|
||||||
private int index = 0;
|
private int index = 0;
|
||||||
|
|
||||||
public CastingTableContainer(int syncId, PlayerInventory playerInventory, BlockContext blockContext) {
|
public CastingTableScreenHandler(int syncId, PlayerInventory playerInventory, ScreenHandlerContext blockContext) {
|
||||||
super(ContainerType.STONECUTTER, syncId);
|
super(ScreenHandlerType.STONECUTTER, syncId);
|
||||||
|
|
||||||
inventory = new BasicInventory(2) {
|
inventory = new SimpleInventory(2) {
|
||||||
public void markDirty() {
|
public void markDirty() {
|
||||||
super.markDirty();
|
super.markDirty();
|
||||||
CastingTableContainer.this.onContentChanged(this);
|
CastingTableScreenHandler.this.onContentChanged(this);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
context = blockContext;
|
context = blockContext;
|
||||||
result = new CraftingResultInventory();
|
result = new CraftingResultInventory();
|
||||||
|
|
||||||
if (playerInventory.player.isCreative()) {
|
setSpells(playerInventory.player);
|
||||||
spells = SpellRegistry.getSpells();
|
|
||||||
} else {
|
|
||||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) playerInventory.player;
|
|
||||||
Map<Identifier, Integer> spellsMap = spellPlayer.getSpells();
|
|
||||||
List<Spell> spellsArray = new ArrayList<>();
|
|
||||||
|
|
||||||
Spell[] allSpells = SpellRegistry.getSpells();
|
|
||||||
for (Spell spell : allSpells) {
|
|
||||||
if (spellsMap.containsKey(spell.getID()) && spellsMap.get(spell.getID()) >= spell.getLevel()) {
|
|
||||||
spellsArray.add(spell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
spells = spellsArray.toArray(new Spell[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
addSlot(new Slot(inventory, 0, 136, 37) {
|
addSlot(new Slot(inventory, 0, 136, 37) {
|
||||||
@Override
|
@Override
|
||||||
@ -63,7 +53,7 @@ public class CastingTableContainer extends Container {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxStackAmount() {
|
public int getMaxItemCount() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,10 +84,15 @@ public class CastingTableContainer extends Container {
|
|||||||
player.addExperienceLevels(-spells[index].getXPCost());
|
player.addExperienceLevels(-spells[index].getXPCost());
|
||||||
}
|
}
|
||||||
|
|
||||||
SorceryCraft.playSpellSound(player);
|
context.run((world, blockPos) -> {
|
||||||
|
SorceryCraft.playSpellSound(world, blockPos);
|
||||||
|
if (!world.isClient()) {
|
||||||
|
SorceryCraft.CREATE_SPELL_CRITERION.trigger((ServerPlayerEntity) player);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
CastingTableContainer.this.inventory.setInvStack(0, ItemStack.EMPTY);
|
CastingTableScreenHandler.this.inventory.setStack(0, ItemStack.EMPTY);
|
||||||
CastingTableContainer.this.inventory.takeInvStack(1, spells[index].getItemCost().getCount());
|
CastingTableScreenHandler.this.inventory.removeStack(1, spells[index].getItemCost().getCount());
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -114,15 +109,39 @@ public class CastingTableContainer extends Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void resetIndex() {
|
||||||
|
index = 0;
|
||||||
|
onContentChanged(inventory);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpells(PlayerEntity player) {
|
||||||
|
if (player.isCreative() ? SorceryCraft.getConfig().limitCastingTable.creative : SorceryCraft.getConfig().limitCastingTable.survival) {
|
||||||
|
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||||
|
Map<Identifier, Integer> spellsMap = spellPlayer.getDiscoveredSpells();
|
||||||
|
List<Spell> spellsArray = new ArrayList<>();
|
||||||
|
|
||||||
|
Spell[] allSpells = SpellRegistry.getSpells();
|
||||||
|
for (Spell spell : allSpells) {
|
||||||
|
if (spellsMap.containsKey(spell.getID()) && spellsMap.get(spell.getID()) >= spell.getLevel()) {
|
||||||
|
spellsArray.add(spell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
spells = spellsArray.toArray(new Spell[0]);
|
||||||
|
} else {
|
||||||
|
spells = SpellRegistry.getSpells();
|
||||||
|
}
|
||||||
|
resetIndex();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean canTakeResult(PlayerEntity playerEntity) {
|
public boolean canTakeResult(PlayerEntity playerEntity) {
|
||||||
return (playerEntity.isCreative() || playerEntity.experienceLevel >= spells[index].getXPCost()) && spells[index].getXPCost() > 0;
|
return playerEntity.isCreative() || playerEntity.experienceLevel >= spells[index].getXPCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIndex(int index) {
|
public void setIndex(int index) {
|
||||||
this.index = index;
|
this.index = index;
|
||||||
onContentChanged(inventory);
|
onContentChanged(inventory);
|
||||||
|
|
||||||
if (inventory.getInvStack(0).isEmpty() && inventory.getInvStack(1).isEmpty()) {
|
if (inventory.getStack(0).isEmpty() && inventory.getStack(1).isEmpty()) {
|
||||||
ItemStack spellItem = new ItemStack(SorceryCraft.SPELL_ITEM);
|
ItemStack spellItem = new ItemStack(SorceryCraft.SPELL_ITEM);
|
||||||
autoFill(0, spellItem, true);
|
autoFill(0, spellItem, true);
|
||||||
ItemStack paymentItem = getRecipes()[index].getItemCost();
|
ItemStack paymentItem = getRecipes()[index].getItemCost();
|
||||||
@ -130,33 +149,71 @@ public class CastingTableContainer extends Container {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ItemStack transferSlot(PlayerEntity player, int invSlot) {
|
||||||
|
ItemStack itemStack = ItemStack.EMPTY;
|
||||||
|
Slot slot = slots.get(invSlot);
|
||||||
|
if (slot != null && slot.hasStack()) {
|
||||||
|
ItemStack itemStack2 = slot.getStack();
|
||||||
|
itemStack = itemStack2.copy();
|
||||||
|
if (invSlot == 2) {
|
||||||
|
if (!insertItem(itemStack2, 3, 39, true)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot.onStackChanged(itemStack2, itemStack);
|
||||||
|
} else if (invSlot != 0 && invSlot != 1) {
|
||||||
|
if (invSlot < 30) {
|
||||||
|
if (!insertItem(itemStack2, 30, 39, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else if (invSlot < 39 && !insertItem(itemStack2, 3, 30, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
} else if (!insertItem(itemStack2, 3, 39, false)) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemStack2.isEmpty()) {
|
||||||
|
slot.setStack(ItemStack.EMPTY);
|
||||||
|
} else {
|
||||||
|
slot.markDirty();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (itemStack2.getCount() == itemStack.getCount()) {
|
||||||
|
return ItemStack.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
slot.onTakeItem(player, itemStack2);
|
||||||
|
}
|
||||||
|
|
||||||
|
return itemStack;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void close(PlayerEntity player) {
|
public void close(PlayerEntity player) {
|
||||||
super.close(player);
|
super.close(player);
|
||||||
context.run((world, blockPos) -> {
|
context.run((BiConsumer<World, BlockPos>) (world, blockPos) -> dropInventory(player, world, inventory));
|
||||||
dropInventory(player, world, inventory);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onContentChanged(Inventory inventory) {
|
public void onContentChanged(Inventory inventory) {
|
||||||
super.onContentChanged(inventory);
|
super.onContentChanged(inventory);
|
||||||
ItemStack item = inventory.getInvStack(0);
|
ItemStack item = inventory.getStack(0);
|
||||||
ItemStack cost = inventory.getInvStack(1);
|
ItemStack cost = inventory.getStack(1);
|
||||||
if (inventory == this.inventory) {
|
if (inventory == this.inventory) {
|
||||||
if (spells.length > 0 &&
|
if (spells.length > 0 &&
|
||||||
!item.isEmpty() &&
|
!item.isEmpty() &&
|
||||||
cost.getItem() == spells[index].getItemCost().getItem() &&
|
cost.getItem() == spells[index].getItemCost().getItem() &&
|
||||||
cost.getCount() >= spells[index].getItemCost().getCount()) {
|
cost.getCount() >= spells[index].getItemCost().getCount()) {
|
||||||
ItemStack resultItem = item.copy();
|
ItemStack resultItem = item.copy();
|
||||||
Map<Identifier, Integer> resultSpells = SpellTag.getSpells(resultItem);
|
Map<Identifier, Integer> resultSpells = SpellHelper.getSpells(resultItem);
|
||||||
if (!resultSpells.containsKey(spells[index].getID()) || resultSpells.get(spells[index].getID()) <= spells[index].getLevel()) {
|
if (!resultSpells.containsKey(spells[index].getID()) || resultSpells.get(spells[index].getID()) <= spells[index].getLevel()) {
|
||||||
resultSpells.put(spells[index].getID(), spells[index].getLevel());
|
resultSpells.put(spells[index].getID(), spells[index].getLevel());
|
||||||
}
|
}
|
||||||
SpellTag.setSpells(resultItem, resultSpells);
|
SpellHelper.setSpells(resultItem, resultSpells);
|
||||||
result.setInvStack(2, resultItem);
|
result.setStack(2, resultItem);
|
||||||
} else {
|
} else {
|
||||||
result.setInvStack(2, ItemStack.EMPTY);
|
result.setStack(2, ItemStack.EMPTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -166,14 +223,14 @@ public class CastingTableContainer extends Container {
|
|||||||
for (int i = 3; i < 39; ++i) {
|
for (int i = 3; i < 39; ++i) {
|
||||||
ItemStack itemStack = slots.get(i).getStack();
|
ItemStack itemStack = slots.get(i).getStack();
|
||||||
if (!itemStack.isEmpty() && itemCompatible(stack, itemStack)) {
|
if (!itemStack.isEmpty() && itemCompatible(stack, itemStack)) {
|
||||||
ItemStack invSlot = inventory.getInvStack(slot);
|
ItemStack invSlot = inventory.getStack(slot);
|
||||||
int count = invSlot.isEmpty() ? 0 : invSlot.getCount();
|
int count = invSlot.isEmpty() ? 0 : invSlot.getCount();
|
||||||
int requiredCount = Math.min((onlyOne ? 1 : stack.getMaxCount()) - count, itemStack.getCount());
|
int requiredCount = Math.min((onlyOne ? 1 : stack.getMaxCount()) - count, itemStack.getCount());
|
||||||
ItemStack modifiedItem = itemStack.copy();
|
ItemStack modifiedItem = itemStack.copy();
|
||||||
int totalCount = count + requiredCount;
|
int totalCount = count + requiredCount;
|
||||||
itemStack.decrement(requiredCount);
|
itemStack.decrement(requiredCount);
|
||||||
modifiedItem.setCount(totalCount);
|
modifiedItem.setCount(totalCount);
|
||||||
inventory.setInvStack(slot, modifiedItem);
|
inventory.setStack(slot, modifiedItem);
|
||||||
if (totalCount >= stack.getMaxCount() || onlyOne) {
|
if (totalCount >= stack.getMaxCount() || onlyOne) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -188,7 +245,7 @@ public class CastingTableContainer extends Container {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canUse(PlayerEntity player) {
|
public boolean canUse(PlayerEntity player) {
|
||||||
return true;
|
return context.run((world, blockPos) -> world.getBlockState(blockPos).getBlock().equals(SorceryCraft.CASTING_TABLE_BLOCK) && player.squaredDistanceTo((double) blockPos.getX() + 0.5D, (double) blockPos.getY() + 0.5D, (double) blockPos.getZ() + 0.5D) <= 64.0D, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Spell[] getRecipes() {
|
public Spell[] getRecipes() {
|
@ -2,26 +2,23 @@ package com.thebrokenrail.sorcerycraft.item;
|
|||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.Spell;
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity;
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellRegistry;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
|
||||||
import net.minecraft.client.item.TooltipContext;
|
import net.minecraft.client.item.TooltipContext;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemGroup;
|
import net.minecraft.item.ItemGroup;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.text.LiteralText;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
import net.minecraft.util.DefaultedList;
|
|
||||||
import net.minecraft.util.Formatting;
|
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.Rarity;
|
import net.minecraft.util.Rarity;
|
||||||
import net.minecraft.util.TypedActionResult;
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
import net.minecraft.util.collection.DefaultedList;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -37,39 +34,41 @@ public class SpellItem extends Item {
|
|||||||
public TypedActionResult<ItemStack> use(World world, PlayerEntity playerEntity, Hand hand) {
|
public TypedActionResult<ItemStack> use(World world, PlayerEntity playerEntity, Hand hand) {
|
||||||
ItemStack itemStack = playerEntity.getStackInHand(hand);
|
ItemStack itemStack = playerEntity.getStackInHand(hand);
|
||||||
|
|
||||||
Map<Identifier, Integer> spells = SpellTag.getSpells(itemStack);
|
if (!world.isClient()) {
|
||||||
|
|
||||||
if (spells.size() > 0) {
|
|
||||||
SorceryCraft.playSpellSound(playerEntity);
|
SorceryCraft.playSpellSound(playerEntity);
|
||||||
|
|
||||||
if (!world.isClient()) {
|
playerEntity.incrementStat(SorceryCraft.CAST_SPELL_STAT);
|
||||||
SpellEntity entity = new SpellEntity(world, playerEntity);
|
|
||||||
entity.setItem(itemStack);
|
|
||||||
entity.setProperties(playerEntity, playerEntity.pitch, playerEntity.yaw, 0.0f, 1.5f, 1.0f);
|
|
||||||
world.spawnEntity(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!playerEntity.isCreative()) {
|
SpellEntity entity = new SpellEntity(world, playerEntity);
|
||||||
itemStack.decrement(1);
|
entity.setItem(itemStack);
|
||||||
}
|
entity.setProperties(playerEntity, playerEntity.pitch, playerEntity.yaw, 0.0f, 1.5f, 1.0f);
|
||||||
|
world.spawnEntity(entity);
|
||||||
return new TypedActionResult<>(ActionResult.SUCCESS, itemStack);
|
|
||||||
} else {
|
|
||||||
return new TypedActionResult<>(ActionResult.FAIL, itemStack);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!playerEntity.isCreative()) {
|
||||||
|
itemStack.decrement(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TypedActionResult<>(ActionResult.SUCCESS, itemStack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean hasEnchantmentGlint(ItemStack stack) {
|
public ActionResult useOnEntity(ItemStack stack, PlayerEntity user, LivingEntity entity, Hand hand) {
|
||||||
Map<Identifier, Integer> spells = SpellTag.getSpells(stack);
|
use(user.getEntityWorld(), user, hand);
|
||||||
return spells.size() > 0;
|
return ActionResult.SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasGlint(ItemStack stack) {
|
||||||
|
Map<Identifier, Integer> spells = SpellHelper.getSpells(stack);
|
||||||
|
return spells.size() > 0 || super.hasGlint(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendTooltip(ItemStack itemStack, World world, List<Text> tooltip, TooltipContext tooltipContext) {
|
public void appendTooltip(ItemStack itemStack, World world, List<Text> tooltip, TooltipContext tooltipContext) {
|
||||||
Map<Identifier, Integer> spells = SpellTag.getSpells(itemStack);
|
Map<Identifier, Integer> spells = SpellHelper.getSpells(itemStack);
|
||||||
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
|
||||||
tooltip.add(SpellTag.getTranslatedSpell(entry.getKey(), entry.getValue()));
|
tooltip.add(SpellHelper.getTranslatedSpell(entry.getKey(), entry.getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +81,7 @@ public class SpellItem extends Item {
|
|||||||
ItemStack item = new ItemStack(this);
|
ItemStack item = new ItemStack(this);
|
||||||
Map<Identifier, Integer> spell = new HashMap<>();
|
Map<Identifier, Integer> spell = new HashMap<>();
|
||||||
spell.put(value.getID(), value.getLevel());
|
spell.put(value.getID(), value.getLevel());
|
||||||
SpellTag.setSpells(item, spell);
|
SpellHelper.setSpells(item, spell);
|
||||||
stacks.add(item);
|
stacks.add(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -98,36 +97,9 @@ public class SpellItem extends Item {
|
|||||||
super.inventoryTick(stack, world, entity, slot, selected);
|
super.inventoryTick(stack, world, entity, slot, selected);
|
||||||
if (!world.isClient() && entity instanceof PlayerEntity) {
|
if (!world.isClient() && entity instanceof PlayerEntity) {
|
||||||
PlayerEntity player = (PlayerEntity) entity;
|
PlayerEntity player = (PlayerEntity) entity;
|
||||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
Map<Identifier, Integer> itemSpells = SpellHelper.getSpells(player.inventory.getStack(slot));
|
||||||
|
|
||||||
Map<Identifier, Integer> playerSpells = spellPlayer.getSpells();
|
SpellHelper.learnSpells(player, itemSpells);
|
||||||
Map<Identifier, Integer> itemSpells = SpellTag.getSpells(player.inventory.getInvStack(slot));
|
|
||||||
|
|
||||||
boolean changed = false;
|
|
||||||
|
|
||||||
for (Map.Entry<Identifier, Integer> entry : itemSpells.entrySet()) {
|
|
||||||
Spell spell = SpellRegistry.getSpell(entry.getKey(), entry.getValue());
|
|
||||||
if (spell != null) {
|
|
||||||
if (spell.getLevel() >= spell.getMaxLevel()) {
|
|
||||||
spell = SpellRegistry.getSpell(entry.getKey(), spell.getMaxLevel() - 1);
|
|
||||||
}
|
|
||||||
assert spell != null;
|
|
||||||
if (!playerSpells.containsKey(spell.getID()) || playerSpells.get(spell.getID()) < spell.getLevel()) {
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
playerSpells.put(spell.getID(), spell.getLevel());
|
|
||||||
assert world.getServer() != null;
|
|
||||||
Text text = new LiteralText("[").append(SpellTag.getTranslatedSpell(spell.getID(), spell.getLevel()).getString()).append("]").formatted(Formatting.GREEN);
|
|
||||||
world.getServer().getPlayerManager().sendToAll(new TranslatableText("chat." + SorceryCraft.NAMESPACE + ".new_spell", player.getDisplayName(), text));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed) {
|
|
||||||
//LearnedNewSpellS2CPacket.send((ServerPlayerEntity) player);
|
|
||||||
SorceryCraft.playSpellSound(player);
|
|
||||||
spellPlayer.setSpells(playerSpells);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,14 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.mixin;
|
||||||
|
|
||||||
|
import net.minecraft.advancement.criterion.Criteria;
|
||||||
|
import net.minecraft.advancement.criterion.Criterion;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||||
|
|
||||||
|
@Mixin(Criteria.class)
|
||||||
|
public interface CriteriaRegistryHook {
|
||||||
|
@Invoker("register")
|
||||||
|
static <T extends Criterion<?>> T callRegister(T criterion) {
|
||||||
|
return criterion;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.mixin;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.client.gui.CastingTableScreen;
|
||||||
|
import net.minecraft.client.font.TextRenderer;
|
||||||
|
import net.minecraft.client.gui.DrawableHelper;
|
||||||
|
import net.minecraft.client.gui.widget.AbstractButtonWidget;
|
||||||
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
|
||||||
|
@SuppressWarnings("ConstantConditions")
|
||||||
|
@Mixin(AbstractButtonWidget.class)
|
||||||
|
public class MixinAbstractButtonWidget {
|
||||||
|
@Redirect(at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/widget/AbstractButtonWidget;drawCenteredText(Lnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/font/TextRenderer;Lnet/minecraft/text/Text;III)V"), method = "renderButton")
|
||||||
|
public void drawCenteredText(MatrixStack matrices, TextRenderer textRenderer, Text text, int centerX, int y, int color) {
|
||||||
|
if ((Object) this instanceof CastingTableScreen.WidgetButtonPage) {
|
||||||
|
DrawableHelper.drawStringWithShadow(matrices, textRenderer, text.getString(), ((CastingTableScreen.WidgetButtonPage) (Object) this).x + 5, y, color);
|
||||||
|
} else {
|
||||||
|
DrawableHelper.drawCenteredText(matrices, textRenderer, text, centerX, y, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,8 @@ package com.thebrokenrail.sorcerycraft.mixin;
|
|||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
import com.thebrokenrail.sorcerycraft.entity.SpellEntity;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
@ -14,13 +16,14 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
@Mixin(ClientPlayNetworkHandler.class)
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
public class MixinClientPlayNetworkHandler {
|
public class MixinClientPlayNetworkHandler {
|
||||||
@Shadow
|
@Shadow
|
||||||
private ClientWorld world;
|
private ClientWorld world;
|
||||||
|
|
||||||
@Inject(method = "onEntitySpawn", at = @At(value = "TAIL"))
|
@Inject(method = "onEntitySpawn", at = @At(value = "TAIL"))
|
||||||
public void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo callbackInfo) {
|
public void onEntitySpawn(EntitySpawnS2CPacket packet, CallbackInfo info) {
|
||||||
EntityType<?> entityType = packet.getEntityTypeId();
|
EntityType<?> entityType = packet.getEntityTypeId();
|
||||||
Entity entity = null;
|
Entity entity = null;
|
||||||
|
|
||||||
|
@ -0,0 +1,30 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.mixin;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.client.gui.CastingTableScreen;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.client.network.ClientPlayerEntity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
@Mixin(ClientPlayerEntity.class)
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
|
public class MixinClientPlayerEntity extends MixinPlayerEntity {
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
protected MinecraftClient client;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setDiscoveredSpells(Map<Identifier, Integer> spells) {
|
||||||
|
super.setDiscoveredSpells(spells);
|
||||||
|
if (client.currentScreen instanceof CastingTableScreen) {
|
||||||
|
((CastingTableScreen) client.currentScreen).resetIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,15 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.mixin;
|
package com.thebrokenrail.sorcerycraft.mixin;
|
||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity;
|
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.Unique;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
@ -16,25 +20,32 @@ import java.util.Map;
|
|||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Mixin(PlayerEntity.class)
|
@Mixin(PlayerEntity.class)
|
||||||
public class MixinPlayerEntity implements SpellPlayerEntity {
|
public class MixinPlayerEntity implements SpellPlayerEntity {
|
||||||
private Map<Identifier, Integer> spells = new HashMap<>();
|
@Shadow
|
||||||
|
public ScreenHandler currentScreenHandler;
|
||||||
|
@Unique
|
||||||
|
private Map<Identifier, Integer> discoveredSpells = new HashMap<>();
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "readCustomDataFromTag")
|
@Inject(at = @At("HEAD"), method = "readCustomDataFromTag")
|
||||||
public void readCustomDataFromTag(CompoundTag tag, CallbackInfo info) {
|
public void readCustomDataFromTag(CompoundTag tag, CallbackInfo info) {
|
||||||
spells = SpellTag.getSpells(tag);
|
discoveredSpells = SpellHelper.getSpells(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "writeCustomDataToTag")
|
@Inject(at = @At("HEAD"), method = "writeCustomDataToTag")
|
||||||
public void writeCustomDataToTag(CompoundTag tag, CallbackInfo info) {
|
public void writeCustomDataToTag(CompoundTag tag, CallbackInfo info) {
|
||||||
tag.put(SpellTag.SPELL_TAG, SpellTag.createSpellsTag(spells));
|
tag.put(SpellHelper.SPELL_TAG, SpellHelper.createSpellsTag(discoveredSpells));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSpells(Map<Identifier, Integer> spells) {
|
public void setDiscoveredSpells(Map<Identifier, Integer> spells) {
|
||||||
this.spells = spells;
|
discoveredSpells = spells;
|
||||||
|
if (currentScreenHandler instanceof CastingTableScreenHandler) {
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
((CastingTableScreenHandler) currentScreenHandler).setSpells((PlayerEntity) (Object) this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<Identifier, Integer> getSpells() {
|
public Map<Identifier, Integer> getDiscoveredSpells() {
|
||||||
return spells;
|
return discoveredSpells;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,30 +1,45 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.mixin;
|
package com.thebrokenrail.sorcerycraft.mixin;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
|
||||||
import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket;
|
import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellServerPlayerEntity;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
@Mixin(ServerPlayerEntity.class)
|
@Mixin(ServerPlayerEntity.class)
|
||||||
public abstract class MixinServerPlayerEntity implements SpellPlayerEntity {
|
public abstract class MixinServerPlayerEntity extends MixinPlayerEntity implements SpellServerPlayerEntity {
|
||||||
@Inject(at = @At("HEAD"), method = "copyFrom")
|
@Inject(at = @At("HEAD"), method = "copyFrom")
|
||||||
public void copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo ci) {
|
public void copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo info) {
|
||||||
SpellPlayerEntity oldSpellPlayer = (SpellPlayerEntity) oldPlayer;
|
SpellPlayerEntity oldSpellPlayer = (SpellPlayerEntity) oldPlayer;
|
||||||
SpellPlayerEntity newSpellPlayer = this;
|
SpellPlayerEntity newSpellPlayer = this;
|
||||||
|
|
||||||
newSpellPlayer.setSpells(oldSpellPlayer.getSpells());
|
newSpellPlayer.setDiscoveredSpells(oldSpellPlayer.getDiscoveredSpells());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(at = @At("HEAD"), method = "playerTick")
|
@Override
|
||||||
public void playerTick(CallbackInfo ignored) {
|
public void setDiscoveredSpells(Map<Identifier, Integer> spells) {
|
||||||
|
super.setDiscoveredSpells(spells);
|
||||||
|
if (currentScreenHandler instanceof CastingTableScreenHandler) {
|
||||||
|
sync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void sync() {
|
||||||
CompoundTag tag = new CompoundTag();
|
CompoundTag tag = new CompoundTag();
|
||||||
tag.put(SpellTag.SPELL_TAG, SpellTag.createSpellsTag(getSpells()));
|
tag.put(SpellHelper.SPELL_TAG, SpellHelper.createSpellsTag(getDiscoveredSpells()));
|
||||||
//noinspection ConstantConditions
|
//noinspection ConstantConditions
|
||||||
UpdateKnownSpellsS2CPacket.send((ServerPlayerEntity) (Object) this, tag);
|
UpdateKnownSpellsS2CPacket.send((ServerPlayerEntity) (Object) this, tag);
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,28 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.packet;
|
package com.thebrokenrail.sorcerycraft.packet;
|
||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
import com.thebrokenrail.sorcerycraft.block.CastingTableContainer;
|
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import net.fabricmc.fabric.api.network.PacketContext;
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
import net.minecraft.container.Container;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket;
|
import net.minecraft.network.packet.c2s.play.CustomPayloadC2SPacket;
|
||||||
|
import net.minecraft.screen.ScreenHandler;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.PacketByteBuf;
|
|
||||||
|
|
||||||
public class SelectSpellC2SPacket {
|
public class SelectSpellC2SPacket {
|
||||||
public static void handle(PacketContext context, PacketByteBuf bytes) {
|
public static void handle(PacketContext context, PacketByteBuf bytes) {
|
||||||
int index = bytes.readInt();
|
int index = bytes.readInt();
|
||||||
Container container = context.getPlayer().container;
|
ScreenHandler handler = context.getPlayer().currentScreenHandler;
|
||||||
if (container instanceof CastingTableContainer) {
|
if (handler instanceof CastingTableScreenHandler) {
|
||||||
CastingTableContainer merchantContainer = (CastingTableContainer) container;
|
CastingTableScreenHandler merchantContainer = (CastingTableScreenHandler) handler;
|
||||||
merchantContainer.setIndex(index);
|
merchantContainer.setIndex(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
public static void send(MinecraftClient minecraft, int index) {
|
public static void send(MinecraftClient minecraft, int index) {
|
||||||
PacketByteBuf bytes = new PacketByteBuf(Unpooled.buffer());
|
PacketByteBuf bytes = new PacketByteBuf(Unpooled.buffer());
|
||||||
bytes.writeInt(index);
|
bytes.writeInt(index);
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.packet;
|
package com.thebrokenrail.sorcerycraft.packet;
|
||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellPlayerEntity;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
|
||||||
import com.thebrokenrail.sorcerycraft.spell.SpellTag;
|
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
|
||||||
import io.netty.buffer.Unpooled;
|
import io.netty.buffer.Unpooled;
|
||||||
|
import net.fabricmc.api.EnvType;
|
||||||
|
import net.fabricmc.api.Environment;
|
||||||
import net.fabricmc.fabric.api.network.PacketContext;
|
import net.fabricmc.fabric.api.network.PacketContext;
|
||||||
import net.minecraft.nbt.CompoundTag;
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
import net.minecraft.network.packet.s2c.play.CustomPayloadS2CPacket;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.PacketByteBuf;
|
|
||||||
|
|
||||||
public class UpdateKnownSpellsS2CPacket {
|
public class UpdateKnownSpellsS2CPacket {
|
||||||
|
@Environment(EnvType.CLIENT)
|
||||||
public static void handle(PacketContext context, PacketByteBuf bytes) {
|
public static void handle(PacketContext context, PacketByteBuf bytes) {
|
||||||
CompoundTag tag = bytes.readCompoundTag();
|
CompoundTag tag = bytes.readCompoundTag();
|
||||||
if (context.getPlayer() != null) {
|
if (context.getPlayer() != null) {
|
||||||
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) context.getPlayer();
|
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) context.getPlayer();
|
||||||
spellPlayer.setSpells(SpellTag.getSpells(tag));
|
spellPlayer.setDiscoveredSpells(SpellHelper.getSpells(tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -0,0 +1,54 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.state.property.Properties;
|
||||||
|
import net.minecraft.tag.BlockTags;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class CoolingSpell extends Spell {
|
||||||
|
public CoolingSpell(Identifier id, int level) {
|
||||||
|
super(id, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
|
target.setFireTicks(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(World world, Entity source, Entity attacker, BlockHitResult hitResult) {
|
||||||
|
BlockPos blockPos = hitResult.getBlockPos();
|
||||||
|
if (world.getBlockState(blockPos).isIn(BlockTags.FIRE)) {
|
||||||
|
world.removeBlock(blockPos, false);
|
||||||
|
}
|
||||||
|
if (world.getBlockState(blockPos).contains(Properties.LIT) && world.getBlockState(blockPos).get(Properties.LIT)) {
|
||||||
|
world.setBlockState(blockPos, world.getBlockState(blockPos).with(Properties.LIT, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
BlockPos sideBlockPos = blockPos.offset(hitResult.getSide());
|
||||||
|
if (world.getBlockState(sideBlockPos).isIn(BlockTags.FIRE)) {
|
||||||
|
world.removeBlock(sideBlockPos, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getXPCost() {
|
||||||
|
return 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemCost() {
|
||||||
|
return new ItemStack(Items.ICE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLevel() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,13 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class DamageSpell extends Spell {
|
public class DamageSpell extends Spell {
|
||||||
public DamageSpell(Identifier id, int level) {
|
public DamageSpell(Identifier id, int level) {
|
||||||
@ -13,7 +15,7 @@ public class DamageSpell extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
if (target instanceof LivingEntity) {
|
if (target instanceof LivingEntity) {
|
||||||
StatusEffects.INSTANT_DAMAGE.applyInstantEffect(source, attacker, (LivingEntity) target, getLevel(), 1.0d);
|
StatusEffects.INSTANT_DAMAGE.applyInstantEffect(source, attacker, (LivingEntity) target, getLevel(), 1.0d);
|
||||||
}
|
}
|
||||||
@ -23,10 +25,10 @@ public class DamageSpell extends Spell {
|
|||||||
public int getXPCost() {
|
public int getXPCost() {
|
||||||
switch (getLevel()) {
|
switch (getLevel()) {
|
||||||
case 0: {
|
case 0: {
|
||||||
return 5;
|
return 4;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
return 10;
|
return 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,10 +1,12 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class DissolveSpell extends Spell {
|
public class DissolveSpell extends Spell {
|
||||||
public DissolveSpell(Identifier id, int level) {
|
public DissolveSpell(Identifier id, int level) {
|
||||||
@ -12,7 +14,7 @@ public class DissolveSpell extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
if (target instanceof LivingEntity) {
|
if (target instanceof LivingEntity) {
|
||||||
((LivingEntity) target).clearStatusEffects();
|
((LivingEntity) target).clearStatusEffects();
|
||||||
}
|
}
|
||||||
@ -20,7 +22,7 @@ public class DissolveSpell extends Spell {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getXPCost() {
|
public int getXPCost() {
|
||||||
return 12;
|
return 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,9 +1,14 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.item.AutomaticItemPlacementContext;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class FlameSpell extends Spell {
|
public class FlameSpell extends Spell {
|
||||||
public FlameSpell(Identifier id, int level) {
|
public FlameSpell(Identifier id, int level) {
|
||||||
@ -11,8 +16,16 @@ public class FlameSpell extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
target.setFireTicks(400 + (getLevel() * 200));
|
if (attacker instanceof LivingEntity) {
|
||||||
|
((LivingEntity) attacker).onAttacking(target);
|
||||||
|
}
|
||||||
|
target.setOnFireFor(8 + (getLevel() * 4));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(World world, Entity source, Entity attacker, BlockHitResult hitResult) {
|
||||||
|
Items.FLINT_AND_STEEL.useOnBlock(new AutomaticItemPlacementContext(world, hitResult.getBlockPos(), hitResult.getSide().getOpposite(), new ItemStack(Items.FLINT_AND_STEEL), hitResult.getSide()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -22,7 +35,7 @@ public class FlameSpell extends Spell {
|
|||||||
return 8;
|
return 8;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
return 16;
|
return 12;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class HealSpell extends Spell {
|
public class HealSpell extends Spell {
|
||||||
public HealSpell(Identifier id, int level) {
|
public HealSpell(Identifier id, int level) {
|
||||||
@ -13,7 +15,7 @@ public class HealSpell extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
if (target instanceof LivingEntity) {
|
if (target instanceof LivingEntity) {
|
||||||
StatusEffects.INSTANT_HEALTH.applyInstantEffect(source, attacker, (LivingEntity) target, getLevel(), 1.0d);
|
StatusEffects.INSTANT_HEALTH.applyInstantEffect(source, attacker, (LivingEntity) target, getLevel(), 1.0d);
|
||||||
}
|
}
|
||||||
@ -23,10 +25,10 @@ public class HealSpell extends Spell {
|
|||||||
public int getXPCost() {
|
public int getXPCost() {
|
||||||
switch (getLevel()) {
|
switch (getLevel()) {
|
||||||
case 0: {
|
case 0: {
|
||||||
return 5;
|
return 4;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
return 10;
|
return 8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
@ -10,11 +10,6 @@ public class InwardSpell extends Spell {
|
|||||||
super(id, level);
|
super(id, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getXPCost() {
|
public int getXPCost() {
|
||||||
return 16;
|
return 16;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
@ -7,6 +8,7 @@ import net.minecraft.entity.effect.StatusEffects;
|
|||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class LevitateSpell extends Spell {
|
public class LevitateSpell extends Spell {
|
||||||
public LevitateSpell(Identifier id, int level) {
|
public LevitateSpell(Identifier id, int level) {
|
||||||
@ -14,7 +16,7 @@ public class LevitateSpell extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
if (target instanceof LivingEntity) {
|
if (target instanceof LivingEntity) {
|
||||||
((LivingEntity) target).addStatusEffect(new StatusEffectInstance(StatusEffects.LEVITATION, 400 + (getLevel() * 160)));
|
((LivingEntity) target).addStatusEffect(new StatusEffectInstance(StatusEffects.LEVITATION, 400 + (getLevel() * 160)));
|
||||||
}
|
}
|
||||||
@ -27,7 +29,7 @@ public class LevitateSpell extends Spell {
|
|||||||
return 12;
|
return 12;
|
||||||
}
|
}
|
||||||
case 1: {
|
case 1: {
|
||||||
return 21;
|
return 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityType;
|
||||||
|
import net.minecraft.entity.LightningEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.Items;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.server.world.ServerWorld;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public class LightningSpell extends Spell {
|
||||||
|
public LightningSpell(Identifier id, int level) {
|
||||||
|
super(id, level);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
|
strike(world, target.getPos(), attacker);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(World world, Entity source, Entity attacker, BlockHitResult hitResult) {
|
||||||
|
strike(world, hitResult.getPos(), attacker);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void strike(World world, Vec3d pos, Entity attacker) {
|
||||||
|
ServerWorld serverWorld = (ServerWorld) world;
|
||||||
|
LightningEntity lightningEntity = EntityType.LIGHTNING_BOLT.create(world);
|
||||||
|
assert lightningEntity != null;
|
||||||
|
lightningEntity.updatePosition(pos.x, pos.y, pos.z);
|
||||||
|
if (attacker instanceof ServerPlayerEntity) {
|
||||||
|
lightningEntity.setChanneler((ServerPlayerEntity) attacker);
|
||||||
|
}
|
||||||
|
serverWorld.spawnEntity(lightningEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getXPCost() {
|
||||||
|
return 18;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ItemStack getItemCost() {
|
||||||
|
return new ItemStack(Items.END_ROD);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMaxLevel() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
@ -1,31 +0,0 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
public abstract class Spell {
|
|
||||||
private final Identifier id;
|
|
||||||
private final int level;
|
|
||||||
|
|
||||||
public Spell(Identifier id, int level) {
|
|
||||||
this.id = id;
|
|
||||||
this.level = level;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Identifier getID() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getLevel() {
|
|
||||||
return level;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void execute(Entity target, Entity source, Entity attacker);
|
|
||||||
|
|
||||||
public abstract int getXPCost();
|
|
||||||
|
|
||||||
public abstract ItemStack getItemCost();
|
|
||||||
|
|
||||||
public abstract int getMaxLevel();
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
|
||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public interface SpellPlayerEntity {
|
|
||||||
void setSpells(Map<Identifier, Integer> spells);
|
|
||||||
|
|
||||||
Map<Identifier, Integer> getSpells();
|
|
||||||
}
|
|
@ -1,55 +0,0 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
|
||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class SpellRegistry {
|
|
||||||
private static final Map<Identifier, Class<?>> spells = new HashMap<>();
|
|
||||||
|
|
||||||
public static Spell getSpell(Identifier id, int level) {
|
|
||||||
if (!spells.containsKey(id)) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
return (Spell) spells.get(id).getConstructor(Identifier.class, int.class).newInstance(id, level);
|
|
||||||
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static int getMaxLevel(Identifier id) {
|
|
||||||
Spell tempSpell = getSpell(id, 0);
|
|
||||||
if (tempSpell == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return tempSpell.getMaxLevel();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Spell[] getSpells() {
|
|
||||||
List<Spell> out = new ArrayList<>();
|
|
||||||
for (Map.Entry<Identifier, Class<?>> entry : spells.entrySet()) {
|
|
||||||
int maxLevel = getMaxLevel(entry.getKey());
|
|
||||||
if (maxLevel == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < maxLevel; i++) {
|
|
||||||
Spell spell = getSpell(entry.getKey(), i);
|
|
||||||
if (spell != null) {
|
|
||||||
out.add(spell);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return out.toArray(new Spell[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Identifier registerSpell(Identifier id, Class<?> spell) {
|
|
||||||
spells.put(id, spell);
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,85 +0,0 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
|
||||||
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.nbt.CompoundTag;
|
|
||||||
import net.minecraft.nbt.ListTag;
|
|
||||||
import net.minecraft.nbt.Tag;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.text.TranslatableText;
|
|
||||||
import net.minecraft.util.Formatting;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class SpellTag {
|
|
||||||
public static final String SPELL_TAG = "Spells";
|
|
||||||
|
|
||||||
public static void setSpells(ItemStack itemStack, Map<Identifier, Integer> map) {
|
|
||||||
CompoundTag tag;
|
|
||||||
if (itemStack.hasTag()) {
|
|
||||||
tag = itemStack.getTag();
|
|
||||||
} else {
|
|
||||||
tag = new CompoundTag();
|
|
||||||
tag.put(SPELL_TAG, new ListTag());
|
|
||||||
}
|
|
||||||
assert tag != null;
|
|
||||||
|
|
||||||
tag.put(SPELL_TAG, createSpellsTag(map));
|
|
||||||
|
|
||||||
itemStack.setTag(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ListTag createSpellsTag(Map<Identifier, Integer> map) {
|
|
||||||
ListTag spells = new ListTag();
|
|
||||||
|
|
||||||
for (Map.Entry<Identifier, Integer> entry : map.entrySet()) {
|
|
||||||
CompoundTag spell = new CompoundTag();
|
|
||||||
spell.putString("id", entry.getKey().toString());
|
|
||||||
spell.putInt("level", entry.getValue());
|
|
||||||
spells.add(spell);
|
|
||||||
}
|
|
||||||
|
|
||||||
return spells;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<Identifier, Integer> getSpells(ItemStack itemStack) {
|
|
||||||
return getSpells(itemStack.getTag());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Map<Identifier, Integer> getSpells(CompoundTag tag) {
|
|
||||||
if (tag == null) {
|
|
||||||
tag = new CompoundTag();
|
|
||||||
tag.put(SPELL_TAG, new ListTag());
|
|
||||||
}
|
|
||||||
Tag spellsTag = tag.get(SPELL_TAG);
|
|
||||||
ListTag spells;
|
|
||||||
if (spellsTag instanceof ListTag) {
|
|
||||||
spells = (ListTag) spellsTag;
|
|
||||||
} else {
|
|
||||||
spells = new ListTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<Identifier, Integer> map = new HashMap<>();
|
|
||||||
|
|
||||||
for (int i = 0; i < spells.size(); i++) {
|
|
||||||
CompoundTag spell = spells.getCompound(i);
|
|
||||||
Identifier id = new Identifier(spell.getString("id"));
|
|
||||||
int level = spell.getInt("level");
|
|
||||||
if (map.get(id) == null || map.get(id) < level) {
|
|
||||||
map.put(id, level);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Text getTranslatedSpell(Identifier id, int level) {
|
|
||||||
Text text = new TranslatableText("spell." + id.getNamespace() + '.' + id.getPath());
|
|
||||||
text.formatted(Formatting.GRAY);
|
|
||||||
if (level != 0 || SpellRegistry.getMaxLevel(id) != 1) {
|
|
||||||
text.append(" ").append(new TranslatableText("enchantment.level." + (level + 1)));
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
|
||||||
|
|
||||||
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
|
||||||
import net.minecraft.util.Identifier;
|
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public class Spells {
|
|
||||||
public static final Identifier HEAL_SPELL;
|
|
||||||
public static final Identifier DAMAGE_SPELL;
|
|
||||||
public static final Identifier DISSOLVE_SPELL;
|
|
||||||
public static final Identifier STEADFAST_SPELL;
|
|
||||||
public static final Identifier FLAME_SPELL;
|
|
||||||
public static final Identifier LEVITATE_SPELL;
|
|
||||||
public static final Identifier TELEPORT_SPELL;
|
|
||||||
public static final Identifier INWARD_SPELL;
|
|
||||||
|
|
||||||
static {
|
|
||||||
HEAL_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "heal_spell"), HealSpell.class);
|
|
||||||
DAMAGE_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "damage_spell"), DamageSpell.class);
|
|
||||||
DISSOLVE_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "dissolve_spell"), DissolveSpell.class);
|
|
||||||
STEADFAST_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "steadfast_spell"), SteadfastSpell.class);
|
|
||||||
FLAME_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "flame_spell"), FlameSpell.class);
|
|
||||||
LEVITATE_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "levitate_spell"), LevitateSpell.class);
|
|
||||||
TELEPORT_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "teleport_spell"), TeleportSpell.class);
|
|
||||||
INWARD_SPELL = SpellRegistry.registerSpell(new Identifier(SorceryCraft.NAMESPACE, "inward_spell"), InwardSpell.class);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,6 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
@ -10,11 +10,6 @@ public class SteadfastSpell extends Spell {
|
|||||||
super(id, level);
|
super(id, level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
|
||||||
// NOOP
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getXPCost() {
|
public int getXPCost() {
|
||||||
return 18;
|
return 18;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
@ -16,12 +17,11 @@ public class TeleportSpell extends Spell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private int getMaxTeleport(World world) {
|
private int getMaxTeleport(World world) {
|
||||||
return world.getDimension().isNether() ? 128 : 256;
|
return world.getRegistryKey() != World.OVERWORLD ? 128 : 256;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(Entity target, Entity source, Entity attacker) {
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
World world = target.getEntityWorld();
|
|
||||||
int range = 16 + (8 * getLevel());
|
int range = 16 + (8 * getLevel());
|
||||||
if (target instanceof LivingEntity) {
|
if (target instanceof LivingEntity) {
|
||||||
LivingEntity user = (LivingEntity) target;
|
LivingEntity user = (LivingEntity) target;
|
||||||
@ -57,6 +57,9 @@ public class TeleportSpell extends Spell {
|
|||||||
case 1: {
|
case 1: {
|
||||||
return 18;
|
return 18;
|
||||||
}
|
}
|
||||||
|
case 2: {
|
||||||
|
return 24;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -70,12 +73,15 @@ public class TeleportSpell extends Spell {
|
|||||||
case 1: {
|
case 1: {
|
||||||
return new ItemStack(Items.CHORUS_FRUIT);
|
return new ItemStack(Items.CHORUS_FRUIT);
|
||||||
}
|
}
|
||||||
|
case 2: {
|
||||||
|
return new ItemStack(Items.CHORUS_FLOWER);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ItemStack.EMPTY;
|
return ItemStack.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getMaxLevel() {
|
public int getMaxLevel() {
|
||||||
return 2;
|
return 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,101 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell.api;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.text.MutableText;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.hit.BlockHitResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spell Implementation Base Class
|
||||||
|
*/
|
||||||
|
public abstract class Spell {
|
||||||
|
private final Identifier id;
|
||||||
|
private final int level;
|
||||||
|
|
||||||
|
public Spell(Identifier id, int level) {
|
||||||
|
this.id = id;
|
||||||
|
this.level = level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ID of this spell
|
||||||
|
* @return The Spell ID
|
||||||
|
*/
|
||||||
|
public Identifier getID() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the level of this spell
|
||||||
|
* @return The Spell's Level
|
||||||
|
*/
|
||||||
|
public int getLevel() {
|
||||||
|
return level;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute this spell on an Entity
|
||||||
|
* @param world World
|
||||||
|
* @param source A SpellEntity
|
||||||
|
* @param attacker The Entity that cast this spell
|
||||||
|
* @param target The Target
|
||||||
|
*/
|
||||||
|
public void execute(World world, Entity source, Entity attacker, Entity target) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute this spell on a block
|
||||||
|
* @param world World
|
||||||
|
* @param source A SpellEntity
|
||||||
|
* @param attacker The Entity that cast this spell
|
||||||
|
* @param hitResult The block's HitResult
|
||||||
|
*/
|
||||||
|
public void execute(World world, Entity source, Entity attacker, BlockHitResult hitResult) {
|
||||||
|
// NOOP
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the amount of levels required to make this spell in a Casting Table
|
||||||
|
* @return The XP cost
|
||||||
|
*/
|
||||||
|
public abstract int getXPCost();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the item(s) required to make this spell in a Casting Table, or ItemStack.EMPTY if an item is not required
|
||||||
|
* @return The item cost
|
||||||
|
*/
|
||||||
|
public abstract ItemStack getItemCost();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the maximum level of this spell
|
||||||
|
* @return The Spell's Max Level
|
||||||
|
*/
|
||||||
|
public abstract int getMaxLevel();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default Implementation for Spell.getTranslation()
|
||||||
|
* @param id Spell ID
|
||||||
|
* @param level Spell Level
|
||||||
|
* @return Translated Display Name
|
||||||
|
*/
|
||||||
|
public static MutableText getDefaultTranslation(Identifier id, int level) {
|
||||||
|
MutableText text = new TranslatableText("spell." + id.getNamespace() + '.' + id.getPath());
|
||||||
|
if (level != 0 || SpellRegistry.getMaxLevel(id) != 1) {
|
||||||
|
text.append(" ").append(new TranslatableText("enchantment.level." + (level + 1)));
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Translated Display Name
|
||||||
|
* @return Translated Display Name
|
||||||
|
*/
|
||||||
|
public MutableText getTranslation() {
|
||||||
|
return getDefaultTranslation(getID(), getLevel());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,114 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell.api.registry;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Spell Implementation Registry
|
||||||
|
*/
|
||||||
|
public class SpellRegistry {
|
||||||
|
private static final Map<Identifier, Class<?>> spells = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Spell Implementation
|
||||||
|
* @param entry Map Entry
|
||||||
|
* @return Spell Implementation
|
||||||
|
*/
|
||||||
|
public static Spell getSpell(Map.Entry<Identifier, Integer> entry) {
|
||||||
|
return getSpell(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Spell Implementation
|
||||||
|
* @param id Spell ID
|
||||||
|
* @param level Spell Level
|
||||||
|
* @return Spell Implementation
|
||||||
|
*/
|
||||||
|
public static Spell getSpell(Identifier id, int level) {
|
||||||
|
if (!spells.containsKey(id)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return (Spell) spells.get(id).getConstructor(Identifier.class, int.class).newInstance(id, level);
|
||||||
|
} catch (NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Max Level of a Spell
|
||||||
|
* @param id Spell ID
|
||||||
|
* @return Max Level
|
||||||
|
*/
|
||||||
|
public static int getMaxLevel(Identifier id) {
|
||||||
|
Spell tempSpell = getSpell(id, 0);
|
||||||
|
if (tempSpell == null) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return tempSpell.getMaxLevel();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get All Spell Implementations
|
||||||
|
* @return List of Spell Implementations
|
||||||
|
*/
|
||||||
|
public static Spell[] getSpells() {
|
||||||
|
List<Spell> out = new ArrayList<>();
|
||||||
|
for (Map.Entry<Identifier, Class<?>> entry : spells.entrySet()) {
|
||||||
|
int maxLevel = getMaxLevel(entry.getKey());
|
||||||
|
if (maxLevel == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < maxLevel; i++) {
|
||||||
|
Spell spell = getSpell(entry.getKey(), i);
|
||||||
|
if (spell != null) {
|
||||||
|
out.add(spell);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.toArray(new Spell[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get All Max Level Spell Implementations
|
||||||
|
* @return List of Spell Implementations
|
||||||
|
*/
|
||||||
|
public static Spell[] getMaxSpells() {
|
||||||
|
List<Spell> out = new ArrayList<>();
|
||||||
|
for (Map.Entry<Identifier, Class<?>> entry : spells.entrySet()) {
|
||||||
|
int maxLevel = getMaxLevel(entry.getKey());
|
||||||
|
if (maxLevel == -1) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
out.add(getSpell(entry.getKey(), maxLevel - 1));
|
||||||
|
}
|
||||||
|
return out.toArray(new Spell[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a Spell
|
||||||
|
* @param id The Spell ID
|
||||||
|
* @param spell The Spell Class
|
||||||
|
* @return The Spell ID
|
||||||
|
*/
|
||||||
|
public static Identifier register(Identifier id, Class<?> spell) {
|
||||||
|
spells.put(id, spell);
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gat All Spell IDs
|
||||||
|
* @return List of Spell IDs
|
||||||
|
*/
|
||||||
|
public static Identifier[] getSpellsID() {
|
||||||
|
return spells.keySet().toArray(new Identifier[0]);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell.api.registry;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.CoolingSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.DamageSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.DissolveSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.FlameSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.HealSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.InwardSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.LevitateSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.LightningSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.SteadfastSpell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.TeleportSpell;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All Builtin Spells
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
public class Spells {
|
||||||
|
public static final Identifier HEAL_SPELL;
|
||||||
|
public static final Identifier DAMAGE_SPELL;
|
||||||
|
public static final Identifier DISSOLVE_SPELL;
|
||||||
|
public static final Identifier STEADFAST_SPELL;
|
||||||
|
public static final Identifier FLAME_SPELL;
|
||||||
|
public static final Identifier LEVITATE_SPELL;
|
||||||
|
public static final Identifier TELEPORT_SPELL;
|
||||||
|
public static final Identifier INWARD_SPELL;
|
||||||
|
public static final Identifier COOLING_SPELL;
|
||||||
|
public static final Identifier LIGHTNING_SPELL;
|
||||||
|
|
||||||
|
static {
|
||||||
|
HEAL_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "heal_spell"), HealSpell.class);
|
||||||
|
DAMAGE_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "damage_spell"), DamageSpell.class);
|
||||||
|
DISSOLVE_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "dissolve_spell"), DissolveSpell.class);
|
||||||
|
STEADFAST_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "steadfast_spell"), SteadfastSpell.class);
|
||||||
|
FLAME_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "flame_spell"), FlameSpell.class);
|
||||||
|
LEVITATE_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "levitate_spell"), LevitateSpell.class);
|
||||||
|
TELEPORT_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "teleport_spell"), TeleportSpell.class);
|
||||||
|
INWARD_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "inward_spell"), InwardSpell.class);
|
||||||
|
COOLING_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "cooling_spell"), CoolingSpell.class);
|
||||||
|
LIGHTNING_SPELL = SpellRegistry.register(new Identifier(SorceryCraft.NAMESPACE, "lightning_spell"), LightningSpell.class);
|
||||||
|
}
|
||||||
|
}
|
@ -1,11 +1,18 @@
|
|||||||
package com.thebrokenrail.sorcerycraft.spell;
|
package com.thebrokenrail.sorcerycraft.spell.util;
|
||||||
|
|
||||||
|
import com.google.gson.JsonDeserializationContext;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.loot.condition.LootCondition;
|
import net.minecraft.loot.condition.LootCondition;
|
||||||
import net.minecraft.loot.context.LootContext;
|
import net.minecraft.loot.context.LootContext;
|
||||||
import net.minecraft.loot.function.ConditionalLootFunction;
|
import net.minecraft.loot.function.ConditionalLootFunction;
|
||||||
import net.minecraft.loot.function.LootFunction;
|
import net.minecraft.loot.function.LootFunction;
|
||||||
|
import net.minecraft.loot.function.LootFunctionType;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.registry.Registry;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
@ -19,14 +26,30 @@ public class RandomSpellLootTableFunction extends ConditionalLootFunction {
|
|||||||
while (!(context.getRandom().nextDouble() > chance)) {
|
while (!(context.getRandom().nextDouble() > chance)) {
|
||||||
Spell[] spells = SpellRegistry.getSpells();
|
Spell[] spells = SpellRegistry.getSpells();
|
||||||
int index = context.getRandom().nextInt(spells.length);
|
int index = context.getRandom().nextInt(spells.length);
|
||||||
Map<Identifier, Integer> spell = SpellTag.getSpells(stack);
|
Map<Identifier, Integer> spell = SpellHelper.getSpells(stack);
|
||||||
spell.put(spells[index].getID(), spells[index].getLevel());
|
spell.put(spells[index].getID(), spells[index].getLevel());
|
||||||
SpellTag.setSpells(stack, spell);
|
SpellHelper.setSpells(stack, spell);
|
||||||
chance = chance * 0.25d;
|
chance = chance * 0.25d;
|
||||||
}
|
}
|
||||||
return stack;
|
return stack;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LootFunctionType getType() {
|
||||||
|
return Registry.LOOT_FUNCTION_TYPE.get(new Identifier(SorceryCraft.NAMESPACE, "random_spell"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class Factory extends ConditionalLootFunction.Serializer<RandomSpellLootTableFunction> {
|
||||||
|
public Factory() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RandomSpellLootTableFunction fromJson(JsonObject json, JsonDeserializationContext context, LootCondition[] conditions) {
|
||||||
|
return (RandomSpellLootTableFunction) new com.thebrokenrail.sorcerycraft.spell.util.RandomSpellLootTableFunction.Builder().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static class Builder extends ConditionalLootFunction.Builder<RandomSpellLootTableFunction.Builder> {
|
public static class Builder extends ConditionalLootFunction.Builder<RandomSpellLootTableFunction.Builder> {
|
||||||
@Override
|
@Override
|
||||||
protected RandomSpellLootTableFunction.Builder getThisBuilder() {
|
protected RandomSpellLootTableFunction.Builder getThisBuilder() {
|
@ -0,0 +1,138 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell.util;
|
||||||
|
|
||||||
|
import com.thebrokenrail.sorcerycraft.SorceryCraft;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.Spell;
|
||||||
|
import com.thebrokenrail.sorcerycraft.spell.api.registry.SpellRegistry;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.nbt.CompoundTag;
|
||||||
|
import net.minecraft.nbt.ListTag;
|
||||||
|
import net.minecraft.nbt.Tag;
|
||||||
|
import net.minecraft.network.MessageType;
|
||||||
|
import net.minecraft.network.packet.s2c.play.GameMessageS2CPacket;
|
||||||
|
import net.minecraft.server.network.ServerPlayerEntity;
|
||||||
|
import net.minecraft.text.LiteralText;
|
||||||
|
import net.minecraft.text.MutableText;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.text.TranslatableText;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.Util;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class SpellHelper {
|
||||||
|
public static final String SPELL_TAG = "Spells";
|
||||||
|
|
||||||
|
public static void setSpells(ItemStack itemStack, Map<Identifier, Integer> map) {
|
||||||
|
CompoundTag tag;
|
||||||
|
if (itemStack.hasTag()) {
|
||||||
|
tag = itemStack.getTag();
|
||||||
|
} else {
|
||||||
|
tag = new CompoundTag();
|
||||||
|
tag.put(SPELL_TAG, new ListTag());
|
||||||
|
}
|
||||||
|
assert tag != null;
|
||||||
|
|
||||||
|
tag.put(SPELL_TAG, createSpellsTag(map));
|
||||||
|
|
||||||
|
itemStack.setTag(tag);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ListTag createSpellsTag(Map<Identifier, Integer> map) {
|
||||||
|
ListTag spells = new ListTag();
|
||||||
|
|
||||||
|
for (Map.Entry<Identifier, Integer> entry : map.entrySet()) {
|
||||||
|
CompoundTag spell = new CompoundTag();
|
||||||
|
spell.putString("id", entry.getKey().toString());
|
||||||
|
spell.putInt("level", entry.getValue());
|
||||||
|
spells.add(spell);
|
||||||
|
}
|
||||||
|
|
||||||
|
return spells;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Identifier, Integer> getSpells(ItemStack itemStack) {
|
||||||
|
return getSpells(itemStack.getTag());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<Identifier, Integer> getSpells(CompoundTag tag) {
|
||||||
|
if (tag == null) {
|
||||||
|
tag = new CompoundTag();
|
||||||
|
tag.put(SPELL_TAG, new ListTag());
|
||||||
|
}
|
||||||
|
Tag spellsTag = tag.get(SPELL_TAG);
|
||||||
|
ListTag spells;
|
||||||
|
if (spellsTag instanceof ListTag) {
|
||||||
|
spells = (ListTag) spellsTag;
|
||||||
|
} else {
|
||||||
|
spells = new ListTag();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<Identifier, Integer> map = new HashMap<>();
|
||||||
|
|
||||||
|
for (int i = 0; i < spells.size(); i++) {
|
||||||
|
CompoundTag spell = spells.getCompound(i);
|
||||||
|
|
||||||
|
Identifier id = new Identifier(spell.getString("id"));
|
||||||
|
int level = spell.getInt("level");
|
||||||
|
|
||||||
|
if (map.get(id) == null || map.get(id) < level) {
|
||||||
|
map.put(id, level);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Text getTranslatedSpell(Identifier id, int level) {
|
||||||
|
Spell spell = SpellRegistry.getSpell(id, level);
|
||||||
|
MutableText text;
|
||||||
|
if (spell != null) {
|
||||||
|
text = spell.getTranslation();
|
||||||
|
} else {
|
||||||
|
text = Spell.getDefaultTranslation(id, level);
|
||||||
|
}
|
||||||
|
text.formatted(Formatting.GRAY);
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Text getTranslatedSpellChat(Identifier id, int level) {
|
||||||
|
return new LiteralText("[").append(SpellHelper.getTranslatedSpell(id, level).getString()).append("]").formatted(Formatting.GREEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void learnSpells(PlayerEntity player, Map<Identifier, Integer> itemSpells) {
|
||||||
|
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
|
||||||
|
World world = player.getEntityWorld();
|
||||||
|
|
||||||
|
Map<Identifier, Integer> playerSpells = spellPlayer.getDiscoveredSpells();
|
||||||
|
|
||||||
|
boolean changed = false;
|
||||||
|
|
||||||
|
for (Map.Entry<Identifier, Integer> entry : itemSpells.entrySet()) {
|
||||||
|
Spell spell = SpellRegistry.getSpell(entry);
|
||||||
|
if (spell != null) {
|
||||||
|
if (spell.getLevel() >= spell.getMaxLevel()) {
|
||||||
|
spell = SpellRegistry.getSpell(entry.getKey(), spell.getMaxLevel() - 1);
|
||||||
|
}
|
||||||
|
assert spell != null;
|
||||||
|
if (!playerSpells.containsKey(spell.getID()) || playerSpells.get(spell.getID()) < spell.getLevel()) {
|
||||||
|
changed = true;
|
||||||
|
|
||||||
|
playerSpells.put(spell.getID(), spell.getLevel());
|
||||||
|
assert world.getServer() != null;
|
||||||
|
Text text = getTranslatedSpellChat(spell.getID(), spell.getLevel());
|
||||||
|
world.getServer().getPlayerManager().sendToAll(new GameMessageS2CPacket(new TranslatableText("chat." + SorceryCraft.NAMESPACE + ".discovered_spell", player.getDisplayName(), text), MessageType.CHAT, Util.NIL_UUID));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changed) {
|
||||||
|
SorceryCraft.playSpellSound(player);
|
||||||
|
spellPlayer.setDiscoveredSpells(playerSpells);
|
||||||
|
SorceryCraft.DISCOVER_ALL_SPELLS_CRITERION.trigger((ServerPlayerEntity) player);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,11 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public interface SpellPlayerEntity {
|
||||||
|
void setDiscoveredSpells(Map<Identifier, Integer> spells);
|
||||||
|
|
||||||
|
Map<Identifier, Integer> getDiscoveredSpells();
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
package com.thebrokenrail.sorcerycraft.spell.util;
|
||||||
|
|
||||||
|
public interface SpellServerPlayerEntity extends SpellPlayerEntity {
|
||||||
|
void sync();
|
||||||
|
}
|
@ -1,19 +1,38 @@
|
|||||||
{
|
{
|
||||||
"item.sorcerycraft.spell": "Spell",
|
"item.sorcerycraft.spell": "Spell",
|
||||||
"block.sorcerycraft.casting_table": "Casting Table",
|
"block.sorcerycraft.casting_table": "Casting Table",
|
||||||
"itemGroup.sorcerycraft.spells": "SorceryCraft",
|
"itemGroup.sorcerycraft.spells": "SorceryCraft",
|
||||||
"container.sorcerycraft.casting_table": "Casting Table",
|
"container.sorcerycraft.casting_table": "Casting Table",
|
||||||
"container.sorcerycraft.spells": "Spells",
|
"container.sorcerycraft.spells": "Spells",
|
||||||
"chat.sorcerycraft.new_spell": "%s has learned the spell %s",
|
"chat.sorcerycraft.discovered_spell": "%s has discovered the spell %s",
|
||||||
"entity.sorcerycraft.spell": "Spell",
|
"entity.sorcerycraft.spell": "Spell",
|
||||||
"command.sorcerycraft.spell.cleared_spells": "All spells cleared from %s",
|
"command.sorcerycraft.spell.forgotten_spell": "%s has forgotten the spell %s",
|
||||||
"command.sorcerycraft.spell.listing_spells": "%s knows the following spells:",
|
"command.sorcerycraft.spell.listing_spells": "%s has discovered the following spells: %s",
|
||||||
"spell.sorcerycraft.damage_spell": "Damage",
|
"command.sorcerycraft.spell.unknown_spell": "Unknown spell: %s",
|
||||||
"spell.sorcerycraft.heal_spell": "Heal",
|
"command.sorcerycraft.spell.not_holding_spell": "%s is not holding a spell",
|
||||||
"spell.sorcerycraft.dissolve_spell": "Dissolve",
|
"command.sorcerycraft.spell.applied_spell": "Applied Spell %s",
|
||||||
"spell.sorcerycraft.steadfast_spell": "Steadfast",
|
"command.sorcerycraft.spell.removed_spell": "Removed Spell %s",
|
||||||
"spell.sorcerycraft.flame_spell": "Flame",
|
"stat.sorcerycraft.interact_with_casting_table": "Interactions with Casting Table",
|
||||||
"spell.sorcerycraft.levitate_spell": "Levitate",
|
"stat.sorcerycraft.cast_spell": "Spells Cast",
|
||||||
"spell.sorcerycraft.teleport_spell": "Teleport",
|
"text.autoconfig.sorcerycraft.title": "SorceryCraft Config",
|
||||||
"spell.sorcerycraft.inward_spell": "Inward"
|
"text.autoconfig.sorcerycraft.option.failureChance": "Spell Failure Chance",
|
||||||
|
"text.autoconfig.sorcerycraft.option.limitCastingTable": "Limit Casting Table To Discovered Spells",
|
||||||
|
"text.autoconfig.sorcerycraft.option.limitCastingTable.creative": "Creative Mode",
|
||||||
|
"text.autoconfig.sorcerycraft.option.limitCastingTable.survival": "Survival Mode",
|
||||||
|
"advancements.sorcerycraft.adventure.discover_spell.title": "Witchcraft!",
|
||||||
|
"advancements.sorcerycraft.adventure.discover_spell.description": "Discover a spell",
|
||||||
|
"advancements.sorcerycraft.adventure.create_spell.title": "Spellbinding!",
|
||||||
|
"advancements.sorcerycraft.adventure.create_spell.description": "Cast a spell using a Casting Table",
|
||||||
|
"advancements.sorcerycraft.adventure.discover_all_spells.title": "Master of Magic!",
|
||||||
|
"advancements.sorcerycraft.adventure.discover_all_spells.description": "Discover all spells",
|
||||||
|
"spell.sorcerycraft.damage_spell": "Damage",
|
||||||
|
"spell.sorcerycraft.heal_spell": "Heal",
|
||||||
|
"spell.sorcerycraft.dissolve_spell": "Dissolve",
|
||||||
|
"spell.sorcerycraft.steadfast_spell": "Steadfast",
|
||||||
|
"spell.sorcerycraft.flame_spell": "Flame",
|
||||||
|
"spell.sorcerycraft.levitate_spell": "Levitate",
|
||||||
|
"spell.sorcerycraft.teleport_spell": "Teleport",
|
||||||
|
"spell.sorcerycraft.inward_spell": "Inward",
|
||||||
|
"spell.sorcerycraft.cooling_spell": "Cooling",
|
||||||
|
"spell.sorcerycraft.lightning_spell": "Lightning"
|
||||||
}
|
}
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"parent": "item/generated",
|
"parent": "item/generated",
|
||||||
"textures": {
|
"textures": {
|
||||||
"layer0": "minecraft:item/paper"
|
"layer0": "sorcerycraft:item/spell"
|
||||||
}
|
}
|
||||||
}
|
}
|
Binary file not shown.
Before Width: | Height: | Size: 528 B After Width: | Height: | Size: 362 B |
BIN
src/main/resources/assets/sorcerycraft/textures/item/spell.png
Normal file
BIN
src/main/resources/assets/sorcerycraft/textures/item/spell.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"parent": "sorcerycraft:adventure/discover_spell",
|
||||||
|
"display": {
|
||||||
|
"icon": {
|
||||||
|
"item": "sorcerycraft:casting_table"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"translate": "advancements.sorcerycraft.adventure.create_spell.title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"translate": "advancements.sorcerycraft.adventure.create_spell.description"
|
||||||
|
},
|
||||||
|
"frame": "task",
|
||||||
|
"show_toast": true,
|
||||||
|
"announce_to_chat": true,
|
||||||
|
"hidden": false
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"sorcerycraft:casting_table": {
|
||||||
|
"trigger": "sorcerycraft:create_spell"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"parent": "sorcerycraft:adventure/create_spell",
|
||||||
|
"display": {
|
||||||
|
"icon": {
|
||||||
|
"item": "sorcerycraft:spell",
|
||||||
|
"nbt": "{Spells: [{id: \"sorcerycraft:damage_spell\", level: 0}]}"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"translate": "advancements.sorcerycraft.adventure.discover_all_spells.title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"translate": "advancements.sorcerycraft.adventure.discover_all_spells.description"
|
||||||
|
},
|
||||||
|
"frame": "challenge",
|
||||||
|
"show_toast": true,
|
||||||
|
"announce_to_chat": true,
|
||||||
|
"hidden": false
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"sorcerycraft:spell": {
|
||||||
|
"trigger": "sorcerycraft:discover_all_spells"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rewards": {
|
||||||
|
"experience": 100
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,36 @@
|
|||||||
|
{
|
||||||
|
"parent": "minecraft:adventure/root",
|
||||||
|
"display": {
|
||||||
|
"icon": {
|
||||||
|
"item": "sorcerycraft:spell"
|
||||||
|
},
|
||||||
|
"title": {
|
||||||
|
"translate": "advancements.sorcerycraft.adventure.discover_spell.title"
|
||||||
|
},
|
||||||
|
"description": {
|
||||||
|
"translate": "advancements.sorcerycraft.adventure.discover_spell.description"
|
||||||
|
},
|
||||||
|
"frame": "task",
|
||||||
|
"show_toast": true,
|
||||||
|
"announce_to_chat": true,
|
||||||
|
"hidden": false
|
||||||
|
},
|
||||||
|
"criteria": {
|
||||||
|
"sorcerycraft:spell": {
|
||||||
|
"trigger": "minecraft:inventory_changed",
|
||||||
|
"conditions": {
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"item": "sorcerycraft:spell"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rewards": {
|
||||||
|
"recipes": [
|
||||||
|
"sorcerycraft:spell",
|
||||||
|
"sorcerycraft:casting_table"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
@ -1,19 +1,19 @@
|
|||||||
{
|
{
|
||||||
"type": "minecraft:block",
|
"type": "minecraft:block",
|
||||||
"pools": [
|
"pools": [
|
||||||
{
|
|
||||||
"rolls": 1,
|
|
||||||
"entries": [
|
|
||||||
{
|
{
|
||||||
"type": "minecraft:item",
|
"rolls": 1,
|
||||||
"name": "sorcerycraft:casting_table"
|
"entries": [
|
||||||
|
{
|
||||||
|
"type": "minecraft:item",
|
||||||
|
"name": "sorcerycraft:casting_table"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"conditions": [
|
||||||
|
{
|
||||||
|
"condition": "minecraft:survives_explosion"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
],
|
]
|
||||||
"conditions": [
|
|
||||||
{
|
|
||||||
"condition": "minecraft:survives_explosion"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
@ -1,24 +1,23 @@
|
|||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
"LCL",
|
"LSL",
|
||||||
"CDC",
|
"SDS",
|
||||||
"LCL"
|
"LSL"
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"L": {
|
"L": {
|
||||||
"item": "minecraft:lapis_lazuli"
|
"item": "minecraft:lapis_lazuli"
|
||||||
|
},
|
||||||
|
"S": {
|
||||||
|
"item": "minecraft:smooth_stone"
|
||||||
|
},
|
||||||
|
"D": {
|
||||||
|
"item": "minecraft:diamond"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"C": {
|
"result": {
|
||||||
"item": "minecraft:cobblestone"
|
"item": "sorcerycraft:casting_table"
|
||||||
},
|
|
||||||
"D": {
|
|
||||||
"item": "minecraft:diamond"
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"item": "sorcerycraft:casting_table",
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,21 @@
|
|||||||
{
|
{
|
||||||
"type": "minecraft:crafting_shaped",
|
"type": "minecraft:crafting_shaped",
|
||||||
"pattern": [
|
"pattern": [
|
||||||
" L ",
|
" L ",
|
||||||
"LPL",
|
"LPL",
|
||||||
" L "
|
" L "
|
||||||
],
|
],
|
||||||
"key": {
|
"key": {
|
||||||
"L": {
|
"L": {
|
||||||
"item": "minecraft:lapis_lazuli"
|
"item": "minecraft:lapis_lazuli"
|
||||||
|
},
|
||||||
|
"P": {
|
||||||
|
"item": "minecraft:paper"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"P": {
|
"result": {
|
||||||
"item": "minecraft:paper"
|
"item": "sorcerycraft:spell",
|
||||||
|
"count": 1
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"result": {
|
|
||||||
"item": "sorcerycraft:spell",
|
|
||||||
"count": 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,33 +1,43 @@
|
|||||||
{
|
{
|
||||||
"schemaVersion": 1,
|
"schemaVersion": 1,
|
||||||
"id": "sorcerycraft",
|
"id": "sorcerycraft",
|
||||||
"version": "${version}",
|
"version": "${version}",
|
||||||
"name": "SorceryCraft",
|
"name": "${name}",
|
||||||
"description": "Cast Spells in Minecraft!",
|
"description": "Cast Spells in Minecraft!",
|
||||||
"authors": [
|
"authors": [
|
||||||
"TheBrokenRail"
|
"TheBrokenRail"
|
||||||
],
|
|
||||||
"contact": {
|
|
||||||
"homepage": "https://thebrokenrail.com/",
|
|
||||||
"sources": "https://gitea.thebrokenrail.com/TheBrokenRail/SorceryCraft.git"
|
|
||||||
},
|
|
||||||
"license": "MIT",
|
|
||||||
"icon": "assets/sorcerycraft/textures/block/casting_table.png",
|
|
||||||
"environment": "*",
|
|
||||||
"entrypoints": {
|
|
||||||
"main": [
|
|
||||||
"com.thebrokenrail.sorcerycraft.SorceryCraft"
|
|
||||||
],
|
],
|
||||||
"client": [
|
"contact": {
|
||||||
"com.thebrokenrail.sorcerycraft.SorceryCraft"
|
"homepage": "https://thebrokenrail.com/",
|
||||||
]
|
"sources": "https://gitea.thebrokenrail.com/TheBrokenRail/SorceryCraft.git",
|
||||||
},
|
"issues": "https://gitea.thebrokenrail.com/TheBrokenRail/SorceryCraft/issues"
|
||||||
"mixins": [
|
},
|
||||||
"sorcerycraft.mixins.json"
|
"license": "MIT",
|
||||||
],
|
"icon": "assets/sorcerycraft/textures/item/spell.png",
|
||||||
"depends": {
|
"environment": "*",
|
||||||
"fabricloader": ">=0.7.4",
|
"entrypoints": {
|
||||||
"fabric": "*",
|
"main": [
|
||||||
"minecraft": "1.16.x"
|
"com.thebrokenrail.sorcerycraft.SorceryCraft"
|
||||||
}
|
],
|
||||||
|
"client": [
|
||||||
|
"com.thebrokenrail.sorcerycraft.client.SorceryCraftClient"
|
||||||
|
],
|
||||||
|
"modmenu": [
|
||||||
|
"com.thebrokenrail.sorcerycraft.client.ModMenu"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"mixins": [
|
||||||
|
"sorcerycraft.mixins.json"
|
||||||
|
],
|
||||||
|
"depends": {
|
||||||
|
"fabricloader": ">=0.7.4",
|
||||||
|
"fabric": "*",
|
||||||
|
"minecraft": "1.16.x"
|
||||||
|
},
|
||||||
|
"custom": {
|
||||||
|
"modupdater": {
|
||||||
|
"strategy": "curseforge",
|
||||||
|
"projectID": 365308
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,18 @@
|
|||||||
{
|
{
|
||||||
"required": true,
|
"required": true,
|
||||||
"package": "com.thebrokenrail.sorcerycraft.mixin",
|
"package": "com.thebrokenrail.sorcerycraft.mixin",
|
||||||
"compatibilityLevel": "JAVA_8",
|
"compatibilityLevel": "JAVA_8",
|
||||||
"client": [
|
"client": [
|
||||||
"MixinClientPlayNetworkHandler"
|
"MixinClientPlayerEntity",
|
||||||
],
|
"MixinClientPlayNetworkHandler",
|
||||||
"mixins": [
|
"MixinAbstractButtonWidget"
|
||||||
"MixinPlayerEntity",
|
],
|
||||||
"MixinServerPlayerEntity"
|
"mixins": [
|
||||||
],
|
"CriteriaRegistryHook",
|
||||||
"injectors": {
|
"MixinPlayerEntity",
|
||||||
"defaultRequire": 1
|
"MixinServerPlayerEntity"
|
||||||
}
|
],
|
||||||
|
"injectors": {
|
||||||
|
"defaultRequire": 1
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user