Merge branch 'development' into 'development'

Fix BlockInteract stuff for modern bluckutils

See merge request Songoda/songodaupdater!26
This commit is contained in:
Brianna O'Keefe 2020-02-07 02:51:09 +00:00
commit 5c9a5ff9ef
11 changed files with 229 additions and 104 deletions

View File

@ -10,6 +10,7 @@ build:
stage: build
image: maven:3.5.3-jdk-8
script:
- sed -e "s/{REPO_USER}/$REPO_USER/g" -e "s/{REPO_PASS}/$REPO_PASS/g" $path/settings.xml > ~/.m2/settings.xml
- find $path/ -type f -name "*.xml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g
- find $path/ -type f -name "*.yml" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g
- find $path/ -type f -name "*SongodaCore.java" -print0 | xargs -0 sed -i -e s/maven-version-number/$version/g

View File

@ -30,6 +30,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version>
<executions>
<execution>
<id>attach-sources</id>

View File

@ -25,26 +25,27 @@ public enum CompatibleSound {
// https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/mapping-and-modding-tutorials/2213619-1-8-all-playsound-sound-arguments
/* 1.15 */
BLOCK_BEEHIVE_DRIP,
BLOCK_BEEHIVE_ENTER,
BLOCK_BEEHIVE_EXIT,
BLOCK_BEEHIVE_SHEAR,
BLOCK_BEEHIVE_WORK,
BLOCK_HONEY_BLOCK_BREAK,
BLOCK_HONEY_BLOCK_FALL,
BLOCK_HONEY_BLOCK_HIT,
BLOCK_HONEY_BLOCK_PLACE,
BLOCK_HONEY_BLOCK_SLIDE,
BLOCK_HONEY_BLOCK_STEP,
ENTITY_BEE_DEATH,
ENTITY_BEE_HURT,
ENTITY_BEE_LOOP,
ENTITY_BEE_LOOP_AGGRESSIVE,
ENTITY_BEE_POLLINATE,
ENTITY_BEE_STING,
ENTITY_IRON_GOLEM_DAMAGE,
ENTITY_IRON_GOLEM_REPAIR,
ITEM_HONEY_BOTTLE_DRINK,
// TODO: add similar sounds for older versions
BLOCK_BEEHIVE_DRIP(ServerVersion.V1_15, v(null, true)),
BLOCK_BEEHIVE_ENTER(ServerVersion.V1_15, v(null, true)),
BLOCK_BEEHIVE_EXIT(ServerVersion.V1_15, v(null, true)),
BLOCK_BEEHIVE_SHEAR(ServerVersion.V1_15, v(null, true)),
BLOCK_BEEHIVE_WORK(ServerVersion.V1_15, v(null, true)),
BLOCK_HONEY_BLOCK_BREAK(ServerVersion.V1_15, v(null, true)),
BLOCK_HONEY_BLOCK_FALL(ServerVersion.V1_15, v(null, true)),
BLOCK_HONEY_BLOCK_HIT(ServerVersion.V1_15, v(null, true)),
BLOCK_HONEY_BLOCK_PLACE(ServerVersion.V1_15, v(null, true)),
BLOCK_HONEY_BLOCK_SLIDE(ServerVersion.V1_15, v(null, true)),
BLOCK_HONEY_BLOCK_STEP(ServerVersion.V1_15, v(null, true)),
ENTITY_BEE_DEATH(ServerVersion.V1_15, v(null, true)),
ENTITY_BEE_HURT(ServerVersion.V1_15, v(null, true)),
ENTITY_BEE_LOOP(ServerVersion.V1_15, v(null, true)),
ENTITY_BEE_LOOP_AGGRESSIVE(ServerVersion.V1_15, v(null, true)),
ENTITY_BEE_POLLINATE(ServerVersion.V1_15, v(null, true)),
ENTITY_BEE_STING(ServerVersion.V1_15, v(null, true)),
ENTITY_IRON_GOLEM_DAMAGE(ServerVersion.V1_15, v(null, true)),
ENTITY_IRON_GOLEM_REPAIR(ServerVersion.V1_15, v(null, true)),
ITEM_HONEY_BOTTLE_DRINK(ServerVersion.V1_15, v(null, true)),
AMBIENT_CAVE(ServerVersion.V1_9, v("AMBIENCE_CAVE")),
AMBIENT_UNDERWATER_ENTER,

View File

@ -12,6 +12,15 @@ import org.bukkit.inventory.ItemStack;
*/
public enum LegacyMaterialAnalouge {
/* 1.15 */
BEE_SPAWN_EGG(ServerVersion.V1_15, "PARROT_SPAWN_EGG", ServerVersion.V1_12, "MONSTER_EGG", (byte) 65),
BEE_NEST(ServerVersion.V1_15, "BIRCH_LOG", "LOG", (byte) 2),
BEEHIVE(ServerVersion.V1_15, "SLIME_BLOCK", ServerVersion.V1_8, "WOOL", (byte) 4),
HONEY_BLOCK(ServerVersion.V1_15, "SLIME_BLOCK", ServerVersion.V1_8, "WOOL", (byte) 4),
HONEY_BOTTLE(ServerVersion.V1_15, "DRAGON_BREATH", ServerVersion.V1_9, "POTION", (byte) 0),
HONEYCOMB(ServerVersion.V1_15, "SUNFLOWER", "DOUBLE_PLANT", (byte) 0),
HONEYCOMB_BLOCK(ServerVersion.V1_15, "SLIME_BLOCK", ServerVersion.V1_8, "WOOL", (byte) 4),
ACACIA_BOAT(ServerVersion.V1_9, "BOAT"),
ACACIA_BUTTON(ServerVersion.V1_13, "WOOD_BUTTON"),
ACACIA_DOOR(ServerVersion.V1_8, "WOOD_DOOR"), // TODO? ACACIA_DOOR & WOODEN_DOOR are the legacy block variants

View File

@ -16,6 +16,8 @@ public class MySQLConnector implements DatabaseConnector {
public MySQLConnector(Plugin plugin, String hostname, int port, String database, String username, String password, boolean useSSL) {
this.plugin = plugin;
System.out.println("connecting to " + hostname + " : " + port + " with " + password);
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://" + hostname + ":" + port + "/" + database + "?useSSL=" + useSSL);
config.setUsername(username);

View File

@ -155,6 +155,18 @@ public class Gui {
.collect(Collectors.toList())
.forEach(Player::closeInventory);
}
/**
* Close the GUI as if the player closed it normally
*/
public void close() {
allowClose = true;
inventory.getViewers().stream()
.filter(e -> e instanceof Player)
.map(e -> (Player) e)
.collect(Collectors.toList())
.forEach(Player::closeInventory);
}
@NotNull
public GuiType getType() {

View File

@ -236,6 +236,8 @@ public class Locale {
added.stream().collect(Collectors.joining("\n"))
);
}
existingLang.setRootNodeSpacing(0);
existingLang.save();
}
existingLang.setRootNodeSpacing(0);
existingLang.save();

View File

@ -1,5 +1,9 @@
package com.songoda.core.utils;
import java.lang.reflect.Method;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.bukkit.Bukkit;
import org.bukkit.Effect;
import org.bukkit.Material;
import org.bukkit.block.Block;
@ -8,6 +12,7 @@ import org.bukkit.block.data.Ageable;
import org.bukkit.block.data.Bisected;
import org.bukkit.block.data.BlockData;
import org.bukkit.block.data.AnaloguePowerable;
import org.bukkit.block.data.Powerable;
import org.bukkit.block.data.type.Door;
import org.bukkit.block.data.type.Gate;
import org.bukkit.block.data.type.Switch;
@ -15,47 +20,161 @@ import org.bukkit.block.data.type.TrapDoor;
public class BlockUtilsModern {
protected static void _updatePressurePlateModern(Block plate, int power) {
BlockData blockData = plate.getBlockData();
if (blockData instanceof AnaloguePowerable) {
AnaloguePowerable a = (AnaloguePowerable) blockData;
a.setPower(Math.max(a.getMaximumPower(), power));
plate.setBlockData(a);
}
}
protected static void _updatePressurePlateModern(Block plate, int power) {
BlockData blockData = plate.getBlockData();
boolean update = false;
if (blockData instanceof AnaloguePowerable) {
AnaloguePowerable a = (AnaloguePowerable) blockData;
int toPower = Math.min(a.getMaximumPower(), power);
if ((update = toPower != a.getPower())) {
a.setPower(toPower);
plate.setBlockData(a);
}
} else if (blockData instanceof Powerable) {
Powerable p = (Powerable) blockData;
if ((update = p.isPowered() != (power != 0))) {
p.setPowered(power != 0);
plate.setBlockData(p);
}
}
if (update) {
_updateRedstoneNeighbours(plate);
}
}
protected static void _toggleLeverModern(Block lever) {
BlockData blockData = lever.getBlockData();
if (blockData instanceof Switch) {
Switch s = (Switch) blockData;
s.setPowered(!s.isPowered());
lever.setBlockData(s);
//lever.getWorld().playEffect(lever.getLocation(), Effect.CLICK1, 0);
lever.getState().update();
}
}
protected static void _toggleLeverModern(Block lever) {
BlockData blockData = lever.getBlockData();
if (blockData instanceof Switch) {
Switch s = (Switch) blockData;
s.setPowered(!s.isPowered());
lever.setBlockData(s);
_updateRedstoneNeighbours(lever);
}
}
protected static void _pressButtonModern(Block button) {
BlockData blockData = button.getBlockData();
if (blockData instanceof Switch) {
Switch s = (Switch) blockData;
s.setPowered(true);
button.setBlockData(s);
//lever.getWorld().playEffect(lever.getLocation(), Effect.CLICK1, 0);
button.getState().update();
}
}
protected static void _pressButtonModern(Block button) {
BlockData blockData = button.getBlockData();
if (blockData instanceof Switch) {
Switch s = (Switch) blockData;
s.setPowered(true);
button.setBlockData(s);
_updateRedstoneNeighbours(button);
}
}
static void _releaseButtonModern(Block button) {
BlockData blockData = button.getBlockData();
if (blockData instanceof Switch) {
Switch s = (Switch) blockData;
s.setPowered(false);
button.setBlockData(s);
//lever.getWorld().playEffect(lever.getLocation(), Effect.CLICK1, 0);
button.getState().update();
}
}
static void _releaseButtonModern(Block button) {
BlockData blockData = button.getBlockData();
if (blockData instanceof Switch) {
Switch s = (Switch) blockData;
s.setPowered(false);
button.setBlockData(s);
_updateRedstoneNeighbours(button);
}
}
private static Class<?> clazzCraftWorld, clazzCraftBlock,
clazzLeverBlock, clazzButtonBlock, clazzPressurePlateBlock;
private static Method craftWorld_getHandle, craftBlock_getNMSBlock, craftBlock_getPostition, craftBlockData_getState,
nmsLever_updateNeighbours, nmsButton_updateNeighbours, nmsPlate_updateNeighbours;
static {
try {
// Cache reflection.
String ver = Bukkit.getServer().getClass().getPackage().getName().substring(23);
clazzCraftWorld = Class.forName("org.bukkit.craftbukkit." + ver + ".CraftWorld");
clazzCraftBlock = Class.forName("org.bukkit.craftbukkit." + ver + ".block.CraftBlock");
//clazzBlockPosition = Class.forName("net.minecraft.server." + ver + ".BlockPosition");
craftWorld_getHandle = clazzCraftWorld.getMethod("getHandle");
craftBlock_getNMSBlock = clazzCraftBlock.getDeclaredMethod("getNMSBlock");
craftBlock_getNMSBlock.setAccessible(true);
craftBlock_getPostition = clazzCraftBlock.getDeclaredMethod("getPosition");
Class<?> clazzCraftBlockData = Class.forName("org.bukkit.craftbukkit." + ver + ".block.data.CraftBlockData");
craftBlockData_getState = clazzCraftBlockData.getDeclaredMethod("getState");
Class<?> clazzWorld = Class.forName("net.minecraft.server." + ver + ".World");
Class<?> clazzBlockState = Class.forName("net.minecraft.server." + ver + ".IBlockData");
Class<?> clazzBlockPos = Class.forName("net.minecraft.server." + ver + ".BlockPosition");
clazzLeverBlock = Class.forName("net.minecraft.server." + ver + ".BlockLever");
clazzButtonBlock = Class.forName("net.minecraft.server." + ver + ".BlockButtonAbstract");
clazzPressurePlateBlock = Class.forName("net.minecraft.server." + ver + ".BlockPressurePlateAbstract");
// nmsLever_updateNeighbours, nmsButton_updateNeighbours, nmsPlate_updateNeighbours
nmsLever_updateNeighbours = clazzLeverBlock.getDeclaredMethod("e", clazzBlockState, clazzWorld, clazzBlockPos);
nmsLever_updateNeighbours.setAccessible(true);
nmsButton_updateNeighbours = clazzButtonBlock.getDeclaredMethod("f", clazzBlockState, clazzWorld, clazzBlockPos);
nmsButton_updateNeighbours.setAccessible(true);
nmsPlate_updateNeighbours = clazzPressurePlateBlock.getDeclaredMethod("a", clazzWorld, clazzBlockPos);
nmsPlate_updateNeighbours.setAccessible(true);
} catch (Throwable ex) {
Logger.getLogger(BlockUtilsModern.class.getName()).log(Level.SEVERE, null, ex);
}
}
static void _updateRedstoneNeighbours(Block block) {
try {
// spigot made some changes to how data updates work in 1.13+
// updating the data value of a redstone power source
// does NOT update attatched block power,
// even if you update the block state. (Still broken last I checked in 1.15.2)
// so now we're going to manually call the updateNeighbours block method
// invoke and cast objects.
Object cworld = clazzCraftWorld.cast(block.getWorld());
Object mworld = craftWorld_getHandle.invoke(cworld);
Object cblock = clazzCraftBlock.cast(block);
Object mblock = craftBlock_getNMSBlock.invoke(cblock);
Object mpos = craftBlock_getPostition.invoke(cblock);
//System.out.println(mblock.getClass());
// now for testing stuff
if (clazzLeverBlock.isAssignableFrom(mblock.getClass())) {
final Object mstate = craftBlockData_getState.invoke(block.getBlockData());
nmsLever_updateNeighbours.invoke(mblock, mstate, mworld, mpos);
} else if (clazzButtonBlock.isAssignableFrom(mblock.getClass())) {
final Object mstate = craftBlockData_getState.invoke(block.getBlockData());
nmsButton_updateNeighbours.invoke(mblock, mstate, mworld, mpos);
} else if (clazzPressurePlateBlock.isAssignableFrom(mblock.getClass())) {
nmsPlate_updateNeighbours.invoke(mblock, mworld, mpos);
} else {
System.out.println("Unknown redstone: " + mblock.getClass().getName());
}
//
// if(mblock instanceof net.minecraft.server.v1_15_R1.BlockLever) {
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockLever.class.getDeclaredMethod("e", net.minecraft.server.v1_15_R1.IBlockData.class, net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
// updateNeighbours.setAccessible(true);
// // IBlockData = block state after being powered
//
// updateNeighbours.invoke(mblock,
// ((org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData) block.getBlockData()).getState(),
// mworld,
// mpos);
// } else if(mblock instanceof net.minecraft.server.v1_15_R1.BlockButtonAbstract) {
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockButtonAbstract.class.getDeclaredMethod("f", net.minecraft.server.v1_15_R1.IBlockData.class, net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
// updateNeighbours.setAccessible(true);
// // IBlockData = block state after being powered
//
// updateNeighbours.invoke(mblock,
// ((org.bukkit.craftbukkit.v1_15_R1.block.data.CraftBlockData) block.getBlockData()).getState(),
// mworld,
// mpos);
// } else if(mblock instanceof net.minecraft.server.v1_15_R1.BlockPressurePlateAbstract) {
// Method updateNeighbours = net.minecraft.server.v1_15_R1.BlockPressurePlateAbstract.class.getDeclaredMethod("a", net.minecraft.server.v1_15_R1.World.class, net.minecraft.server.v1_15_R1.BlockPosition.class);
// updateNeighbours.setAccessible(true);
// // IBlockData = block state after being powered
//
// updateNeighbours.invoke(mblock,
// mworld,
// mpos);
// }
} catch (Throwable ex) {
Logger.getLogger(BlockUtilsModern.class.getName()).log(Level.SEVERE, null, ex);
}
}
protected static void _toggleDoorStatesModern(boolean allowDoorToOpen, Block... doors) {
for (Block door : doors) {

View File

@ -14,9 +14,10 @@
<dependencies>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot</artifactId>
<version>1.15</version>
<groupId>com.destroystokyo.papermc</groupId>
<artifactId>paper</artifactId>
<version>1.15.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.songoda</groupId>

View File

@ -4,6 +4,7 @@ import com.songoda.core.nms.CustomAnvil;
import com.songoda.core.nms.methods.AnvilTextChange;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.minecraft.server.v1_15_R1.BlockPosition;
@ -11,7 +12,6 @@ import net.minecraft.server.v1_15_R1.ChatMessage;
import net.minecraft.server.v1_15_R1.Container;
import net.minecraft.server.v1_15_R1.ContainerAccess;
import net.minecraft.server.v1_15_R1.ContainerAnvil;
import net.minecraft.server.v1_15_R1.ContainerProperty;
import net.minecraft.server.v1_15_R1.Containers;
import net.minecraft.server.v1_15_R1.EntityHuman;
import net.minecraft.server.v1_15_R1.EntityPlayer;
@ -50,38 +50,27 @@ public class AnvilView extends ContainerAnvil implements CustomAnvil {
}
}
// 1.14.3 and 1.14.4 have different fields for levelCost
static boolean compat_mode = true;
static Method mc_ContainerProperty_set;
static Method mc_ContainerProperty_get;
// 1.14 also made this field private. Fun.
// 1.15 made this field public again, but now it's final. idk.
static Field mc_Container_windowId;
// 1.14 also introduced a title field, also private, which can only be set once and can't be checked
static Field mc_Container_title;
static {
try {
mc_Container_windowId = Container.class.getDeclaredField("windowId");
mc_Container_windowId.setAccessible(true);
mc_Container_title = Container.class.getDeclaredField("title");
mc_Container_title.setAccessible(true);
mc_Container_windowId = Container.class.getDeclaredField("windowId");
mc_Container_windowId.setAccessible(true);
// remove the final modifier
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(mc_Container_windowId, mc_Container_windowId.getModifiers() & ~Modifier.FINAL);
} catch (Exception ex) {
Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex);
}
for (Method m : ContainerProperty.class.getMethods()) {
if (m.getName().equals("set")) {
compat_mode = false;
break;
}
}
if (compat_mode) {
try {
mc_ContainerProperty_set = ContainerProperty.class.getDeclaredMethod("a", int.class);
mc_ContainerProperty_get = ContainerProperty.class.getDeclaredMethod("b");
} catch (Exception ex) {
Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Setup Error", ex);
}
}
}
public AnvilView(int id, EntityPlayer entity, InventoryHolder holder) {
@ -120,18 +109,7 @@ public class AnvilView extends ContainerAnvil implements CustomAnvil {
public void e() {
super.e();
if (cost >= 0) {
if (compat_mode) {
if (mc_ContainerProperty_set != null) {
try {
mc_ContainerProperty_set.invoke(this.levelCost, 0);
} catch (Exception ex) {
Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex);
mc_ContainerProperty_set = null;
}
}
} else {
this.levelCost.set(cost);
}
this.levelCost.set(cost);
}
textChange.onChange();
}
@ -180,19 +158,9 @@ public class AnvilView extends ContainerAnvil implements CustomAnvil {
public int getLevelCost() {
if (cost >= 0) {
return cost;
} else if (compat_mode) {
if (mc_ContainerProperty_get != null) {
try {
return (int) mc_ContainerProperty_get.invoke(this.levelCost);
} catch (Exception ex) {
Logger.getLogger(AnvilView.class.getName()).log(Level.SEVERE, "Anvil Error", ex);
mc_ContainerProperty_get = null;
}
}
} else {
return this.levelCost.get();
}
return -1;
}
@Override
@ -258,4 +226,4 @@ public class AnvilView extends ContainerAnvil implements CustomAnvil {
entity.activeContainer.addSlotListener(entity);
}
}
}

9
settings.xml Normal file
View File

@ -0,0 +1,9 @@
<settings>
<servers>
<server>
<id>private</id>
<username>{REPO_USER}</username>
<password>{REPO_PASS}</password>
</server>
</servers>
</settings>