Compare commits

...

10 commits

11 changed files with 113 additions and 44 deletions

View file

@ -1,4 +1,4 @@
Copyright (c) <year> <owner>. All rights reserved. Copyright (c) 2021 vodofrede. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

View file

@ -1,3 +1,9 @@
# ImmersiveXP # ImmersiveXP
A mod for Minecraft (Fabric) that allows players to get experience from various sources other than fighting mobs or mining. A mod for Minecraft (Fabric) that allows players to get experience from various sources other than fighting mobs or mining.
Currently, this mods adds a small amount of experience for doing the following actions:
- Chopping a log from a naturally-grown tree
- Harvesting crops
- Harvesting melons
- Harvesting berries from sweet berry bushes

View file

@ -11,24 +11,13 @@ version = project.mod_version
group = project.maven_group group = project.maven_group
repositories { repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
// Loom adds the essential maven repositories to download Minecraft and libraries from automatically.
// See https://docs.gradle.org/current/userguide/declaring_repositories.html
// for more information about repositories.
} }
dependencies { dependencies {
// To change the versions see the gradle.properties file
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.yarn_mappings}:v2"
modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" modImplementation "net.fabricmc:fabric-loader:${project.loader_version}"
// Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}" modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_version}"
// PSA: Some older mods, compiled on Loom 0.2.1, might have outdated Maven POMs.
// You may need to force-disable transitiveness on them.
} }
processResources { processResources {

View file

@ -2,14 +2,13 @@
org.gradle.jvmargs=-Xmx1G org.gradle.jvmargs=-Xmx1G
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/versions.html
minecraft_version=1.17.1 minecraft_version=1.17.1
yarn_mappings=1.17.1+build.39 yarn_mappings=1.17.1+build.39
loader_version=0.11.6 loader_version=0.11.6
# Mod Properties # Mod Properties
mod_version = 1.0.0 mod_version = 1.0.3
maven_group = eu.vodofrede maven_group = dk.palmoe
archives_base_name = immersivexp archives_base_name = immersivexp
# Dependencies # Dependencies

View file

@ -0,0 +1,63 @@
package dk.palmoe.immersivexp;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.Reader;
import com.google.gson.Gson;
import com.google.gson.stream.JsonWriter;
import org.apache.commons.io.IOUtils;;
public class Config {
public int logBaseXP = 0;
public int logRandXP = 2;
public int cropBaseXP = 0;
public int cropRandXP = 2;
public int berriesBaseXP = 0;
public int berriesRandXP = 2;
public static final File FILE = new File("config/immersivexp.json");
public static Config INSTANCE = null;
public static Config getInstance() {
if (INSTANCE == null) {
INSTANCE = new Config().read();
}
return INSTANCE;
}
private Config read() {
if (!FILE.exists())
return new Config().write();
Reader reader = null;
try {
return new Gson().fromJson(reader = new FileReader(FILE), Config.class);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(reader);
}
}
private Config write() {
Gson gson = new Gson();
JsonWriter writer = null;
try {
writer = gson.newJsonWriter(new FileWriter(FILE));
writer.setIndent(" ");
gson.toJson(gson.toJsonTree(this, Config.class), writer);
} catch (Exception e) {
ImmersiveXP.LOGGER.error("Couldn't save config");
e.printStackTrace();
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(writer);
}
return this;
}
}

View file

@ -1,4 +1,4 @@
package eu.vodofrede.immersivexp; package dk.palmoe.immersivexp;
import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents; import net.fabricmc.fabric.api.event.player.PlayerBlockBreakEvents;
import net.fabricmc.fabric.api.event.player.UseBlockCallback; import net.fabricmc.fabric.api.event.player.UseBlockCallback;
@ -15,10 +15,18 @@ import net.minecraft.util.registry.Registry;
public class Events { public class Events {
public static void init() { public static void init() {
PlayerBlockBreakEvents.AFTER.register((world, player, pos, state, entity) -> { PlayerBlockBreakEvents.AFTER.register((world, player, pos, state, entity) -> {
// TODO: Make experience amount configurable
if (world instanceof ServerWorld) { if (world instanceof ServerWorld) {
if (state.getBlock() instanceof CropBlock || state.getBlock() instanceof MelonBlock) { if (state.getBlock() instanceof CropBlock) {
Util.spawnExp((ServerWorld) world, pos, 1, 1); int age = state.get(CropBlock.AGE);
if (age == 7) {
Config config = Config.getInstance();
Util.spawnXp((ServerWorld) world, pos, config.cropBaseXP, config.cropRandXP);
}
}
if (state.getBlock() instanceof MelonBlock) {
Config config = Config.getInstance();
Util.spawnXp((ServerWorld) world, pos, config.cropBaseXP, config.cropRandXP);
} }
if (state.isIn(BlockTags.LOGS)) { if (state.isIn(BlockTags.LOGS)) {
@ -26,18 +34,25 @@ public class Events {
boolean isGrown = Util.isTreeNaturallyGrown(world, pos); boolean isGrown = Util.isTreeNaturallyGrown(world, pos);
if (holdingAxe && isGrown) { if (holdingAxe && isGrown) {
Util.spawnExp((ServerWorld) world, pos, 1, 4); Config config = Config.getInstance();
Util.spawnXp((ServerWorld) world, pos, config.logBaseXP, config.logRandXP);
} }
} }
} }
}); });
UseBlockCallback.EVENT.register(((player, world, hand, hitResult) -> { UseBlockCallback.EVENT.register(((player, world, hand, hitResult) -> {
// TODO: Make experience amount configurable
BlockState state = world.getBlockState(hitResult.getBlockPos()); BlockState state = world.getBlockState(hitResult.getBlockPos());
if (state.getBlock() instanceof SweetBerryBushBlock && world instanceof ServerWorld) { if (state.getBlock() instanceof SweetBerryBushBlock && world instanceof ServerWorld) {
Util.spawnExp((ServerWorld) world, hitResult.getBlockPos(), 1, 1); int age = state.get(SweetBerryBushBlock.AGE);
if (age == 3) {
ImmersiveXP.LOGGER.info("Giving xp for sweet berry bush");
Config config = Config.getInstance();
Util.spawnXp((ServerWorld) world, hitResult.getBlockPos(), config.berriesBaseXP,
config.berriesRandXP);
}
} }
return ActionResult.PASS; return ActionResult.PASS;

View file

@ -1,4 +1,4 @@
package eu.vodofrede.immersivexp; package dk.palmoe.immersivexp;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;

View file

@ -1,7 +1,6 @@
package eu.vodofrede.immersivexp; package dk.palmoe.immersivexp;
import java.util.LinkedList; import java.util.LinkedList;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.LeavesBlock; import net.minecraft.block.LeavesBlock;
import net.minecraft.entity.ExperienceOrbEntity; import net.minecraft.entity.ExperienceOrbEntity;
@ -12,11 +11,14 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
public class Util { public class Util {
public static final int MAX_SEARCH_DEPTH = 100;
public static boolean isTreeNaturallyGrown(World world, BlockPos pos) { public static boolean isTreeNaturallyGrown(World world, BlockPos pos) {
LinkedList<BlockPos> queue = new LinkedList<BlockPos>(); LinkedList<BlockPos> queue = new LinkedList<BlockPos>();
queue.push(pos.up()); queue.push(pos.up());
int search_depth = 0;
while (!queue.isEmpty()) { while (!queue.isEmpty() && (search_depth <= MAX_SEARCH_DEPTH)) {
BlockPos nextPos = queue.pop(); BlockPos nextPos = queue.pop();
BlockPos[] dirs = { nextPos.north(), nextPos.east(), nextPos.south(), nextPos.west(), nextPos.up() }; BlockPos[] dirs = { nextPos.north(), nextPos.east(), nextPos.south(), nextPos.west(), nextPos.up() };
@ -30,13 +32,15 @@ public class Util {
queue.push(dir); queue.push(dir);
} }
} }
search_depth++;
} }
return false; return false;
} }
public static void spawnExp(ServerWorld world, BlockPos pos, int min, int cap) { public static void spawnXp(ServerWorld world, BlockPos pos, int min, int cap) {
Vec3d exp_pos = new Vec3d(pos.getX(), pos.getY(), pos.getZ()); Vec3d xp_pos = new Vec3d(pos.getX(), pos.getY(), pos.getZ());
ExperienceOrbEntity.spawn(world, exp_pos, min + world.random.nextInt(cap)); ExperienceOrbEntity.spawn(world, xp_pos, min + world.random.nextInt(cap));
} }
} }

View file

@ -1,10 +0,0 @@
package eu.vodofrede.immersivexp.mixin;
import org.spongepowered.asm.mixin.Mixin;
import net.minecraft.client.gui.screen.TitleScreen;
@Mixin(TitleScreen.class)
public class ImmersiveXPMixin {
}

View file

@ -16,9 +16,9 @@
"environment": "*", "environment": "*",
"entrypoints": { "entrypoints": {
"main": ["eu.vodofrede.immersivexp.ImmersiveXP"] "main": ["dk.palmoe.immersivexp.ImmersiveXP"]
}, },
"mixins": ["immersivexp.mixins.json"], "mixins": [],
"depends": { "depends": {
"fabricloader": ">=0.11.3", "fabricloader": ">=0.11.3",
@ -28,5 +28,8 @@
}, },
"suggests": { "suggests": {
"another-mod": "*" "another-mod": "*"
},
"custom": {
"modmenu": {}
} }
} }

View file

@ -1,10 +1,10 @@
{ {
"required": true, "required": true,
"minVersion": "0.8", "minVersion": "0.8",
"package": "eu.vodofrede.immersivexp.mixin", "package": "dk.palmoe.immersivexp.mixin",
"compatibilityLevel": "JAVA_16", "compatibilityLevel": "JAVA_16",
"mixins": ["ImmersiveXPMixin"], "mixins": [],
"client": ["ImmersiveXPMixin"], "client": [],
"injectors": { "injectors": {
"defaultRequire": 1 "defaultRequire": 1
} }