Compare commits

...

2 commits

Author SHA1 Message Date
b20f8314d0 Update Changelog.md, Reproducibility.md
All checks were successful
Build TurnBasedMC and create Release / build-and-create-release (push) Successful in 1m41s
2024-01-16 22:19:13 +09:00
e1e462cb6d Bump version to 1.25.1, update to forge 49.0.19
MC Version 1.20.4
2024-01-16 22:17:06 +09:00
12 changed files with 275 additions and 244 deletions

View file

@ -1,7 +1,12 @@
# Upcoming changes # Upcoming changes
# Version Forge-1.25.1
Add icon for mod in Mod list description. Add icon for mod in Mod list description.
Update for Forge 49.0.19.
Works on Forge Minecraft 1.20.4.
# Version NeoForge-1.25.1 # Version NeoForge-1.25.1
Add icon for mod in Mod list description. Add icon for mod in Mod list description.

View file

@ -71,7 +71,7 @@ configured for them.)
Simply invoke `./gradlew build` in the mod directory and after some time the Simply invoke `./gradlew build` in the mod directory and after some time the
finished jar will be saved at finished jar will be saved at
`build/libs/TurnBasedMinecraft-Forge-1.25.0-all.jar` `build/libs/TurnBasedMinecraft-Forge-1.25.1-all.jar`
# Reproducibility # Reproducibility

View file

@ -4,6 +4,19 @@ Starting with version 1.24.0 of this mod, this file will list what version of
Java was used to compile the jars. In theory, using the same version of Java Java was used to compile the jars. In theory, using the same version of Java
should result in an identical jar due to reproducible builds. should result in an identical jar due to reproducible builds.
## Forge 1.25.1
$ java --version
openjdk 17.0.9 2023-10-17
OpenJDK Runtime Environment (build 17.0.9+8)
OpenJDK 64-Bit Server VM (build 17.0.9+8, mixed mode)
$ javac --version
javac 17.0.9
$ sha256sum build/libs/TurnBasedMinecraft-Forge-1.25.1-all.jar
33711947eed8b24fa7fd65d36ecdb6ed78e144af8d7fff6e1bfa304cfe4a1d3d build/libs/TurnBasedMinecraft-Forge-1.25.1-all.jar
## NeoForge 1.25.1 ## NeoForge 1.25.1
$ java --version $ java --version

View file

@ -5,8 +5,8 @@ plugins {
id 'net.minecraftforge.gradle' version '[6.0.16,6.2)' id 'net.minecraftforge.gradle' version '[6.0.16,6.2)'
} }
version = "1.25.0" version = mod_version
group = "com.burnedkirby.TurnBasedMinecraft" group = mod_group_id
archivesBaseName = "TurnBasedMinecraft-Forge" archivesBaseName = "TurnBasedMinecraft-Forge"
java.toolchain.languageVersion = JavaLanguageVersion.of(17) java.toolchain.languageVersion = JavaLanguageVersion.of(17)
@ -33,48 +33,8 @@ minecraft {
// Default run configurations. // Default run configurations.
// These can be tweaked, removed, or duplicated as needed. // These can be tweaked, removed, or duplicated as needed.
runs { runs {
client { // applies to all the run configs below
workingDirectory project.file('run') configureEach {
// Recommended logging data for a userdev environment
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', 'TurnBasedMinecraftMod'
mods {
TurnBasedMinecraftMod {
source sourceSets.main
}
}
}
server {
workingDirectory project.file('run')
// Recommended logging data for a userdev environment
property 'forge.logging.markers', 'REGISTRIES'
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', 'TurnBasedMinecraftMod'
mods {
TurnBasedMinecraftMod {
source sourceSets.main
}
}
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
workingDirectory project.file('run') workingDirectory project.file('run')
// Recommended logging data for a userdev environment // Recommended logging data for a userdev environment
@ -88,33 +48,31 @@ minecraft {
// You can set various levels here. // You can set various levels here.
// Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels // Please read: https://stackoverflow.com/questions/2031163/when-to-use-the-different-log-levels
property 'forge.logging.console.level', 'debug' property 'forge.logging.console.level', 'debug'
}
client {
// Comma-separated list of namespaces to load gametests from. Empty = all namespaces. // Comma-separated list of namespaces to load gametests from. Empty = all namespaces.
property 'forge.enabledGameTestNamespaces', 'TurnBasedMinecraftMod' property 'forge.enabledGameTestNamespaces', mod_id
}
mods { server {
TurnBasedMinecraftMod { property 'forge.enabledGameTestNamespaces', mod_id
source sourceSets.main args '--nogui'
} }
}
// This run config launches GameTestServer and runs all registered gametests, then exits.
// By default, the server will crash when no gametests are provided.
// The gametest system is also enabled by default for other run configs under the /test command.
gameTestServer {
property 'forge.enabledGameTestNamespaces', mod_id
} }
data { data {
workingDirectory project.file('run') // example of overriding the workingDirectory set in configureEach above
workingDirectory project.file('run-data')
// Recommended logging data for a userdev environment // Specify the modid for data generation, where to output the resulting resource, and where to look for existing resources.
property 'forge.logging.markers', 'REGISTRIES' args '--mod', mod_id, '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources/')
// Recommended logging level for the console
property 'forge.logging.console.level', 'debug'
args '--mod', 'TurnBasedMinecraftMod', '--all', '--output', file('src/generated/resources/'), '--existing', file('src/main/resources')
mods {
TurnBasedMinecraftMod {
source sourceSets.main
}
}
} }
} }
} }
@ -122,22 +80,6 @@ minecraft {
// Include resources generated by data generators. // Include resources generated by data generators.
sourceSets.main.resources { srcDir 'src/generated/resources' } 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'
// // }
// mavenCentral()
// jcenter()
//
// dependencies {
// classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.4'
// }
//}
repositories { repositories {
flatDir { flatDir {
dir 'libs' dir 'libs'
@ -145,23 +87,13 @@ repositories {
} }
dependencies { dependencies {
// Specify the version of Minecraft to use, If this is any group other then 'net.minecraft' it is assumed // Specify the version of Minecraft to use.
// that the dep is a ForgeGradle 'patcher' dependency. And it's patches will be applied. // Any artifact can be supplied so long as it has a "userdev" classifier artifact and is a compatible patcher artifact.
// The userdev artifact is a special name and will get all sorts of transformations applied to it. // The "userdev" classifier will be requested and setup by ForgeGradle.
// If the group id is "net.minecraft" and the artifact id is one of ["client", "server", "joined"],
// then special handling is done to allow a setup of a vanilla dependency without the use of an external repository.
minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}" minecraft "net.minecraftforge:forge:${minecraft_version}-${forge_version}"
// 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
//implementation files('libs/javamp3-1.0.3.jar')
implementation 'fr.delthas:javamp3:1.0.3' implementation 'fr.delthas:javamp3:1.0.3'
implementation 'com.github.stephengold:j-ogg-vorbis:1.0.4' implementation 'com.github.stephengold:j-ogg-vorbis:1.0.4'
@ -194,22 +126,21 @@ tasks.named('processResources', ProcessResources).configure {
} }
} }
// Example for how to get properties into the manifest for reading by the runtime.. // Example for how to get properties into the manifest for reading at runtime.
jar { tasks.named('jar', Jar).configure {
archiveClassifier = 'slim'
manifest { manifest {
attributes([ attributes([
"Specification-Title": "TurnBasedMinecraftMod", 'Specification-Title' : mod_id,
"Specification-Vendor": "TurnBasedMinecraftMod_BK", 'Specification-Vendor' : mod_authors,
"Specification-Version": "1", // We are version 1 of ourselves 'Specification-Version' : '1', // We are version 1 of ourselves
"Implementation-Title": "TurnBasedMinecraftMod", 'Implementation-Title' : "TurnBasedMinecraftMod",
"Implementation-Version": "${version}", 'Implementation-Version' : project.jar.archiveVersion,
"Implementation-Vendor" :"TurnBasedMinecraftMod_BK", 'Implementation-Vendor' : mod_authors
// Do not place timestamp for the sake of reproducible builds
// "Implementation-Timestamp": new Date().format("yyyy-MM-dd'T'HH:mm:ssZ"),
// "ContainedDeps": "javamp3-1.0.3.jar"
]) ])
} }
// This is the preferred method to reobfuscate your jar file
finalizedBy 'reobfJar'
} }
// Reproducible Builds // Reproducible Builds
@ -218,24 +149,16 @@ tasks.withType(AbstractArchiveTask).configureEach {
reproducibleFileOrder = true reproducibleFileOrder = true
} }
// Example configuration to allow publishing using the maven-publish task tasks.withType(JavaCompile).configureEach {
// we define a custom artifact that is sourced from the reobfJar output task options.encoding = 'UTF-8' // Use the UTF-8 charset for Java compilation
// and then declare that to be published }
// Note you'll need to add a repository here
//def reobfFile = file("$buildDir/reobfJar/output.jar") // Merge the resources and classes into the same directory.
//def reobfArtifact = artifacts.add('default', reobfFile) { // This is done because java expects modules to be in a single directory.
// type 'jar' // And if we have it in multiple we have to do performance intensive hacks like having the UnionFileSystem
// builtBy 'reobfJar' // This will eventually be migrated to ForgeGradle so modders don't need to manually do it. But that is later.
//} sourceSets.each {
//publishing { def dir = layout.buildDirectory.dir("sourcesSets/$it.name")
// publications { it.output.resourcesDir = dir
// mavenJava(MavenPublication) { it.java.destinationDirectory = dir
// artifact reobfArtifact }
// }
// }
// repositories {
// maven {
// url "file:///${project.projectDir}/mcmodsrepo"
// }
// }
//}

View file

@ -4,17 +4,17 @@ org.gradle.daemon=false
## Environment Properties ## Environment Properties
# The Minecraft version must agree with the Forge version to get a valid artifact # The Minecraft version must agree with the Forge version to get a valid artifact
minecraft_version=1.20.2 minecraft_version=1.20.4
# The Minecraft version range can use any release version of Minecraft as bounds. # The Minecraft version range can use any release version of Minecraft as bounds.
# Snapshots, pre-releases, and release candidates are not guaranteed to sort properly # Snapshots, pre-releases, and release candidates are not guaranteed to sort properly
# as they do not follow standard versioning conventions. # as they do not follow standard versioning conventions.
minecraft_version_range=[1.20.2,1.21) minecraft_version_range=[1.20.4,1.21)
# The Forge version must agree with the Minecraft version to get a valid artifact # The Forge version must agree with the Minecraft version to get a valid artifact
forge_version=48.1.0 forge_version=49.0.19
# The Forge version range can use any version of Forge as bounds or match the loader version range # The Forge version range can use any version of Forge as bounds or match the loader version range
forge_version_range=[48,) forge_version_range=[0,)
# The loader version range can only use the major version of Forge/FML as bounds # The loader version range can only use the major version of Forge/FML as bounds
loader_version_range=[48,) loader_version_range=[0,)
# The mapping channel to use for mappings. # The mapping channel to use for mappings.
# The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"]. # The default set of supported mapping channels are ["official", "snapshot", "snapshot_nodoc", "stable", "stable_nodoc"].
# Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin. # Additional mapping channels can be registered through the "channelProviders" extension in a Gradle plugin.
@ -32,7 +32,7 @@ loader_version_range=[48,)
mapping_channel=official mapping_channel=official
# The mapping version to query from the mapping channel. # The mapping version to query from the mapping channel.
# This must match the format required by the mapping channel. # This must match the format required by the mapping channel.
mapping_version=1.20.2 mapping_version=1.20.4
## Mod Properties ## Mod Properties
@ -44,11 +44,11 @@ mod_name=TurnBasedMinecraftMod
# The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default. # The license of the mod. Review your options at https://choosealicense.com/. All Rights Reserved is the default.
mod_license=MIT mod_license=MIT
# The mod version. See https://semver.org/ # The mod version. See https://semver.org/
mod_version=1.25.0 mod_version=1.25.1
# The group ID for the mod. It is only important when publishing as an artifact to a Maven repository. # The group ID for the mod. It is only important when publishing as an artifact to a Maven repository.
# This should match the base package used for the mod sources. # This should match the base package used for the mod sources.
# See https://maven.apache.org/guides/mini/guide-naming-conventions.html # See https://maven.apache.org/guides/mini/guide-naming-conventions.html
#mod_group_id=com.example.examplemod mod_group_id=com.burnedkirby.TurnBasedMinecraft
# The authors of the mod. This is a simple text string that is used for display purposes in the mod list. # The authors of the mod. This is a simple text string that is used for display purposes in the mod list.
mod_authors=BurnedKirby a.k.a. Stephen Seo mod_authors=BurnedKirby a.k.a. Stephen Seo
# The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list. # The description of the mod. This is a simple multiline text string that is used for display purposes in the mod list.

View file

@ -150,11 +150,11 @@ public class BattleGui extends Screen {
.getSideAEntrySet()) { .getSideAEntrySet()) {
if (e.getValue().entity != null) { if (e.getValue().entity != null) {
addRenderableWidget(new EntitySelectionButton(width / 4 - 60, y, 120, 20, e.getValue().entity.getDisplayName(), e.getKey(), true, (button) -> { addRenderableWidget(new EntitySelectionButton(width / 4 - 60, y, 120, 20, e.getValue().entity.getDisplayName(), e.getKey(), true, (button) -> {
buttonActionEvent(button, ButtonAction.ATTACK_TARGET); entityButtonActionEvent(button, ButtonAction.ATTACK_TARGET);
})); }));
} else { } else {
addRenderableWidget(new EntitySelectionButton(width / 4 - 60, y, 120, 20, "Unknown", e.getKey(), true, (button) -> { addRenderableWidget(new EntitySelectionButton(width / 4 - 60, y, 120, 20, "Unknown", e.getKey(), true, (button) -> {
buttonActionEvent(button, ButtonAction.ATTACK_TARGET); entityButtonActionEvent(button, ButtonAction.ATTACK_TARGET);
})); }));
} }
y += 20; y += 20;
@ -168,11 +168,11 @@ public class BattleGui extends Screen {
.getSideBEntrySet()) { .getSideBEntrySet()) {
if (e.getValue().entity != null) { if (e.getValue().entity != null) {
addRenderableWidget(new EntitySelectionButton(width * 3 / 4 - 60, y, 120, 20, e.getValue().entity.getDisplayName(), e.getKey(), false, (button) -> { addRenderableWidget(new EntitySelectionButton(width * 3 / 4 - 60, y, 120, 20, e.getValue().entity.getDisplayName(), e.getKey(), false, (button) -> {
buttonActionEvent(button, ButtonAction.ATTACK_TARGET); entityButtonActionEvent(button, ButtonAction.ATTACK_TARGET);
})); }));
} else { } else {
addRenderableWidget(new EntitySelectionButton(width * 3 / 4 - 60, y, 120, 20, "Unknown", e.getKey(), false, (button) -> { addRenderableWidget(new EntitySelectionButton(width * 3 / 4 - 60, y, 120, 20, "Unknown", e.getKey(), false, (button) -> {
buttonActionEvent(button, ButtonAction.ATTACK_TARGET); entityButtonActionEvent(button, ButtonAction.ATTACK_TARGET);
})); }));
} }
y += 20; y += 20;
@ -202,8 +202,8 @@ public class BattleGui extends Screen {
case SWITCH_ITEM: case SWITCH_ITEM:
info = "To which item will you switch to?"; info = "To which item will you switch to?";
for (int i = 0; i < 9; ++i) { for (int i = 0; i < 9; ++i) {
addRenderableWidget(new ItemSelectionButton(width / 2 - 88 + i * 20, height - 19, 16, 16, "", i, (button) -> { addRenderableWidget(new ItemSelectionButton(width / 2 - 88 + i * 20, height - 19, 16, 16, i, (button) -> {
buttonActionEvent(button, ButtonAction.DO_ITEM_SWITCH); itemButtonActionEvent(button, ButtonAction.DO_ITEM_SWITCH);
})); }));
} }
addRenderableWidget(Button.builder(Component.literal("Cancel"), (button) -> { addRenderableWidget(Button.builder(Component.literal("Cancel"), (button) -> {
@ -213,8 +213,8 @@ public class BattleGui extends Screen {
case USE_ITEM: case USE_ITEM:
info = "Which item will you use?"; info = "Which item will you use?";
for (int i = 0; i < 9; ++i) { for (int i = 0; i < 9; ++i) {
addRenderableWidget(new ItemSelectionButton(width / 2 - 88 + i * 20, height - 19, 16, 16, "", i, (button) -> { addRenderableWidget(new ItemSelectionButton(width / 2 - 88 + i * 20, height - 19, 16, 16, i, (button) -> {
buttonActionEvent(button, ButtonAction.DO_USE_ITEM); itemButtonActionEvent(button, ButtonAction.DO_USE_ITEM);
})); }));
} }
addRenderableWidget(Button.builder(Component.literal("Cancel"), (button) -> { addRenderableWidget(Button.builder(Component.literal("Cancel"), (button) -> {
@ -269,10 +269,6 @@ public class BattleGui extends Screen {
drawString(guiGraphics, info, width / 2 - stringWidth / 2, 20, 0xFFFFFFFF); drawString(guiGraphics, info, width / 2 - stringWidth / 2, 20, 0xFFFFFFFF);
} }
@Override
public void renderBackground(GuiGraphics p_283688_, int p_299421_, int p_298679_, float p_297268_) {
}
protected void buttonActionEvent(AbstractButton button, ButtonAction action) { protected void buttonActionEvent(AbstractButton button, ButtonAction action) {
switch (action) { switch (action) {
case ATTACK: case ATTACK:
@ -294,14 +290,8 @@ public class BattleGui extends Screen {
setState(MenuState.WAITING); setState(MenuState.WAITING);
break; break;
case ATTACK_TARGET: case ATTACK_TARGET:
if (button instanceof EntitySelectionButton) { // Invalid but set to main menu anyways.
TurnBasedMinecraftMod.getHandler().send(new PacketBattleDecision( setState(MenuState.MAIN_MENU);
TurnBasedMinecraftMod.proxy.getLocalBattle().getId(), Battle.Decision.ATTACK, ((EntitySelectionButton) button).getID()),
PacketDistributor.SERVER.noArg());
setState(MenuState.WAITING);
} else {
setState(MenuState.MAIN_MENU);
}
break; break;
case SWITCH_HELD_ITEM: case SWITCH_HELD_ITEM:
setState(MenuState.SWITCH_ITEM); setState(MenuState.SWITCH_ITEM);
@ -313,28 +303,47 @@ public class BattleGui extends Screen {
setState(MenuState.MAIN_MENU); setState(MenuState.MAIN_MENU);
break; break;
case DO_ITEM_SWITCH: case DO_ITEM_SWITCH:
if (button instanceof ItemSelectionButton) { // Invalid but set to main menu anyways.
TurnBasedMinecraftMod.getHandler().send(new PacketBattleDecision( setState(MenuState.MAIN_MENU);
TurnBasedMinecraftMod.proxy.getLocalBattle().getId(), Battle.Decision.SWITCH_ITEM, ((ItemSelectionButton) button).getID()),
PacketDistributor.SERVER.noArg());
if (((ItemSelectionButton) button).getID() >= 0 && ((ItemSelectionButton) button).getID() < 9) {
Minecraft.getInstance().player.getInventory().selected = ((ItemSelectionButton) button).getID();
}
setState(MenuState.WAITING);
} else {
setState(MenuState.MAIN_MENU);
}
break; break;
case DO_USE_ITEM: case DO_USE_ITEM:
if (button instanceof ItemSelectionButton) { // Invalid, but set menu to main menu anyways.
TurnBasedMinecraftMod.getHandler().send(new PacketBattleDecision( setState(MenuState.MAIN_MENU);
TurnBasedMinecraftMod.proxy.getLocalBattle().getId(), Battle.Decision.USE_ITEM, ((ItemSelectionButton) button).getID()), break;
}
}
protected void entityButtonActionEvent(EntitySelectionButton button, ButtonAction action) {
if (action.equals(ButtonAction.ATTACK_TARGET)) {
TurnBasedMinecraftMod.getHandler().send(new PacketBattleDecision(
TurnBasedMinecraftMod.proxy.getLocalBattle().getId(), Battle.Decision.ATTACK, button.getID()),
PacketDistributor.SERVER.noArg());
setState(MenuState.WAITING);
} else {
setState(MenuState.MAIN_MENU);
}
}
protected void itemButtonActionEvent(ItemSelectionButton button, ButtonAction action) {
switch (action) {
case DO_ITEM_SWITCH:
TurnBasedMinecraftMod.getHandler().send(
new PacketBattleDecision(TurnBasedMinecraftMod.proxy.getLocalBattle().getId(), Battle.Decision.SWITCH_ITEM, button.getID()),
PacketDistributor.SERVER.noArg());
if (button.getID() >= 0 && button.getID() < 9) {
Minecraft.getInstance().player.getInventory().selected = button.getID();
}
setState(MenuState.WAITING);
break;
case DO_USE_ITEM:
TurnBasedMinecraftMod.getHandler().send(
new PacketBattleDecision(TurnBasedMinecraftMod.proxy.getLocalBattle().getId(), Battle.Decision.USE_ITEM, button.getID()),
PacketDistributor.SERVER.noArg()); PacketDistributor.SERVER.noArg());
setState(MenuState.WAITING); setState(MenuState.WAITING);
} else { break;
default:
setState(MenuState.MAIN_MENU); setState(MenuState.MAIN_MENU);
} break;
break;
} }
} }
@ -351,6 +360,11 @@ public class BattleGui extends Screen {
return false; // TODO verify return value return false; // TODO verify return value
} }
@Override
public void renderBackground(GuiGraphics p_283688_, int p_299421_, int p_298679_, float p_297268_) {
// Left blank to not render background.
}
@Override @Override
public boolean keyReleased(int a, int b, int c) { public boolean keyReleased(int a, int b, int c) {
if (getMinecraft().player.isCreative()) { if (getMinecraft().player.isCreative()) {

View file

@ -1,34 +1,49 @@
package com.burnedkirby.TurnBasedMinecraft.client; package com.burnedkirby.TurnBasedMinecraft.client;
import com.burnedkirby.TurnBasedMinecraft.common.CommonProxy;
import com.burnedkirby.TurnBasedMinecraft.common.TurnBasedMinecraftMod; import com.burnedkirby.TurnBasedMinecraft.common.TurnBasedMinecraftMod;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractButton; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.Renderable;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarratedElementType;
import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.LivingEntity;
public class EntitySelectionButton extends AbstractButton { public class EntitySelectionButton implements Renderable, GuiEventListener, NarratableEntry {
TBMButtonPress onPress; private int x;
private int y;
private int width;
private int height;
private boolean focused;
private Button nestedButton;
TBMEntityButtonPress onPress;
private int entityID; private int entityID;
private boolean isSideA; private boolean isSideA;
public EntitySelectionButton(int x, int y, int widthIn, int heightIn, String buttonText, int entityID, boolean isSideA, TBMButtonPress onPress) { public EntitySelectionButton(int x, int y, int widthIn, int heightIn, String buttonText, int entityID, boolean isSideA, TBMEntityButtonPress onPress) {
super(x, y, widthIn, heightIn, Component.literal(buttonText)); this.x = x;
this.y = y;
this.width = widthIn;
this.height = heightIn;
this.onPress = onPress; this.onPress = onPress;
this.entityID = entityID; this.entityID = entityID;
this.isSideA = isSideA; this.isSideA = isSideA;
this.nestedButton = Button.builder(Component.literal(buttonText), (unused) -> {}).pos(x, y).size(widthIn, heightIn).build();
} }
public EntitySelectionButton(int x, int y, int widthIn, int heightIn, Component buttonTextComponent, int entityID, boolean isSideA, TBMButtonPress onPress) { public EntitySelectionButton(int x, int y, int widthIn, int heightIn, Component buttonTextComponent, int entityID, boolean isSideA, TBMEntityButtonPress onPress) {
super(x, y, widthIn, heightIn, buttonTextComponent); this.x = x;
this.y = y;
this.width = widthIn;
this.height = heightIn;
this.onPress = onPress; this.onPress = onPress;
this.entityID = entityID; this.entityID = entityID;
this.isSideA = isSideA; this.isSideA = isSideA;
this.nestedButton = Button.builder(buttonTextComponent, (unused) -> {}).pos(x, y).size(widthIn, heightIn).build();
} }
public int getID() { public int getID() {
@ -41,63 +56,86 @@ public class EntitySelectionButton extends AbstractButton {
@Override @Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) { public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float partialTicks) {
super.render(guiGraphics, mouseX, mouseY, partialTicks); this.nestedButton.render(guiGraphics, mouseX, mouseY, partialTicks);
Entity e = Minecraft.getInstance().level.getEntity(entityID); Entity e = Minecraft.getInstance().level.getEntity(entityID);
if (e != null && e instanceof LivingEntity && ((LivingEntity) e).isAlive()) { if (e != null && e instanceof LivingEntity && ((LivingEntity) e).isAlive()) {
int health = (int) (((LivingEntity) e).getHealth() + 0.5f); int health = (int) (((LivingEntity) e).getHealth() + 0.5f);
int xpos = getX(); int xpos = this.x;
int xoffset; int xoffset;
if (isSideA) { if (isSideA) {
xpos += getWidth() + 4; xpos += this.width + 4;
xoffset = 4; xoffset = 4;
} else { } else {
xpos -= 6; xpos -= 6;
xoffset = -4; xoffset = -4;
} }
if (health > 200) { if (health > 200) {
guiGraphics.fill(xpos, getY() + getHeight() * 4 / 5, xpos + 2, getY() + getHeight(), 0xFFFF0000); guiGraphics.fill(xpos, this.y + this.height * 4 / 5, xpos + 2, this.y + this.height, 0xFFFF0000);
guiGraphics.fill(xpos, getY() + getHeight() * 3 / 5, xpos + 2, getY() + getHeight() * 4 / 5, 0xFFFFFF00); guiGraphics.fill(xpos, this.y + this.height * 3 / 5, xpos + 2, this.y + this.height * 4 / 5, 0xFFFFFF00);
guiGraphics.fill(xpos, getY() + getHeight() * 2 / 5, xpos + 2, getY() + getHeight() * 3 / 5, 0xFF00FF00); guiGraphics.fill(xpos, this.y + this.height * 2 / 5, xpos + 2, this.y + this.height * 3 / 5, 0xFF00FF00);
guiGraphics.fill(xpos, getY() + getHeight() / 5, xpos + 2, getY() + getHeight() * 2 / 5, 0xFF00FFFF); guiGraphics.fill(xpos, this.y + this.height / 5, xpos + 2, this.y + this.height * 2 / 5, 0xFF00FFFF);
guiGraphics.fill(xpos, getY(), xpos + 2, getY() + getHeight() / 5, 0xFF0000FF); guiGraphics.fill(xpos, this.y, xpos + 2, this.y + this.height / 5, 0xFF0000FF);
int healthHeight = ((health - 200) * getHeight() / 100); int healthHeight = ((health - 200) * this.height / 100);
guiGraphics.fill(xpos + xoffset, getY() + getHeight() - healthHeight, xpos + xoffset + 2, getY() + getHeight(), 0xFFFFFFFF); guiGraphics.fill(xpos + xoffset, this.y + this.height - healthHeight, xpos + xoffset + 2, this.y + this.height, 0xFFFFFFFF);
} else if (health > 100) { } else if (health > 100) {
guiGraphics.fill(xpos, getY() + getHeight() * 4 / 5, xpos + 2, getY() + getHeight(), 0xFFFF0000); guiGraphics.fill(xpos, this.y + this.height * 4 / 5, xpos + 2, this.y + this.height, 0xFFFF0000);
guiGraphics.fill(xpos, getY() + getHeight() * 3 / 5, xpos + 2, getY() + getHeight() * 4 / 5, 0xFFFFFF00); guiGraphics.fill(xpos, this.y + this.height * 3 / 5, xpos + 2, this.y + this.height * 4 / 5, 0xFFFFFF00);
guiGraphics.fill(xpos, getY() + getHeight() * 2 / 5, xpos + 2, getY() + getHeight() * 3 / 5, 0xFF00FF00); guiGraphics.fill(xpos, this.y + this.height * 2 / 5, xpos + 2, this.y + this.height * 3 / 5, 0xFF00FF00);
guiGraphics.fill(xpos, getY() + getHeight() / 5, xpos + 2, getY() + getHeight() * 2 / 5, 0xFF00FFFF); guiGraphics.fill(xpos, this.y + this.height / 5, xpos + 2, this.y + this.height * 2 / 5, 0xFF00FFFF);
int healthHeight = ((health - 100) * getHeight() / 100); int healthHeight = ((health - 100) * this.height / 100);
guiGraphics.fill(xpos + xoffset, getY() + getHeight() - healthHeight, xpos + xoffset + 2, getY() + getHeight(), 0xFF0000FF); guiGraphics.fill(xpos + xoffset, this.y + this.height - healthHeight, xpos + xoffset + 2, this.y + this.height, 0xFF0000FF);
} else if (health > 50) { } else if (health > 50) {
guiGraphics.fill(xpos, getY() + getHeight() * 4 / 5, xpos + 2, getY() + getHeight(), 0xFFFF0000); guiGraphics.fill(xpos, this.y + this.height * 4 / 5, xpos + 2, this.y + this.height, 0xFFFF0000);
guiGraphics.fill(xpos, getY() + getHeight() * 3 / 5, xpos + 2, getY() + getHeight() * 4 / 5, 0xFFFFFF00); guiGraphics.fill(xpos, this.y + this.height * 3 / 5, xpos + 2, this.y + this.height * 4 / 5, 0xFFFFFF00);
guiGraphics.fill(xpos, getY() + getHeight() * 2 / 5, xpos + 2, getY() + getHeight() * 3 / 5, 0xFF00FF00); guiGraphics.fill(xpos, this.y + this.height * 2 / 5, xpos + 2, this.y + this.height * 3 / 5, 0xFF00FF00);
int healthHeight = ((health - 50) * getHeight() / 50); int healthHeight = ((health - 50) * this.height / 50);
guiGraphics.fill(xpos + xoffset, getY() + getHeight() - healthHeight, xpos + xoffset + 2, getY() + getHeight(), 0xFF00FFFF); guiGraphics.fill(xpos + xoffset, this.y + this.height - healthHeight, xpos + xoffset + 2, this.y + this.height, 0xFF00FFFF);
} else if (health > 20) { } else if (health > 20) {
guiGraphics.fill(xpos, getY() + getHeight() * 4 / 5, xpos + 2, getY() + getHeight(), 0xFFFF0000); guiGraphics.fill(xpos, this.y + this.height * 4 / 5, xpos + 2, this.y + this.height, 0xFFFF0000);
guiGraphics.fill(xpos, getY() + getHeight() * 3 / 5, xpos + 2, getY() + getHeight() * 4 / 5, 0xFFFFFF00); guiGraphics.fill(xpos, this.y + this.height * 3 / 5, xpos + 2, this.y + this.height * 4 / 5, 0xFFFFFF00);
int healthHeight = ((health - 20) * getHeight() / 30); int healthHeight = ((health - 20) * this.height / 30);
guiGraphics.fill(xpos + xoffset, getY() + getHeight() - healthHeight, xpos + xoffset + 2, getY() + getHeight(), 0xFF00FF00); guiGraphics.fill(xpos + xoffset, this.y + this.height - healthHeight, xpos + xoffset + 2, this.y + this.height, 0xFF00FF00);
} else if (health > 10) { } else if (health > 10) {
guiGraphics.fill(xpos, getY() + getHeight() * 4 / 5, xpos + 2, getY() + getHeight(), 0xFFFF0000); guiGraphics.fill(xpos, this.y + this.height * 4 / 5, xpos + 2, this.y + this.height, 0xFFFF0000);
int healthHeight = ((health - 10) * getHeight() / 10); int healthHeight = ((health - 10) * this.height / 10);
guiGraphics.fill(xpos + xoffset, getY() + getHeight() - healthHeight, xpos + xoffset + 2, getY() + getHeight(), 0xFFFFFF00); guiGraphics.fill(xpos + xoffset, this.y + this.height - healthHeight, xpos + xoffset + 2, this.y + this.height, 0xFFFFFF00);
} else { } else {
int healthHeight = (health * getHeight() / 10); int healthHeight = (health * this.height / 10);
guiGraphics.fill(xpos + xoffset, getY() + getHeight() - healthHeight, xpos + xoffset + 2, getY() + getHeight(), 0xFFFF0000); guiGraphics.fill(xpos + xoffset, this.y + this.height - healthHeight, xpos + xoffset + 2, this.y + this.height, 0xFFFF0000);
} }
} }
} }
@Override
protected void updateWidgetNarration(NarrationElementOutput p_259858_) {
p_259858_.add(NarratedElementType.HINT, TurnBasedMinecraftMod.proxy.getEntity(entityID, Minecraft.getInstance().level.dimension()).getName());
}
@Override
public void onPress() { public void onPress() {
onPress.onPress(this); onPress.onPress(this);
} }
@Override
public void setFocused(boolean b) {
this.focused = b;
}
@Override
public boolean isFocused() {
return focused;
}
@Override
public NarrationPriority narrationPriority() {
return NarrationPriority.FOCUSED;
}
@Override
public void updateNarration(NarrationElementOutput narrationElementOutput) {
narrationElementOutput.add(NarratedElementType.HINT, TurnBasedMinecraftMod.proxy.getEntity(entityID, Minecraft.getInstance().level.dimension()).getName());
}
@Override
public boolean mouseClicked(double x, double y, int unknown) {
if (unknown == 0 && x >= this.x && y >= this.y && x <= (double)(this.x + this.width) && y <= (double)(this.y + this.height)) {
onPress();
return true;
}
return false;
}
} }

View file

@ -1,19 +1,26 @@
package com.burnedkirby.TurnBasedMinecraft.client; package com.burnedkirby.TurnBasedMinecraft.client;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.client.gui.GuiGraphics; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.AbstractButton; import net.minecraft.client.gui.components.Renderable;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.client.gui.narration.NarratedElementType; import net.minecraft.client.gui.narration.NarratedElementType;
import net.minecraft.client.gui.narration.NarrationElementOutput; import net.minecraft.client.gui.narration.NarrationElementOutput;
import net.minecraft.network.chat.Component;
public class ItemSelectionButton extends AbstractButton { public class ItemSelectionButton implements Renderable, GuiEventListener, NarratableEntry {
private int x;
TBMButtonPress onPress; private int y;
private int width;
private int height;
TBMItemButtonPress onPress;
private int itemStackID; private int itemStackID;
private boolean focused;
public ItemSelectionButton(int x, int y, int widthIn, int heightIn, String buttonText, int itemStackID, TBMButtonPress onPress) { public ItemSelectionButton(int x, int y, int widthIn, int heightIn, int itemStackID, TBMItemButtonPress onPress) {
super(x, y, widthIn, heightIn, Component.literal(buttonText)); this.x = x;
this.y = y;
this.width = widthIn;
this.height = heightIn;
this.onPress = onPress; this.onPress = onPress;
this.itemStackID = itemStackID; this.itemStackID = itemStackID;
} }
@ -24,23 +31,44 @@ public class ItemSelectionButton extends AbstractButton {
@Override @Override
public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float unk) { public void render(GuiGraphics guiGraphics, int mouseX, int mouseY, float unk) {
if (visible) { boolean hovered = mouseX >= this.x && mouseY >= this.y && mouseX < this.x + this.width && mouseY < this.y + this.height;
boolean hovered = mouseX >= getX() && mouseY >= getY() && mouseX < getX() + getWidth() && mouseY < getY() + getHeight(); if (hovered) {
if (hovered) { guiGraphics.fill(this.x, this.y, this.x + this.width, this.y + this.height, 0x80FFFFFF);
guiGraphics.fill(getX(), getY(), getX() + getWidth(), getY() + getHeight(), 0x80FFFFFF); } else {
} else { guiGraphics.fill(this.x, this.y, this.x + this.width, this.y + this.height, 0x20707070);
guiGraphics.fill(getX(), getY(), getX() + getWidth(), getY() + getHeight(), 0x20707070);
}
} }
} }
@Override
protected void updateWidgetNarration(NarrationElementOutput p_259858_) {
p_259858_.add(NarratedElementType.HINT, "Item " + this.itemStackID);
}
@Override
public void onPress() { public void onPress() {
onPress.onPress(this); onPress.onPress(this);
} }
}
@Override
public void setFocused(boolean b) {
focused = b;
}
@Override
public boolean isFocused() {
return focused;
}
@Override
public NarrationPriority narrationPriority() {
return NarrationPriority.FOCUSED;
}
@Override
public void updateNarration(NarrationElementOutput narrationElementOutput) {
narrationElementOutput.add(NarratedElementType.HINT, "Item " + this.itemStackID);
}
@Override
public boolean mouseClicked(double x, double y, int unknown) {
if (unknown == 0 && x >= this.x && y >= this.y && x <= (double)(this.x + this.width) && y <= (double)(this.y + this.height)) {
onPress();
return true;
}
return false;
}
}

View file

@ -0,0 +1,5 @@
package com.burnedkirby.TurnBasedMinecraft.client;
public interface TBMEntityButtonPress {
void onPress(EntitySelectionButton button);
}

View file

@ -0,0 +1,5 @@
package com.burnedkirby.TurnBasedMinecraft.client;
public interface TBMItemButtonPress {
void onPress(ItemSelectionButton button);
}

View file

@ -37,7 +37,7 @@ import org.apache.logging.log4j.Logger;
public class TurnBasedMinecraftMod { public class TurnBasedMinecraftMod {
public static final String MODID = "com_burnedkirby_turnbasedminecraft"; public static final String MODID = "com_burnedkirby_turnbasedminecraft";
public static final String NAME = "Turn Based Minecraft Mod"; public static final String NAME = "Turn Based Minecraft Mod";
public static final String VERSION = "1.25.0"; public static final String VERSION = "1.25.1";
public static final String CONFIG_FILENAME = "TBM_Config.toml"; public static final String CONFIG_FILENAME = "TBM_Config.toml";
public static final String DEFAULT_CONFIG_FILENAME = "TBM_Config_DEFAULT.toml"; public static final String DEFAULT_CONFIG_FILENAME = "TBM_Config_DEFAULT.toml";
public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/"; public static final String CONFIG_DIRECTORY = "config/TurnBasedMinecraft/";
@ -78,7 +78,7 @@ public class TurnBasedMinecraftMod {
} }
private void firstInit(final FMLCommonSetupEvent event) { private void firstInit(final FMLCommonSetupEvent event) {
proxy = DistExecutor.safeRunForDist(() -> ClientProxy::new, () -> CommonProxy::new); proxy = DistExecutor.unsafeRunForDist(() -> () -> new ClientProxy(), () -> () -> new CommonProxy());
proxy.setLogger(logger); proxy.setLogger(logger);
proxy.initialize(); proxy.initialize();

View file

@ -33,7 +33,7 @@ description='''
Implements turn-based-battle in Minecraft. Implements turn-based-battle in Minecraft.
''' '''
logoFile="/assets/com_burnedkirby_turnbasedminecraft/tbmm_icon.png" logoFile="assets/com_burnedkirby_turnbasedminecraft/tbmm_icon.png"
# A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional. # A dependency - use the . to indicate dependency for a specific modid. Dependencies are optional.
[[dependencies.com_burnedkirby_turnbasedminecraft]] #optional [[dependencies.com_burnedkirby_turnbasedminecraft]] #optional