Skip to content

Commit

Permalink
Use Crossroad to make a 'core-plus-minecraft' subproject; deduplicate…
Browse files Browse the repository at this point in the history
… tons and tons of code into it
  • Loading branch information
quat1024 committed Jun 2, 2023
1 parent b41943d commit 6814a4c
Show file tree
Hide file tree
Showing 95 changed files with 1,014 additions and 4,786 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ For documentation, view the `docs/2.x/` folder.
Versions prior to 2.5 were developed separately, one codebase per version. Maintaining that was difficult, so everything is now in a giant Gradle subproject. This is also unwieldy but in a different way - if you're having trouble fitting the damn thing into RAM, comment out a few subprojects from `settings.gradle`.

* `core` - Truly version-independent code, only depends on a (slightly old version of) google gson. Lowest-common-denominator code.
* `core-plus-minecraft-1.16-thru-1.19.4` - Code that depend on only the common subset of Minecraft 1.16.5, 1.18.2, 1.19.2, and 1.19.4 (using the [crossroad](https://github.com/CrackedPolishedBlackstoneBricksMC/crossroad) jar intersection tool).
* `common-xxx` - Allows accessing Minecraft (through [minivan](https://github.com/CrackedPolishedBlackstoneBricksMC/minivan), formerly [VanillaGradle](https://github.com/SpongePowered/VanillaGradle)) and writing the code of mixins. Contains glue between the version-independent core and the Minecraft version in question.
* Technically `core-plus-minecraft` can also write mixins, but IDE support is weak; my intersection tool currently doesn't emit method bodies
* `fabric-xxx` and `forge-xxx` - Can refer to Minecraft as well as features from the specific modloader. This is generally just a tiny bit of glue code, initialization using modloader services, platform-specific mixins, blah blah.

Each layer includes the code of the previous, both as a Gradle dependency and textually (the sources are compiled together). The stuff in the core is compiled many times over. It's not great.
Expand Down
3 changes: 3 additions & 0 deletions common-1.16.5/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ buildscript {
}

evaluationDependsOn(":core") // fuck gradle episode 151905105
evaluationDependsOn(":core-plus-minecraft-1.16-thru-1.19.4") // fuck gradle episode 151905105

apply plugin: "java"
apply plugin: "agency.highlysuspect.minivan"
Expand Down Expand Up @@ -40,10 +41,12 @@ dependencies {
compileOnly "org.jetbrains:annotations:24.0.1"

implementation project(":core")
implementation project(":core-plus-minecraft-1.16-thru-1.19.4")
}

processResources {
from project(":core").sourceSets.main.resources
from project(":core-plus-minecraft-1.16-thru-1.19.4").sourceSets.main.resources
}

tasks.withType(GenerateModuleMetadata) {
Expand Down
213 changes: 59 additions & 154 deletions common-1.16.5/src/main/java/agency/highlysuspect/apathy/Apathy116.java
Original file line number Diff line number Diff line change
@@ -1,56 +1,36 @@
package agency.highlysuspect.apathy;

import agency.highlysuspect.apathy.core.Apathy;
import agency.highlysuspect.apathy.core.CoreGenOptions;
import agency.highlysuspect.apathy.core.CoreMobOptions;
import agency.highlysuspect.apathy.core.JsonRule;
import agency.highlysuspect.apathy.core.TriState;
import agency.highlysuspect.apathy.core.config.ConfigSchema;
import agency.highlysuspect.apathy.core.rule.PartialSpecAttackerIs;
import agency.highlysuspect.apathy.core.rule.PartialSpecAttackerIsBoss;
import agency.highlysuspect.apathy.core.rule.PartialSpecAttackerTaggedWith;
import agency.highlysuspect.apathy.core.rule.PartialSpecDifficultyIs;
import agency.highlysuspect.apathy.core.rule.PartialSpecRevengeTimer;
import agency.highlysuspect.apathy.core.rule.PartialSpecSpawnType;
import agency.highlysuspect.apathy.core.rule.Rule;
import agency.highlysuspect.apathy.core.rule.RuleSpecAlways;
import agency.highlysuspect.apathy.core.rule.RuleSpecChain;
import agency.highlysuspect.apathy.core.rule.RuleSpecJson;
import agency.highlysuspect.apathy.core.rule.RuleSpecPredicated;
import agency.highlysuspect.apathy.core.rule.Spec;
import agency.highlysuspect.apathy.core.wrapper.Attacker;
import agency.highlysuspect.apathy.core.wrapper.AttackerTag;
import agency.highlysuspect.apathy.core.wrapper.AttackerType;
import agency.highlysuspect.apathy.core.wrapper.Defender;
import agency.highlysuspect.apathy.core.wrapper.DragonDuck;
import agency.highlysuspect.apathy.rule.PartialSpecDefenderHasAdvancement;
import agency.highlysuspect.apathy.rule.PartialSpecDefenderInPlayerSet;
import agency.highlysuspect.apathy.rule.PartialSpecEffect;
import agency.highlysuspect.apathy.rule.PartialSpecLocation;
import agency.highlysuspect.apathy.rule.PartialSpecScore;
import agency.highlysuspect.apathy.rule.PartialSpecScoreboardTeam;
import agency.highlysuspect.apathy.coreplusminecraft.ApathyPlusMinecraft;
import agency.highlysuspect.apathy.coreplusminecraft.PlayerSetManagerGuts;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Registry;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.ComponentUtils;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.MinecraftServer;
import net.minecraft.tags.Tag;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.effect.MobEffect;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.level.Explosion;
import net.minecraft.world.level.Level;
import org.apache.logging.log4j.LogManager;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Locale;
import java.util.Collection;
import java.util.function.Function;

public abstract class Apathy116 extends Apathy {
public abstract class Apathy116 extends ApathyPlusMinecraft {
public static Apathy116 instance116;

public Apathy116() {
super(VerConv.toLogFacade(LogManager.getLogger(MODID)));

if(instance116 == null) {
instance116 = this;
} else {
Expand All @@ -61,95 +41,54 @@ public Apathy116() {
}

@Override
public Rule bakeMobsConfigRule() {
Spec<Rule, ?> ruleSpec;

if(mobCfg.get(CoreMobOptions.nuclearOption)) {
Apathy.instance.log.info("Nuclear option enabled - Ignoring ALL rules in the config file");
ruleSpec = RuleSpecAlways.ALWAYS_DENY;
} else {
ArrayList<Spec<Rule, ?>> ruleSpecList = new ArrayList<>();
for(String ruleName : mobCfg.get(CoreMobOptions.ruleOrder)) {
switch(ruleName.trim().toLowerCase(Locale.ROOT)) {
case "json":
ruleSpecList.add(new RuleSpecJson());
break;
case "difficulty":
ruleSpecList.add(new RuleSpecPredicated(
mobCfg.get(CoreMobOptions.difficultySetIncluded),
mobCfg.get(CoreMobOptions.difficultySetExcluded),
new PartialSpecDifficultyIs(mobCfg.get(CoreMobOptions.difficultySet))
));
break;
case "boss":
ruleSpecList.add(new RuleSpecPredicated(
mobCfg.get(CoreMobOptions.boss),
TriState.DEFAULT,
PartialSpecAttackerIsBoss.INSTANCE
));
break;
case "mobset":
ruleSpecList.add(new RuleSpecPredicated(
mobCfg.get(CoreMobOptions.mobSetIncluded),
mobCfg.get(CoreMobOptions.mobSetExcluded),
new PartialSpecAttackerIs(mobCfg.get(CoreMobOptions.mobSet))
));
break;
case "tagset":
ruleSpecList.add(new RuleSpecPredicated(
mobCfg.get(CoreMobOptions.tagSetIncluded),
mobCfg.get(CoreMobOptions.tagSetExcluded),
new PartialSpecAttackerTaggedWith(mobCfg.get(CoreMobOptions.tagSet))
));
break;
case "playerset":
mobCfg.get(CoreMobOptions.playerSetName).ifPresent(s ->
ruleSpecList.add(new RuleSpecPredicated(
mobCfg.get(CoreMobOptions.playerSetIncluded),
mobCfg.get(CoreMobOptions.playerSetExcluded),
new PartialSpecDefenderInPlayerSet(Collections.singleton(s))
)));
break;
case "potionset":
ruleSpecList.add(new RuleSpecPredicated(
mobCfg.get(VerMobOptions.mobEffectSetIncluded),
mobCfg.get(VerMobOptions.mobEffectSetExcluded),
new PartialSpecEffect(mobCfg.get(VerMobOptions.mobEffectSet), mobCfg.get(VerMobOptions.mobEffectWho))
));
break;
case "spawntype":
ruleSpecList.add(new RuleSpecPredicated(
mobCfg.get(CoreMobOptions.spawnTypeIncluded),
mobCfg.get(CoreMobOptions.spawnTypeExcluded),
new PartialSpecSpawnType(mobCfg.get(CoreMobOptions.spawnTypeSet))
));
break;
case "revenge":
ruleSpecList.add(new RuleSpecPredicated(
TriState.TRUE, TriState.DEFAULT,
new PartialSpecRevengeTimer(mobCfg.get(CoreMobOptions.revengeTimer))
));
break;
default:
Apathy.instance.log.warn("Unknown rule " + ruleName + " listed in the ruleOrder config option.");
}
}

ruleSpec = new RuleSpecChain(ruleSpecList);
}

if(generalCfg.get(CoreGenOptions.debugBuiltinRule)) JsonRule.dump(ruleSpec, "builtin-rule");
if(generalCfg.get(CoreGenOptions.runRuleOptimizer)) {
ruleSpec = ruleSpec.optimize();
if(generalCfg.get(CoreGenOptions.debugBuiltinRule)) JsonRule.dump(ruleSpec, "builtin-rule-opt");
}

return ruleSpec.build();
public Registry<MobEffect> mobEffectRegistry() {
return Registry.MOB_EFFECT;
}

@Override
public Registry<EntityType<?>> entityTypeRegistry() {
return Registry.ENTITY_TYPE;
}

@Override
public BlockPos blockPosContaining(double x, double y, double z) {
return new BlockPos(x, y, z);
}

@Override
public Component literal(String lit) {
return new TextComponent(lit);
}

@Override
public String stringifyComponent(Component comp) {
return comp.getContents();
}

@Override
public <T> Component formatList(Collection<T> things, Function<T, Component> toComponent) {
//Tricky:
//in Minecraft 1.16 this method takes a Collection<T>, but in 1.18 it takes a Collection<? extends T>.
//Even though this call-site textually looks the same, it's not really the same method; it doesn't exist in the hybrid jar.
return ComponentUtils.formatList(things, toComponent);
}

@Override
public PlayerSetManagerGuts getFor(MinecraftServer server) {
return server.overworld().getDataStorage().computeIfAbsent(
PlayerSetManager::new,
"apathy-player-sets"
).guts;
}

@SuppressWarnings("BooleanMethodIsAlwaysInverted") //But it makes more sense that way!
public boolean allowedToTargetPlayer(Mob attacker, ServerPlayer player) {
return allowedToTargetPlayer((Attacker) attacker, (Defender) player);
@Override
public DamageSource comicalAnvilSound(Entity rarrr) {
return DamageSource.ANVIL;
}

@Override
public void explodeNoBlockInteraction(Level level, Entity who, double x, double y, double z, float strength) {
level.explode(who, x, y, z, strength, Explosion.BlockInteraction.NONE);
}

public void noticePlayerAttack(Player player, Entity provoked) {
Expand Down Expand Up @@ -184,40 +123,6 @@ public void noticePlayerAttack(Player player, Entity provoked) {
if(provoked instanceof DragonDuck) ((DragonDuck) provoked).apathy$allowAttackingPlayers();
}

@Override
public void addRules() {
super.addRules();

partialSerializers.register("advancements", PartialSpecDefenderHasAdvancement.Serializer.INSTANCE);
partialSerializers.register("effect", PartialSpecEffect.Serializer.INSTANCE);
partialSerializers.register("in_player_set", PartialSpecDefenderInPlayerSet.Serializer.INSTANCE);
partialSerializers.register("location", PartialSpecLocation.Serializer.INSTANCE);
partialSerializers.register("score", PartialSpecScore.Serializer.INSTANCE);
partialSerializers.register("team", PartialSpecScoreboardTeam.Serializer.INSTANCE);
}

@Override
public void addMobConfig(ConfigSchema schema) {
super.addMobConfig(schema);
VerMobOptions.visit(schema);
}

@Override
public @Nullable AttackerType parseAttackerType(String s) {
s = s.trim();

if(s.isEmpty()) return null; //can sometimes happen due to shitty parsing code in my config library

ResourceLocation rl = ResourceLocation.tryParse(s);
if(rl == null) {
log.error("Can't parse '{}' as a resourcelocation", s);
return null;
}

EntityType<?> type = Registry.ENTITY_TYPE.get(rl); //defaultedregistry, defaults to pig instead of null
return (AttackerType) type; //duck interface
}

public @Nullable AttackerTag parseAttackerTag(String s) {
s = s.trim();

Expand Down
Loading

0 comments on commit 6814a4c

Please sign in to comment.