Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add breeding #7110

Open
wants to merge 67 commits into
base: dev/feature
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
a437ca9
Update aliases I guess?
Fusezion Mar 30, 2023
296a944
Revert "Update aliases I guess?"
Fusezion Mar 30, 2023
2cdf76d
Adding Events
Fusezion Apr 7, 2023
9b3afd9
Breeding Event Expressions
Fusezion Apr 7, 2023
27e1392
More Breeding Related Syntax
Fusezion Apr 7, 2023
07ced16
Pattern Fixes & Class Exist checks
Fusezion Apr 7, 2023
6ab1dba
Test, Test, Test
Fusezion Apr 7, 2023
0423ea7
Merge branch 'master' into enhancement/Breedable
Fusezion Apr 7, 2023
c6acbe9
:purple_heart: Formatting
Fusezion Apr 7, 2023
243d402
Added Adult Syntax
Fusezion Apr 7, 2023
8bcbffb
Apply suggestions from code review
Fusezion Apr 7, 2023
50748f5
ExprLoveTime -> ExprLoveTicks
Fusezion Apr 8, 2023
93059ae
Update ExprBreedingFamily.java
Fusezion Apr 8, 2023
912a300
Update ExprExperience.java
Fusezion Apr 8, 2023
09d1999
Added comment to CondIsAdult and EffMakeAdult
Fusezion Apr 8, 2023
daeb7bf
Merge branch 'master' into enhancement/Breedable
Fusezion Apr 8, 2023
c543ef2
Merge branch 'master' into enhancement/Breedable
TheLimeGlass Apr 8, 2023
34d5453
Syntax description notes
Fusezion Apr 8, 2023
0b894cc
Update ExprLoveTicks and SimpleEvents
Fusezion Apr 8, 2023
0b10f7d
Fix ExprLoveTicks & Update Test
Fusezion Apr 8, 2023
14b7962
LoveTicks -> LoveTime
Fusezion Apr 10, 2023
4ab107e
Merge branch 'master' into enhancement/Breedable
Fusezion Apr 17, 2023
442602a
Apply suggestions from code review
Fusezion Apr 19, 2023
babb7b1
Change CondIsAdult condition checks
Fusezion Apr 19, 2023
60a0500
Apply requested code review changes
Fusezion Apr 19, 2023
a8deec7
Apply more requested changes
Fusezion Apr 19, 2023
f46a502
Merge branch 'enhancement/Breedable' of https://github.com/Fusezion/S…
Fusezion Apr 19, 2023
fcbe57a
Merge branch 'master' into enhancement/Breedable
Fusezion May 1, 2023
a5f894d
Merge branch 'master' into enhancement/Breedable
Fusezion Jul 12, 2023
2556e3b
Merge branch 'SkriptLang:master' into enhancement/Breedable
Fusezion Aug 8, 2023
47301ca
Merge branch 'dev/feature' into enhancement/Breedable
Fusezion Oct 13, 2023
abe6540
Merge branch 'dev/feature' into enhancement/Breedable
sovdeeth Dec 30, 2023
f6e2954
Merge branch 'dev/feature' into enhancement/Breedable
Fusezion Jan 1, 2024
04d4e3a
Merge branch 'dev/feature' into enhancement/Breedable
Fusezion Jan 1, 2024
f14bc73
Merge branch 'dev/feature' into enhancement/Breedable
sovdeeth Jun 28, 2024
485ac5f
Merge branch 'dev/feature' into enhancement/Breedable
sovdeeth Jul 1, 2024
9d98120
update conds
Efnilite Sep 22, 2024
29847db
update exprs
Efnilite Sep 22, 2024
803c718
update effs
Efnilite Sep 22, 2024
fe00590
update event values
Efnilite Sep 22, 2024
668dad6
Merge branch 'fork/Fusezion/enhancement/Breedable' into breeding
Efnilite Sep 22, 2024
91b9ee1
update annot
Efnilite Sep 22, 2024
5018770
update annotations
Efnilite Sep 22, 2024
28c1ac3
update CondIsInLove
Efnilite Sep 22, 2024
f0a12da
renames
Efnilite Sep 22, 2024
987ff80
updates
Efnilite Sep 22, 2024
11dbd44
update tests
Efnilite Sep 22, 2024
7715a65
oops
Efnilite Sep 22, 2024
24e3c2b
fix
Efnilite Sep 22, 2024
05e7627
grr
Efnilite Sep 22, 2024
8b7106f
gahr
Efnilite Sep 22, 2024
d4be4e9
add breeding trigger event
Efnilite Sep 22, 2024
06dd041
more
Efnilite Sep 23, 2024
9ab4f4a
MORE
Efnilite Sep 23, 2024
555c053
MORE!!!!
Efnilite Sep 23, 2024
fb105b4
MORE!!!!!!
Efnilite Sep 23, 2024
fd0baef
Merge branch 'dev/feature' into breeding
Efnilite Sep 23, 2024
d74ddc9
stupid copilot
Efnilite Sep 23, 2024
4f4b5aa
Merge remote-tracking branch 'origin/breeding' into breeding
Efnilite Sep 23, 2024
d43733a
g
Efnilite Sep 23, 2024
eff120d
fixes
Efnilite Sep 26, 2024
43d3769
agag
Efnilite Sep 26, 2024
cbee1bc
Merge branch 'dev/feature' into breeding
Efnilite Oct 14, 2024
ef65bea
move to module
Efnilite Oct 16, 2024
786f4cd
load
Efnilite Oct 16, 2024
b78265e
Merge branch 'dev/feature' into breeding
Efnilite Oct 16, 2024
1dccd2b
fix imports
Efnilite Oct 17, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/ch/njol/skript/Skript.java
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
import org.skriptlang.skript.bukkit.SkriptMetrics;
import org.skriptlang.skript.bukkit.breeding.BreedingModule;
import org.skriptlang.skript.bukkit.displays.DisplayModule;
import org.skriptlang.skript.lang.comparator.Comparator;
import org.skriptlang.skript.lang.comparator.Comparators;
Expand Down Expand Up @@ -555,6 +556,7 @@ public void onEnable() {
getAddonInstance().loadClasses("org.skriptlang.skript.bukkit", "misc");
// todo: become proper module once registry api is merged
DisplayModule.load();
BreedingModule.load();
} catch (final Exception e) {
exception(e, "Could not load required .class files: " + e.getLocalizedMessage());
setEnabled(false);
Expand Down
186 changes: 83 additions & 103 deletions src/main/java/ch/njol/skript/expressions/ExprExperience.java
Original file line number Diff line number Diff line change
@@ -1,146 +1,126 @@
/**
* This file is part of Skript.
*
* Skript is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Skript is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Skript. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright Peter Güttinger, SkriptLang team and contributors
*/
package ch.njol.skript.expressions;

import org.bukkit.event.Event;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.jetbrains.annotations.Nullable;

import ch.njol.skript.Skript;
import ch.njol.skript.classes.Changer.ChangeMode;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Events;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import ch.njol.skript.doc.*;
import ch.njol.skript.events.bukkit.ExperienceSpawnEvent;
import ch.njol.skript.lang.Expression;
import ch.njol.skript.lang.ExpressionType;
import ch.njol.skript.lang.SkriptParser.ParseResult;
import ch.njol.skript.lang.util.SimpleExpression;
import ch.njol.skript.util.Experience;
import ch.njol.util.Kleenean;
import ch.njol.util.coll.CollectionUtils;
import org.bukkit.event.Event;
import org.bukkit.event.block.BlockBreakEvent;
import org.bukkit.event.entity.EntityBreedEvent;
import org.bukkit.event.player.PlayerExpChangeEvent;
import org.jetbrains.annotations.Nullable;

/**
* @author Peter Güttinger
*/
@Name("Experience")
@Description("How much experience was spawned in an experience spawn or block break event. Can be changed.")
@Examples({"on experience spawn:",
@Examples({
"on experience spawn:",
"\tadd 5 to the spawned experience",
"on break of coal ore:",
"",
"on break of coal ore:",
"\tclear dropped experience",
"on break of diamond ore:",
"",
"on break of diamond ore:",
"\tif tool of player = diamond pickaxe:",
"\t\tadd 100 to dropped experience"})
@Since("2.1, 2.5.3 (block break event), 2.7 (experience change event)")
@Events({"experience spawn", "break / mine", "experience change"})
"\t\tadd 100 to dropped experience",
"",
"on breed:",
"\tbreeding father is a cow",
"\tset dropped experience to 10"
})
@Since("2.1, 2.5.3 (block break event), 2.7 (experience change event), INSERT VERSION (breeding event)")
@Events({"experience spawn", "break / mine", "experience change", "entity breeding"})
public class ExprExperience extends SimpleExpression<Experience> {
Efnilite marked this conversation as resolved.
Show resolved Hide resolved

static {
Skript.registerExpression(ExprExperience.class, Experience.class, ExpressionType.SIMPLE, "[the] (spawned|dropped|) [e]xp[erience] [orb[s]]");
Skript.registerExpression(ExprExperience.class, Experience.class, ExpressionType.SIMPLE,
"[the] (spawned|dropped|) [e]xp[erience] [orb[s]]");
}

@Override
public boolean init(final Expression<?>[] exprs, final int matchedPattern, final Kleenean isDelayed, final ParseResult parseResult) {
if (!getParser().isCurrentEvent(ExperienceSpawnEvent.class, BlockBreakEvent.class, PlayerExpChangeEvent.class)) {
Skript.error("The experience expression can only be used in experience spawn, block break and player experience change events");
public boolean init(Expression<?>[] expressions, int matchedPattern,
Kleenean isDelayed, ParseResult parseResult) {
if (!getParser().isCurrentEvent(ExperienceSpawnEvent.class, BlockBreakEvent.class,
PlayerExpChangeEvent.class, EntityBreedEvent.class)) {
Skript.error("The experience expression can only be used in experience spawn, " +
"block break, player experience change and entity breeding events");
return false;
}

return true;
}

@Override
@Nullable
protected Experience[] get(final Event e) {
if (e instanceof ExperienceSpawnEvent)
return new Experience[] {new Experience(((ExperienceSpawnEvent) e).getSpawnedXP())};
else if (e instanceof BlockBreakEvent)
return new Experience[] {new Experience(((BlockBreakEvent) e).getExpToDrop())};
else if (e instanceof PlayerExpChangeEvent)
return new Experience[] {new Experience(((PlayerExpChangeEvent) e).getAmount())};
else
return new Experience[0];
protected Experience @Nullable [] get(Event event) {
Experience[] exp;

if (event instanceof ExperienceSpawnEvent experienceSpawnEvent) {
exp = new Experience[]{new Experience(experienceSpawnEvent.getSpawnedXP())};
} else if (event instanceof BlockBreakEvent blockBreakEvent) {
exp = new Experience[]{new Experience(blockBreakEvent.getExpToDrop())};
} else if (event instanceof PlayerExpChangeEvent playerExpChangeEvent) {
exp = new Experience[]{new Experience(playerExpChangeEvent.getAmount())};
} else if (event instanceof EntityBreedEvent entityBreedEvent) {
exp = new Experience[]{new Experience(entityBreedEvent.getExperience())};
} else {
exp = new Experience[0];
}

return exp;
}

@Override
@Nullable
public Class<?>[] acceptChange(final ChangeMode mode) {
switch (mode) {
case ADD:
case DELETE:
case REMOVE:
case REMOVE_ALL:
return new Class[] {Experience[].class, Number[].class};
case SET:
return new Class[] {Experience.class, Number.class};
case RESET:
return null;
}
return null;
public Class<?> @Nullable [] acceptChange(ChangeMode mode) {
return switch (mode) {
case SET, DELETE -> CollectionUtils.array(Experience.class, Integer.class);
case ADD, REMOVE -> CollectionUtils.array(Experience[].class, Integer[].class);
case RESET -> CollectionUtils.array();
default -> null;
};
}

@Override
public void change(final Event e, final @Nullable Object[] delta, final ChangeMode mode) {
double eventExp;
if (e instanceof ExperienceSpawnEvent) {
eventExp = ((ExperienceSpawnEvent) e).getSpawnedXP();
} else if (e instanceof BlockBreakEvent) {
eventExp = ((BlockBreakEvent) e).getExpToDrop();
} else if (e instanceof PlayerExpChangeEvent) {
eventExp = ((PlayerExpChangeEvent) e).getAmount();
public void change(Event event, Object @Nullable [] delta, ChangeMode mode) {
int exp;

if (event instanceof ExperienceSpawnEvent experienceSpawnEvent) {
exp = experienceSpawnEvent.getSpawnedXP();
} else if (event instanceof BlockBreakEvent blockBreakEvent) {
exp = blockBreakEvent.getExpToDrop();
} else if (event instanceof PlayerExpChangeEvent playerExpChangeEvent) {
exp = playerExpChangeEvent.getAmount();
} else if (event instanceof EntityBreedEvent entityBreedEvent) {
exp = entityBreedEvent.getExperience();
} else {
return;
}
if (delta == null) {
eventExp = 0;
} else {
for (Object obj : delta) {
double value = obj instanceof Experience ? ((Experience) obj).getXP() : ((Number) obj).doubleValue();

if (delta != null) {
for (Object object : delta) {
int value = object instanceof Experience experience ? experience.getXP() : (int) object;
switch (mode) {
case ADD:
eventExp += value;
break;
case SET:
eventExp = value;
break;
case REMOVE:
case REMOVE_ALL:
eventExp -= value;
break;
case RESET:
case DELETE:
assert false;
break;
case ADD -> exp += value;
case SET -> exp = value;
case REMOVE, REMOVE_ALL -> exp -= value;
}
}
}


eventExp = Math.max(0, Math.round(eventExp));
int roundedEventExp = (int) eventExp;
if (e instanceof ExperienceSpawnEvent) {
((ExperienceSpawnEvent) e).setSpawnedXP(roundedEventExp);
} else if (e instanceof BlockBreakEvent) {
((BlockBreakEvent) e).setExpToDrop(roundedEventExp);
} else if (e instanceof PlayerExpChangeEvent) {
((PlayerExpChangeEvent) e).setAmount(roundedEventExp);
exp = Math.max(0, exp);
if (event instanceof ExperienceSpawnEvent experienceSpawnEvent) {
experienceSpawnEvent.setSpawnedXP(exp);
} else if (event instanceof BlockBreakEvent blockBreakEvent) {
blockBreakEvent.setExpToDrop(exp);
} else if (event instanceof PlayerExpChangeEvent playerExpChangeEvent) {
playerExpChangeEvent.setAmount(exp);
} else if (event instanceof EntityBreedEvent entityBreedEvent) {
entityBreedEvent.setExperience(exp);
}
}

Expand All @@ -155,7 +135,7 @@ public Class<? extends Experience> getReturnType() {
}

@Override
public String toString(final @Nullable Event e, final boolean debug) {
public String toString(@Nullable Event event, boolean debug) {
return "the experience";
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.skriptlang.skript.bukkit.breeding;

import ch.njol.skript.Skript;
import ch.njol.skript.lang.util.SimpleEvent;
import ch.njol.skript.registrations.EventValues;
import ch.njol.skript.util.Getter;
import org.bukkit.entity.HumanEntity;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.entity.EntityBreedEvent;
import org.bukkit.event.entity.EntityEnterLoveModeEvent;
import org.bukkit.inventory.ItemStack;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;

public class BreedingModule {

public static void load() throws IOException {
Skript.getAddonInstance().loadClasses("org.skriptlang.skript.bukkit.breeding", "elements");

Skript.registerEvent("Love Mode Enter", SimpleEvent.class, EntityEnterLoveModeEvent.class,
"[entity] enter[s] love mode", "[entity] love mode [enter]")
.description("Called whenever an entity enters a state of being in love.")
.examples(
"on love mode enter:",
"\tcancel event # No one is allowed love here"
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

!!!

)
.since("INSERT VERSION");

EventValues.registerEventValue(EntityBreedEvent.class, ItemStack.class, new Getter<>() {
@Override
public @Nullable ItemStack get(EntityBreedEvent event) {
return event.getBredWith();
}
}, EventValues.TIME_NOW);

EventValues.registerEventValue(EntityEnterLoveModeEvent.class, LivingEntity.class, new Getter<>() {
@Override
public LivingEntity get(EntityEnterLoveModeEvent event) {
return event.getEntity();
}
}, EventValues.TIME_NOW);

EventValues.registerEventValue(EntityEnterLoveModeEvent.class, HumanEntity.class, new Getter<>() {
@Override
public @Nullable HumanEntity get(EntityEnterLoveModeEvent event) {
return event.getHumanEntity();
}
}, EventValues.TIME_NOW);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package org.skriptlang.skript.bukkit.breeding.elements;

import ch.njol.skript.conditions.base.PropertyCondition;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import org.bukkit.entity.Breedable;
import org.bukkit.entity.LivingEntity;

@Name("Can Age")
@Description("Checks whether or not an entity will be able to age/grow up.")
@Examples({
"on breeding:",
"\tentity can't age",
"\tbroadcast \"An immortal has been born!\" to player"
})
@Since("INSERT VERSION")
public class CondCanAge extends PropertyCondition<LivingEntity> {

static {
register(CondCanAge.class, PropertyType.CAN, "(age|grow (up|old[er]))", "livingentities");
}

@Override
public boolean check(LivingEntity entity) {
return entity instanceof Breedable breedable && !breedable.getAgeLock();
}

@Override
protected String getPropertyName() {
return "age";
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.skriptlang.skript.bukkit.breeding.elements;

import ch.njol.skript.Skript;
import ch.njol.skript.conditions.base.PropertyCondition;
import ch.njol.skript.doc.Description;
import ch.njol.skript.doc.Examples;
import ch.njol.skript.doc.Name;
import ch.njol.skript.doc.Since;
import org.bukkit.entity.Breedable;
import org.bukkit.entity.LivingEntity;

@Name("Can Breed")
@Description("Checks whether or not a living entity can be bred.")
@Examples({
"on right click on living entity:",
"\tevent-entity can't breed",
"\tsend \"Turns out %event-entity% is not breedable. Must be a Skript user!\" to player"
})
@Since("INSERT VERSION")
public class CondCanBreed extends PropertyCondition<LivingEntity> {

static {
register(CondCanBreed.class, PropertyType.CAN, "(breed|be bred)", "livingentities");
}

@Override
public boolean check(LivingEntity entity) {
return entity instanceof Breedable breedable && breedable.canBreed();
}

@Override
protected String getPropertyName() {
return "breed";
}

}
Loading