commit 3334e8325aa3c0e1be5e720c6c220b18c2903f52 Author: micle Date: Wed Aug 18 16:01:31 2021 +0100 Initial commit. diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..265ba43 --- /dev/null +++ b/build.gradle @@ -0,0 +1,181 @@ +buildscript { + repositories { + // These repositories are only for Gradle plugins, put any other repositories in the repository block further below + maven { url = 'https://maven.minecraftforge.net' } + mavenCentral() + } + dependencies { + classpath group: 'net.minecraftforge.gradle', name: 'ForgeGradle', version: '5.1.+', changing: true + } +} +apply plugin: 'net.minecraftforge.gradle' +// Only edit below this line, the above code adds and enables the necessary things for Forge to be setup. +apply plugin: 'eclipse' +apply plugin: 'maven-publish' + +version = '1.0' +group = 'com.micle.totemofreviving' // http://maven.apache.org/guides/mini/guide-naming-conventions.html +archivesBaseName = 'totemofreviving' + +// Mojang ships Java 16 to end users in 1.17+ instead of Java 8 in 1.16 or lower, so your mod should target Java 16. +java.toolchain.languageVersion = JavaLanguageVersion.of(16) + +println('Java: ' + System.getProperty('java.version') + ' JVM: ' + System.getProperty('java.vm.version') + '(' + System.getProperty('java.vendor') + ') Arch: ' + System.getProperty('os.arch')) +minecraft { + // The mappings can be changed at any time and must be in the following format. + // Channel: Version: + // snapshot YYYYMMDD Snapshot are built nightly. + // stable # Stables are built at the discretion of the MCP team. + // official MCVersion Official field/method names from Mojang mapping files + // + // You must be aware of the Mojang license when using the 'official' mappings. + // See more information here: https://github.com/MinecraftForge/MCPConfig/blob/master/Mojang.md + // + // Use non-default mappings at your own risk. They may not always work. + // Simply re-run your setup task after changing the mappings to update your workspace. + mappings channel: 'official', version: '1.17.1' + + // accessTransformer = file('src/main/resources/META-INF/accesstransformer.cfg') // Currently, this location cannot be changed from the default. + + // Default run configurations. + // These can be tweaked, removed, or duplicated as needed. + runs { + client { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + totemofreviving { + source sourceSets.main + } + } + } + + server { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + mods { + totemofreviving { + source sourceSets.main + } + } + } + + data { + workingDirectory project.file('run') + + // Recommended logging data for a userdev environment + // The markers can be added/remove as needed separated by commas. + // "SCAN": For mods scan. + // "REGISTRIES": For firing of registry events. + // "REGISTRYDUMP": For getting the contents of all registries. + property 'forge.logging.markers', 'REGISTRIES' + + // Recommended logging level for the console + // You can set various levels here. + // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels + property 'forge.logging.console.level', 'debug' + + // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources. + args '--mod', 'totemofreviving', '--all', + '--existing', file('src/main/resources').toString(), + '--existing', file('src/generated/resources').toString(), + '--output', file('src/generated/resources/') + + mods { + totemofreviving { + source sourceSets.main + } + } + } + } +} + +// Include resources generated by data generators. +sourceSets.main.resources { srcDir 'src/generated/resources' } + +repositories { + // Put repositories for dependencies here + // ForgeGradle automatically adds the Forge maven and Maven Central for you + + // If you have mod jar dependencies in ./libs, you can declare them as a repository like so: + // flatDir { + // dir 'libs' + // } +} + +dependencies { + // Specify the version of Minecraft to use. If this is any group other than 'net.minecraft', it is assumed + // that the dep is a ForgeGradle 'patcher' dependency, and its patches will be applied. + // The userdev artifact is a special name and will get all sorts of transformations applied to it. + minecraft 'net.minecraftforge:forge:1.17.1-37.0.33' + + // Real mod deobf dependency examples - these get remapped to your current mappings + // compileOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}:api") // Adds JEI API as a compile dependency + // runtimeOnly fg.deobf("mezz.jei:jei-${mc_version}:${jei_version}") // Adds the full JEI mod as a runtime dependency + // implementation fg.deobf("com.tterrag.registrate:Registrate:MC${mc_version}-${registrate_version}") // Adds registrate as a dependency + + // Examples using mod jars from ./libs + // implementation fg.deobf("blank:coolmod-${mc_version}:${coolmod_version}") + + // For more info... + // http://www.gradle.org/docs/current/userguide/artifact_dependencies_tutorial.html + // http://www.gradle.org/docs/current/userguide/dependency_management.html +} + +// Example for how to get properties into the manifest for reading at runtime. +jar { + manifest { + attributes([ + "Specification-Title" : "totemofreviving", + "Specification-Vendor" : "totemofrevivingsareus", + "Specification-Version" : "1", // We are version 1 of ourselves + "Implementation-Title" : project.name, + "Implementation-Version" : project.jar.archiveVersion, + "Implementation-Vendor" : "totemofrevivingsareus", + "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ") + ]) + } +} + +// Example configuration to allow publishing using the maven-publish plugin +// This is the preferred method to reobfuscate your jar file +jar.finalizedBy('reobfJar') +// However if you are in a multi-project build, dev time needs unobfed jar files, so you can delay the obfuscation until publishing by doing +// publish.dependsOn('reobfJar') + +publishing { + publications { + mavenJava(MavenPublication) { + artifact jar + } + } + repositories { + maven { + url "file://${project.projectDir}/mcmodsrepo" + } + } +} diff --git a/src/main/java/com/micle/totemofreviving/TotemOfReviving.java b/src/main/java/com/micle/totemofreviving/TotemOfReviving.java new file mode 100755 index 0000000..7faa730 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/TotemOfReviving.java @@ -0,0 +1,53 @@ +package com.micle.totemofreviving; + +import com.micle.totemofreviving.network.C2SRequestPlayerRevive; +import com.micle.totemofreviving.network.C2SRequestTotemCharge; +import com.micle.totemofreviving.network.C2SRequestTotemTarget; +import com.micle.totemofreviving.setup.Registration; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.players.PlayerList; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fmllegacy.network.NetworkRegistry; +import net.minecraftforge.fmllegacy.network.simple.SimpleChannel; + +@Mod(TotemOfReviving.MOD_ID) +public class TotemOfReviving { + public static final String MOD_ID = "totemofreviving"; + public static PlayerList players; + + private static final String PROTOCOL_VERSION = "1"; + public static final SimpleChannel INSTANCE = NetworkRegistry.newSimpleChannel( + new ResourceLocation(TotemOfReviving.MOD_ID, "main"), + () -> PROTOCOL_VERSION, + PROTOCOL_VERSION::equals, + PROTOCOL_VERSION::equals + ); + + public TotemOfReviving() { + Registration.register(); + + int id = 0; + INSTANCE.registerMessage(id++, + C2SRequestPlayerRevive.class, + C2SRequestPlayerRevive::encode, + C2SRequestPlayerRevive::decode, + C2SRequestPlayerRevive::handle + ); + INSTANCE.registerMessage(id++, + C2SRequestTotemTarget.class, + C2SRequestTotemTarget::encode, + C2SRequestTotemTarget::decode, + C2SRequestTotemTarget::handle + ); + INSTANCE.registerMessage(id++, + C2SRequestTotemCharge.class, + C2SRequestTotemCharge::encode, + C2SRequestTotemCharge::decode, + C2SRequestTotemCharge::handle + ); + + // Register ourselves for server and other game events we are interested in + MinecraftForge.EVENT_BUS.register(this); + } +} diff --git a/src/main/java/com/micle/totemofreviving/data/DataGenerators.java b/src/main/java/com/micle/totemofreviving/data/DataGenerators.java new file mode 100755 index 0000000..a918425 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/data/DataGenerators.java @@ -0,0 +1,24 @@ +package com.micle.totemofreviving.data; + +import com.micle.totemofreviving.TotemOfReviving; +import com.micle.totemofreviving.data.client.ModItemModelProvider; +import net.minecraft.data.DataGenerator; +import net.minecraftforge.common.data.ExistingFileHelper; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.forge.event.lifecycle.GatherDataEvent; + +@Mod.EventBusSubscriber(modid = TotemOfReviving.MOD_ID, bus = Mod.EventBusSubscriber.Bus.MOD) +public class DataGenerators { + private DataGenerators() {} + + @SubscribeEvent + public static void gatherData(GatherDataEvent e) { + DataGenerator gen = e.getGenerator(); + ExistingFileHelper existing_file_helper = e.getExistingFileHelper(); + + gen.addProvider(new ModItemModelProvider(gen, existing_file_helper)); + + gen.addProvider(new ModRecipeProvider(gen)); + } +} diff --git a/src/main/java/com/micle/totemofreviving/data/ModRecipeProvider.java b/src/main/java/com/micle/totemofreviving/data/ModRecipeProvider.java new file mode 100755 index 0000000..8c046f6 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/data/ModRecipeProvider.java @@ -0,0 +1,56 @@ +package com.micle.totemofreviving.data; + +import com.micle.totemofreviving.setup.ModItems; +import net.minecraft.data.DataGenerator; +import net.minecraft.data.recipes.FinishedRecipe; +import net.minecraft.data.recipes.RecipeProvider; +import net.minecraft.data.recipes.ShapedRecipeBuilder; +import net.minecraft.world.item.Items; + +import java.util.function.Consumer; + +public class ModRecipeProvider extends RecipeProvider { + public ModRecipeProvider(DataGenerator generator_in) { + super(generator_in); + } + + @Override + protected void buildCraftingRecipes(Consumer consumer) { + ShapedRecipeBuilder.shaped(ModItems.TOTEM_OF_REVIVING.get()) + .define('#', Items.TOTEM_OF_UNDYING) + .define('@', Items.DIAMOND) + .pattern("@@@") + .pattern("@#@") + .pattern("@@@") + .unlockedBy("has_item", has(Items.TOTEM_OF_UNDYING)) + .save(consumer); + ShapedRecipeBuilder.shaped(ModItems.REVIVING_CHARGE.get()) + .define('#', Items.TOTEM_OF_UNDYING) + .define('@', Items.DIAMOND_BLOCK) + .define('E', Items.ENDER_PEARL) + .pattern("@E@") + .pattern("E#E") + .pattern("@E@") + .unlockedBy("has_item", has(ModItems.TOTEM_OF_REVIVING.get())) + .save(consumer); + ShapedRecipeBuilder.shaped(ModItems.STRAW_TOTEM.get()) + .define('W', Items.WHEAT) + .define('/', Items.STICK) + .define('S', Items.STRING) + .define('N', Items.IRON_NUGGET) + .pattern("NSN") + .pattern("NWN") + .pattern("N/N") + .unlockedBy("has_item", has(Items.WHEAT)) + .save(consumer); + ShapedRecipeBuilder.shaped(ModItems.STRAW_CHARGE.get()) + .define('W', Items.WHEAT) + .define('E', Items.EMERALD) + .define('I', Items.IRON_INGOT) + .pattern("IWI") + .pattern("WEW") + .pattern("IWI") + .unlockedBy("has_item", has(Items.EMERALD)) + .save(consumer); + } +} diff --git a/src/main/java/com/micle/totemofreviving/data/client/ModItemModelProvider.java b/src/main/java/com/micle/totemofreviving/data/client/ModItemModelProvider.java new file mode 100755 index 0000000..fe5aa2f --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/data/client/ModItemModelProvider.java @@ -0,0 +1,28 @@ +package com.micle.totemofreviving.data.client; + +import com.micle.totemofreviving.TotemOfReviving; +import net.minecraft.data.DataGenerator; +import net.minecraftforge.client.model.generators.ItemModelBuilder; +import net.minecraftforge.client.model.generators.ItemModelProvider; +import net.minecraftforge.client.model.generators.ModelFile; +import net.minecraftforge.common.data.ExistingFileHelper; + +public class ModItemModelProvider extends ItemModelProvider { + public ModItemModelProvider(DataGenerator generator, ExistingFileHelper existing_file_helper) { + super(generator, TotemOfReviving.MOD_ID, existing_file_helper); + } + + @Override + protected void registerModels() { + ModelFile item_generated = getExistingFile(mcLoc("item/generated")); + + builder(item_generated, "totem_of_reviving"); + builder(item_generated, "reviving_charge"); + builder(item_generated, "straw_totem"); + builder(item_generated, "straw_charge"); + } + + private ItemModelBuilder builder(ModelFile item_generated, String name) { + return getBuilder(name).parent(item_generated).texture("layer0", "item/" + name); + } +} diff --git a/src/main/java/com/micle/totemofreviving/events/ServerTickEventHandler.java b/src/main/java/com/micle/totemofreviving/events/ServerTickEventHandler.java new file mode 100755 index 0000000..75ab9c4 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/events/ServerTickEventHandler.java @@ -0,0 +1,13 @@ +package com.micle.totemofreviving.events; + +import com.micle.totemofreviving.TotemOfReviving; +import net.minecraftforge.event.TickEvent; +import net.minecraftforge.eventbus.api.SubscribeEvent; +import net.minecraftforge.fmllegacy.server.ServerLifecycleHooks; + +public class ServerTickEventHandler { + @SubscribeEvent + public void onServerTick(TickEvent.ServerTickEvent event) { + TotemOfReviving.players = ServerLifecycleHooks.getCurrentServer().getPlayerList(); + } +} diff --git a/src/main/java/com/micle/totemofreviving/items/RevivingChargeItem.java b/src/main/java/com/micle/totemofreviving/items/RevivingChargeItem.java new file mode 100755 index 0000000..733968f --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/items/RevivingChargeItem.java @@ -0,0 +1,11 @@ +package com.micle.totemofreviving.items; + +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Rarity; + +public class RevivingChargeItem extends Item { + public RevivingChargeItem() { + super(new Item.Properties().tab(CreativeModeTab.TAB_MISC).rarity(Rarity.RARE)); + } +} diff --git a/src/main/java/com/micle/totemofreviving/items/StrawChargeItem.java b/src/main/java/com/micle/totemofreviving/items/StrawChargeItem.java new file mode 100755 index 0000000..595bcb1 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/items/StrawChargeItem.java @@ -0,0 +1,11 @@ +package com.micle.totemofreviving.items; + +import net.minecraft.world.item.CreativeModeTab; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.Rarity; + +public class StrawChargeItem extends Item { + public StrawChargeItem() { + super(new Item.Properties().tab(CreativeModeTab.TAB_MISC).rarity(Rarity.UNCOMMON)); + } +} diff --git a/src/main/java/com/micle/totemofreviving/items/StrawTotemItem.java b/src/main/java/com/micle/totemofreviving/items/StrawTotemItem.java new file mode 100755 index 0000000..b5966b4 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/items/StrawTotemItem.java @@ -0,0 +1,82 @@ +package com.micle.totemofreviving.items; + +import com.micle.totemofreviving.TotemOfReviving; +import com.micle.totemofreviving.network.C2SRequestPlayerRevive; +import com.micle.totemofreviving.network.C2SRequestTotemCharge; +import com.micle.totemofreviving.network.C2SRequestTotemTarget; +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.ChatFormatting; +import net.minecraft.client.KeyMapping; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.*; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import java.util.List; + +public class StrawTotemItem extends Item { + public static final String TAG_CHARGE_AMOUNT = "charge"; + public static final String TAG_TARGET_INDEX = "target_index"; + public static final String TAG_TARGET_NAME = "target_name"; + public static final String TAG_FAIL_CHANCE = "fail_chance"; + public static final int STARTING_FAIL_CHANCE = 45; + private static final KeyMapping KEY_LSHIFT = new KeyMapping("StrawTotemItem_LSHIFT", InputConstants.KEY_LSHIFT, KeyMapping.CATEGORY_INTERFACE); + + public StrawTotemItem() { + super(new Item.Properties().tab(CreativeModeTab.TAB_MISC).stacksTo(1).rarity(Rarity.UNCOMMON)); + } + + @Override + public void appendHoverText(ItemStack stack, Level world, List tooltip, TooltipFlag flag) { + super.appendHoverText(stack, world, tooltip, flag); + tooltip.add(new TextComponent(ChatFormatting.GOLD + "Charges: " + ChatFormatting.GRAY + stack.getOrCreateTag().getInt(TAG_CHARGE_AMOUNT))); + tooltip.add(new TextComponent(ChatFormatting.GOLD + "Target: " + ChatFormatting.GRAY + stack.getOrCreateTag().getString(TAG_TARGET_NAME))); + tooltip.add(new TextComponent(ChatFormatting.GOLD + "Fail Chance: " + ChatFormatting.GRAY + stack.getOrCreateTag().getInt(TAG_FAIL_CHANCE))); + tooltip.add(new TextComponent( ChatFormatting.DARK_GRAY + "" + ChatFormatting.ITALIC + "\"Feels kinda funky.\"")); + tooltip.add(new TextComponent("")); + if (KEY_LSHIFT.isDown()) { + tooltip.add(new TextComponent(ChatFormatting.YELLOW + "R-CLICK")); + tooltip.add(new TextComponent(ChatFormatting.GOLD + "When other hand is empty: attempt to revive target.")); + tooltip.add(new TextComponent(ChatFormatting.GOLD + "When other hand has " + ChatFormatting.GRAY + "Straw Reviving Charge" + ChatFormatting.GOLD + ": charge totem.")); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent(ChatFormatting.YELLOW + "SHIFT R-CLICK")); + tooltip.add(new TextComponent(ChatFormatting.GOLD + "Cycle through available targets.")); + } else { + tooltip.add(new TextComponent(ChatFormatting.GRAY + "[" + ChatFormatting.WHITE + "LSHIFT" + ChatFormatting.GRAY + "] for advanced tooltip.")); + } + } + + @Override + public void onCraftedBy(ItemStack stack, Level world, Player player) { + super.onCraftedBy(stack, world, player); + stack.getOrCreateTag().putInt(TAG_CHARGE_AMOUNT, 0); + stack.getOrCreateTag().putInt(TAG_FAIL_CHANCE, STARTING_FAIL_CHANCE); + } + + @Override + @OnlyIn(Dist.CLIENT) + public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + if (!world.isClientSide) { return super.use(world, player, hand); } + if (player.isCrouching()) { + TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemTarget(player.getUUID(), hand)); + } else { + InteractionHand item_charge_hand = InteractionHand.MAIN_HAND; + if (hand.equals(InteractionHand.MAIN_HAND)) { + item_charge_hand = InteractionHand.OFF_HAND; + } + Item item_charge = player.getItemInHand(item_charge_hand).getItem(); + + if (item_charge instanceof StrawChargeItem) { + TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemCharge(player.getUUID(), hand, item_charge_hand)); + } else { + TotemOfReviving.INSTANCE.sendToServer(new C2SRequestPlayerRevive(player.getUUID(), hand)); + } + } + return super.use(world, player, hand); + } +} diff --git a/src/main/java/com/micle/totemofreviving/items/TotemOfRevivingItem.java b/src/main/java/com/micle/totemofreviving/items/TotemOfRevivingItem.java new file mode 100755 index 0000000..68c36c7 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/items/TotemOfRevivingItem.java @@ -0,0 +1,78 @@ +package com.micle.totemofreviving.items; + +import com.micle.totemofreviving.TotemOfReviving; +import com.micle.totemofreviving.network.C2SRequestPlayerRevive; +import com.micle.totemofreviving.network.C2SRequestTotemCharge; +import com.micle.totemofreviving.network.C2SRequestTotemTarget; +import com.mojang.blaze3d.platform.InputConstants; +import net.minecraft.ChatFormatting; +import net.minecraft.client.KeyMapping; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResultHolder; +import net.minecraft.world.entity.player.Player; +import net.minecraft.world.item.*; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; + +import java.util.List; + +public class TotemOfRevivingItem extends Item { + public static final String TAG_CHARGE_AMOUNT = "charge"; + public static final String TAG_TARGET_INDEX = "target_index"; + public static final String TAG_TARGET_NAME = "target_name"; + private static final KeyMapping KEY_LSHIFT = new KeyMapping("TotemOfRevivingItem_LSHIFT", InputConstants.KEY_LSHIFT, KeyMapping.CATEGORY_INTERFACE); + + public TotemOfRevivingItem() { + super(new Item.Properties().tab(CreativeModeTab.TAB_MISC).stacksTo(1).rarity(Rarity.RARE)); + } + + @Override + public void appendHoverText(ItemStack stack, Level world, List tooltip, TooltipFlag flag) { + super.appendHoverText(stack, world, tooltip, flag); + tooltip.add(new TextComponent(ChatFormatting.DARK_AQUA + "Charges: " + ChatFormatting.BLUE + stack.getOrCreateTag().getInt(TAG_CHARGE_AMOUNT)) { + }); + tooltip.add(new TextComponent(ChatFormatting.DARK_AQUA + "Target: " + ChatFormatting.BLUE + stack.getOrCreateTag().getString(TAG_TARGET_NAME))); + tooltip.add(new TextComponent("")); + if (KEY_LSHIFT.isDown()) { + tooltip.add(new TextComponent(ChatFormatting.AQUA + "R-CLICK")); + tooltip.add(new TextComponent(ChatFormatting.DARK_AQUA + "When other hand is empty: attempt to revive target.")); + tooltip.add(new TextComponent(ChatFormatting.DARK_AQUA + "When other hand has " + ChatFormatting.BLUE + "Reviving Charge" + ChatFormatting.DARK_AQUA + ": charge totem.")); + tooltip.add(new TextComponent("")); + tooltip.add(new TextComponent(ChatFormatting.AQUA + "SHIFT R-CLICK")); + tooltip.add(new TextComponent(ChatFormatting.DARK_AQUA + "Cycle through available targets.")); + } else { + tooltip.add(new TextComponent(ChatFormatting.GRAY + "[" + ChatFormatting.WHITE + "LSHIFT" + ChatFormatting.GRAY + "] for advanced tooltip.")); + } + } + + @Override + public void onCraftedBy(ItemStack stack, Level world, Player player) { + super.onCraftedBy(stack, world, player); + stack.getOrCreateTag().putInt(TAG_CHARGE_AMOUNT, 0); + } + + @Override + @OnlyIn(Dist.CLIENT) + public InteractionResultHolder use(Level world, Player player, InteractionHand hand) { + if (!world.isClientSide) { return super.use(world, player, hand); } + if (player.isCrouching()) { + TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemTarget(player.getUUID(), hand)); + } else { + InteractionHand item_charge_hand = InteractionHand.MAIN_HAND; + if (hand.equals(InteractionHand.MAIN_HAND)) { + item_charge_hand = InteractionHand.OFF_HAND; + } + Item item_charge = player.getItemInHand(item_charge_hand).getItem(); + + if (item_charge instanceof RevivingChargeItem) { + TotemOfReviving.INSTANCE.sendToServer(new C2SRequestTotemCharge(player.getUUID(), hand, item_charge_hand)); + } else { + TotemOfReviving.INSTANCE.sendToServer(new C2SRequestPlayerRevive(player.getUUID(), hand)); + } + } + return super.use(world, player, hand); + } +} diff --git a/src/main/java/com/micle/totemofreviving/network/C2SRequestPlayerRevive.java b/src/main/java/com/micle/totemofreviving/network/C2SRequestPlayerRevive.java new file mode 100755 index 0000000..3ae4ad1 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/network/C2SRequestPlayerRevive.java @@ -0,0 +1,86 @@ +package com.micle.totemofreviving.network; + +import com.micle.totemofreviving.TotemOfReviving; +import com.micle.totemofreviving.items.StrawTotemItem; +import com.micle.totemofreviving.items.TotemOfRevivingItem; +import com.micle.totemofreviving.utils.Utils; +import net.minecraft.ChatFormatting; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.stats.Stats; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.GameType; +import net.minecraftforge.fmllegacy.network.NetworkEvent; + +import java.util.UUID; +import java.util.function.Supplier; + +public class C2SRequestPlayerRevive { + private final UUID player_uuid; + private final InteractionHand hand; + + public C2SRequestPlayerRevive(final UUID player_uuid, final InteractionHand hand) { + this.player_uuid = player_uuid; + this.hand = hand; + } + + public static void encode(final C2SRequestPlayerRevive msg, FriendlyByteBuf packet_buffer) { + packet_buffer.writeUUID( msg.player_uuid); + packet_buffer.writeEnum(msg.hand); + } + + public static C2SRequestPlayerRevive decode(final FriendlyByteBuf packet_buffer) { + return new C2SRequestPlayerRevive(packet_buffer.readUUID(), packet_buffer.readEnum(InteractionHand.class)); + } + + public static void handle(final C2SRequestPlayerRevive msg, final Supplier context_supplier) { + final NetworkEvent.Context context = context_supplier.get(); + context.enqueueWork(() -> { + final ServerPlayer sender = TotemOfReviving.players.getPlayer(msg.player_uuid); + if (sender == null) { return; } + + ItemStack item = sender.getItemInHand(msg.hand); + if (item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_TARGET_INDEX) > TotemOfReviving.players.getPlayerCount()-1 || item.getOrCreateTag().getString(TotemOfRevivingItem.TAG_TARGET_NAME).equals("")) { + sender.sendMessage(new TextComponent(ChatFormatting.RED + "Error getting target! (Try selecting the target again)"), sender.getUUID()); + } else { + ServerPlayer player_to_revive = TotemOfReviving.players.getPlayerByName(item.getOrCreateTag().getString(TotemOfRevivingItem.TAG_TARGET_NAME)); + ServerLevel player_to_revive_world = player_to_revive.getLevel(); + ServerLevel sender_world = sender.getLevel(); + int required_charge = player_to_revive.getStats().getValue(Stats.CUSTOM.get(Stats.DEATHS)); + if (player_to_revive.isSpectator()) { + if (player_to_revive_world.equals(sender_world)) { + if (item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT) >= required_charge) { + if (item.getOrCreateTag().contains(StrawTotemItem.TAG_FAIL_CHANCE)) { + int fail_chance = item.getOrCreateTag().getInt(StrawTotemItem.TAG_FAIL_CHANCE); + if (Utils.randomIntRange(0, 100) <= fail_chance) { + item.getOrCreateTag().putInt(StrawTotemItem.TAG_CHARGE_AMOUNT, item.getOrCreateTag().getInt(StrawTotemItem.TAG_CHARGE_AMOUNT)-required_charge); + item.getOrCreateTag().putInt(StrawTotemItem.TAG_FAIL_CHANCE, fail_chance-(5*required_charge)); + sender.addEffect(new MobEffectInstance(MobEffects.POISON, ((fail_chance*10) / 2), 1)); + return; + } else { + item.getOrCreateTag().putInt(StrawTotemItem.TAG_FAIL_CHANCE, fail_chance-(5*required_charge)); + } + } + player_to_revive.teleportTo(sender.getX(), sender.getY(), sender.getZ()); + player_to_revive.setGameMode(GameType.SURVIVAL); + item.getOrCreateTag().putInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT, item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT) - required_charge); + sender.sendMessage(new TextComponent(ChatFormatting.GRAY + "Successfully revived " + ChatFormatting.DARK_GRAY + player_to_revive.getDisplayName().getString()), sender.getUUID()); + } else { + sender.sendMessage(new TextComponent(ChatFormatting.GRAY + "Not enough charge! Required charge is: " + ChatFormatting.DARK_GRAY + required_charge), sender.getUUID()); + } + } else { + sender.sendMessage(new TextComponent(ChatFormatting.DARK_GRAY + player_to_revive.getDisplayName().getString() + ChatFormatting.GRAY + " is not in this dimension!"), sender.getUUID()); + } + } else { + sender.sendMessage(new TextComponent(ChatFormatting.DARK_GRAY + player_to_revive.getDisplayName().getString() + ChatFormatting.GRAY + " is not dead!"), sender.getUUID()); + } + } + }); + context.setPacketHandled(true); + } +} diff --git a/src/main/java/com/micle/totemofreviving/network/C2SRequestTotemCharge.java b/src/main/java/com/micle/totemofreviving/network/C2SRequestTotemCharge.java new file mode 100755 index 0000000..2dbbf0d --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/network/C2SRequestTotemCharge.java @@ -0,0 +1,63 @@ +package com.micle.totemofreviving.network; + +import com.micle.totemofreviving.TotemOfReviving; +import com.micle.totemofreviving.items.StrawTotemItem; +import com.micle.totemofreviving.items.TotemOfRevivingItem; +import com.micle.totemofreviving.utils.Utils; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.effect.MobEffectInstance; +import net.minecraft.world.effect.MobEffects; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraftforge.fmllegacy.network.NetworkEvent; + +import java.util.UUID; +import java.util.function.Supplier; + +public class C2SRequestTotemCharge { + private final UUID player_uuid; + private final InteractionHand hand; + private final InteractionHand item_charge_hand; + + public C2SRequestTotemCharge(final UUID player_uuid, final InteractionHand hand, final InteractionHand item_charge_hand) { + this.player_uuid = player_uuid; + this.hand = hand; + this.item_charge_hand = item_charge_hand; + } + + public static void encode(final C2SRequestTotemCharge msg, final FriendlyByteBuf packet_buffer) { + packet_buffer.writeUUID(msg.player_uuid); + packet_buffer.writeEnum(msg.hand); + packet_buffer.writeEnum(msg.item_charge_hand); + } + + public static C2SRequestTotemCharge decode(final FriendlyByteBuf packet_buffer) { + return new C2SRequestTotemCharge(packet_buffer.readUUID(), packet_buffer.readEnum(InteractionHand.class), packet_buffer.readEnum(InteractionHand.class)); + } + + public static void handle(final C2SRequestTotemCharge msg, final Supplier context_supplier) { + final NetworkEvent.Context context = context_supplier.get(); + context.enqueueWork(() -> { + final ServerPlayer sender = TotemOfReviving.players.getPlayer(msg.player_uuid); + if (sender == null) { return; } + + ItemStack charge_item = sender.getItemInHand(msg.item_charge_hand); + ItemStack totem_item = sender.getItemInHand(msg.hand); + charge_item.setCount(charge_item.getCount()-1); + totem_item.getOrCreateTag().putInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT, totem_item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_CHARGE_AMOUNT)+1); + + if (totem_item.getOrCreateTag().contains(StrawTotemItem.TAG_FAIL_CHANCE)) { + int fail_chance = totem_item.getOrCreateTag().getInt(StrawTotemItem.TAG_FAIL_CHANCE); + if (Utils.randomIntRange(0, 100) <= fail_chance) { + sender.setItemInHand(msg.hand, new ItemStack(Items.AIR)); + sender.addEffect(new MobEffectInstance(MobEffects.POISON, ((fail_chance*10) / 2), 1)); + } else { + totem_item.getOrCreateTag().putInt(StrawTotemItem.TAG_FAIL_CHANCE, fail_chance+5); + } + } + }); + context.setPacketHandled(true); + } +} diff --git a/src/main/java/com/micle/totemofreviving/network/C2SRequestTotemTarget.java b/src/main/java/com/micle/totemofreviving/network/C2SRequestTotemTarget.java new file mode 100755 index 0000000..3d83e33 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/network/C2SRequestTotemTarget.java @@ -0,0 +1,52 @@ +package com.micle.totemofreviving.network; + +import com.micle.totemofreviving.TotemOfReviving; +import com.micle.totemofreviving.items.TotemOfRevivingItem; +import net.minecraft.ChatFormatting; +import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.network.chat.TextComponent; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.InteractionHand; +import net.minecraft.world.item.ItemStack; +import net.minecraftforge.fmllegacy.network.NetworkEvent; + +import java.util.UUID; +import java.util.function.Supplier; + +public class C2SRequestTotemTarget { + private final UUID player_uuid; + private final InteractionHand hand; + + public C2SRequestTotemTarget(final UUID player_uuid, final InteractionHand hand) { + this.player_uuid = player_uuid; + this.hand = hand; + } + + public static void encode(final C2SRequestTotemTarget msg, final FriendlyByteBuf packet_buffer) { + packet_buffer.writeUUID(msg.player_uuid); + packet_buffer.writeEnum(msg.hand); + } + + public static C2SRequestTotemTarget decode(final FriendlyByteBuf packet_buffer) { + return new C2SRequestTotemTarget(packet_buffer.readUUID(), packet_buffer.readEnum(InteractionHand.class)); + } + + public static void handle(final C2SRequestTotemTarget msg, final Supplier context_supplier) { + final NetworkEvent.Context context = context_supplier.get(); + context.enqueueWork(() -> { + final ServerPlayer sender = TotemOfReviving.players.getPlayer(msg.player_uuid); + if (sender == null) { return; } + + ItemStack item = sender.getItemInHand(msg.hand); + int current_player_index = item.getOrCreateTag().getInt(TotemOfRevivingItem.TAG_TARGET_INDEX) + 1; + if (current_player_index > TotemOfReviving.players.getPlayerCount()-1) { + current_player_index = 0; + } + + item.getOrCreateTag().putInt(TotemOfRevivingItem.TAG_TARGET_INDEX, current_player_index); + item.getOrCreateTag().putString(TotemOfRevivingItem.TAG_TARGET_NAME, TotemOfReviving.players.getPlayers().get(current_player_index).getDisplayName().getString()); + sender.sendMessage(new TextComponent(ChatFormatting.GRAY + "Target: " + ChatFormatting.DARK_GRAY + item.getOrCreateTag().getString(TotemOfRevivingItem.TAG_TARGET_NAME)), sender.getUUID()); + }); + context.setPacketHandled(true); + } +} diff --git a/src/main/java/com/micle/totemofreviving/setup/ModItems.java b/src/main/java/com/micle/totemofreviving/setup/ModItems.java new file mode 100755 index 0000000..90aa13d --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/setup/ModItems.java @@ -0,0 +1,18 @@ +package com.micle.totemofreviving.setup; + +import com.micle.totemofreviving.items.RevivingChargeItem; +import com.micle.totemofreviving.items.StrawChargeItem; +import com.micle.totemofreviving.items.StrawTotemItem; +import com.micle.totemofreviving.items.TotemOfRevivingItem; +import net.minecraft.world.item.Item; +import net.minecraftforge.fmllegacy.RegistryObject; + +public class ModItems { + public static final RegistryObject TOTEM_OF_REVIVING = Registration.ITEMS.register("totem_of_reviving", TotemOfRevivingItem::new); + public static final RegistryObject REVIVING_CHARGE = Registration.ITEMS.register("reviving_charge", RevivingChargeItem::new); + public static final RegistryObject STRAW_TOTEM = Registration.ITEMS.register("straw_totem", StrawTotemItem::new); + public static final RegistryObject STRAW_CHARGE = Registration.ITEMS.register("straw_charge", StrawChargeItem::new); + + static void register() { + } +} diff --git a/src/main/java/com/micle/totemofreviving/setup/Registration.java b/src/main/java/com/micle/totemofreviving/setup/Registration.java new file mode 100755 index 0000000..5c605b7 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/setup/Registration.java @@ -0,0 +1,25 @@ +package com.micle.totemofreviving.setup; + +import com.micle.totemofreviving.TotemOfReviving; +import com.micle.totemofreviving.events.ServerTickEventHandler; +import net.minecraft.world.item.Item; +import net.minecraft.world.level.block.Block; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.eventbus.api.IEventBus; +import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext; +import net.minecraftforge.registries.DeferredRegister; +import net.minecraftforge.registries.ForgeRegistries; + +public class Registration { + public static final DeferredRegister BLOCKS = DeferredRegister.create(ForgeRegistries.BLOCKS, TotemOfReviving.MOD_ID); + public static final DeferredRegister ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS, TotemOfReviving.MOD_ID); + + public static void register() { + IEventBus mod_event_bus = FMLJavaModLoadingContext.get().getModEventBus(); + BLOCKS.register(mod_event_bus); + ITEMS.register(mod_event_bus); + MinecraftForge.EVENT_BUS.register(new ServerTickEventHandler()); + + ModItems.register(); + } +} diff --git a/src/main/java/com/micle/totemofreviving/utils/Utils.java b/src/main/java/com/micle/totemofreviving/utils/Utils.java new file mode 100755 index 0000000..36bdac6 --- /dev/null +++ b/src/main/java/com/micle/totemofreviving/utils/Utils.java @@ -0,0 +1,19 @@ +package com.micle.totemofreviving.utils; + +public class Utils { + public static float clamp(float val, float min, float max) { + return Math.max(min, Math.min(max, val)); + } + + public static int randomIntRange(int min, int max) { + return (int) randomDoubleRange(min, max); + } + + public static float randomFloatRange(float min, float max) { + return (float) randomDoubleRange(min, max); + } + + public static double randomDoubleRange(double min, double max) { + return ((Math.random() * (max - min)) + min); + } +} diff --git a/src/main/resources/META-INF/mods.toml b/src/main/resources/META-INF/mods.toml new file mode 100755 index 0000000..84ec75e --- /dev/null +++ b/src/main/resources/META-INF/mods.toml @@ -0,0 +1,58 @@ +# This is an example mods.toml file. It contains the data relating to the loading mods. +# There are several mandatory fields (#mandatory), and many more that are optional (#optional). +# The overall format is standard TOML format, v0.5.0. +# Note that there are a couple of TOML lists in this file. +# Find more information on toml format here: https://github.com/toml-lang/toml +# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml +modLoader="javafml" #mandatory +# A version range to match for said mod loader - for regular FML @Mod it will be the forge version +loaderVersion="[37,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions. +# The license for you mod. This is mandatory metadata and allows for easier comprehension of your redistributive properties. +# Review your options at https://choosealicense.com/. All rights reserved is the default copyright stance, and is thus the default here. +license="All rights reserved" +# A URL to refer people to when problems occur with this mod +#issueTrackerURL="https://change.me.to.your.issue.tracker.example.invalid/" #optional +# A list of mods - how many allowed here is determined by the individual mod loader +[[mods]] #mandatory +# The modid of the mod +modId="totemofreviving" #mandatory +# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it +# ${file.jarVersion} will substitute the value of the Implementation-Version as read from the mod's JAR file metadata +# see the associated build.gradle script for how to populate this completely automatically during a build +version="${file.jarVersion}" #mandatory + # A display name for the mod +displayName="Micle's Totem of Reviving" #mandatory +# A URL to query for updates for this mod. See the JSON update specification https://mcforge.readthedocs.io/en/latest/gettingstarted/autoupdate/ +#updateJSONURL="https://change.me.example.invalid/updates.json" #optional +# A URL for the "homepage" for this mod, displayed in the mod UI +#displayURL="https://change.me.to.your.mods.homepage.example.invalid/" #optional +# A file name (in the root of the mod JAR) containing a logo for display +#logoFile="examplemod.png" #optional +# A text field displayed in the mod UI +#credits="Thanks for this example mod goes to Java" #optional +# A text field displayed in the mod UI +authors="Micle" #optional +# The description text for the mod (multi line!) (#mandatory) +description=''' +Mod for reviving players in a hardcore world. +''' +# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. +[[dependencies.totemofreviving]] #optional + # the modid of the dependency + modId="forge" #mandatory + # Does this dependency have to exist - if not, ordering below must be specified + mandatory=true #mandatory + # The version range of the dependency + versionRange="[37,)" #mandatory + # An ordering relationship for the dependency - BEFORE or AFTER required if the relationship is not mandatory + ordering="NONE" + # Side this dependency is applied on - BOTH, CLIENT or SERVER + side="BOTH" +# Here's another dependency +[[dependencies.totemofreviving]] + modId="minecraft" + mandatory=true +# This version range declares a minimum of the current minecraft version up to but not including the next major version + versionRange="[1.17.1,1.18)" + ordering="NONE" + side="BOTH" diff --git a/src/main/resources/assets/totemofreviving/lang/en_us.json b/src/main/resources/assets/totemofreviving/lang/en_us.json new file mode 100755 index 0000000..11a801d --- /dev/null +++ b/src/main/resources/assets/totemofreviving/lang/en_us.json @@ -0,0 +1,6 @@ +{ + "item.totemofreviving.totem_of_reviving": "Totem of Reviving", + "item.totemofreviving.reviving_charge": "Reviving charge", + "item.totemofreviving.straw_totem": "Straw Totem of Reviving", + "item.totemofreviving.straw_charge": "Straw reviving charge" +} \ No newline at end of file diff --git a/src/main/resources/assets/totemofreviving/textures/item/reviving_charge.png b/src/main/resources/assets/totemofreviving/textures/item/reviving_charge.png new file mode 100755 index 0000000..b6081b1 Binary files /dev/null and b/src/main/resources/assets/totemofreviving/textures/item/reviving_charge.png differ diff --git a/src/main/resources/assets/totemofreviving/textures/item/straw_charge.png b/src/main/resources/assets/totemofreviving/textures/item/straw_charge.png new file mode 100755 index 0000000..2a2e23b Binary files /dev/null and b/src/main/resources/assets/totemofreviving/textures/item/straw_charge.png differ diff --git a/src/main/resources/assets/totemofreviving/textures/item/straw_totem.png b/src/main/resources/assets/totemofreviving/textures/item/straw_totem.png new file mode 100755 index 0000000..a2d6cfe Binary files /dev/null and b/src/main/resources/assets/totemofreviving/textures/item/straw_totem.png differ diff --git a/src/main/resources/assets/totemofreviving/textures/item/totem_of_reviving.png b/src/main/resources/assets/totemofreviving/textures/item/totem_of_reviving.png new file mode 100755 index 0000000..82772bc Binary files /dev/null and b/src/main/resources/assets/totemofreviving/textures/item/totem_of_reviving.png differ diff --git a/src/main/resources/pack.mcmeta b/src/main/resources/pack.mcmeta new file mode 100755 index 0000000..44a5cc8 --- /dev/null +++ b/src/main/resources/pack.mcmeta @@ -0,0 +1,7 @@ +{ + "pack": { + "description": "totemofreviving resources", + "pack_format": 6, + "_comment": "A pack_format of 6 requires json lang files and some texture changes from 1.16.2. Note: we require v6 pack meta for all mods." + } +}