From e88b4400d52f9deaa8c9fd7c0aba55aadfabe601 Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Sat, 27 Oct 2018 18:06:21 -0700 Subject: [PATCH 01/10] Fix item_pre_craft event --- src/main/java/com/laytonsmith/core/ObjectGenerator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/laytonsmith/core/ObjectGenerator.java b/src/main/java/com/laytonsmith/core/ObjectGenerator.java index 2f49cef72..7c62c3066 100644 --- a/src/main/java/com/laytonsmith/core/ObjectGenerator.java +++ b/src/main/java/com/laytonsmith/core/ObjectGenerator.java @@ -225,7 +225,7 @@ public MCLocation location(Construct c, MCWorld w, Target t) { * @return An item array or CNull */ public Construct item(MCItemStack is, Target t) { - if(is.isEmpty()) { + if(is == null || is.isEmpty()) { return CNull.NULL; } From e1fabec41d62d1ed3b913a5d1f7d4a6d1dd3cc2c Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Sat, 27 Oct 2018 18:07:08 -0700 Subject: [PATCH 02/10] Fix ponline() when given a UUID --- .../com/laytonsmith/abstraction/MCServer.java | 2 ++ .../abstraction/bukkit/BukkitMCServer.java | 10 ++++++++ .../core/functions/PlayerManagement.java | 24 +++++++------------ 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/laytonsmith/abstraction/MCServer.java b/src/main/java/com/laytonsmith/abstraction/MCServer.java index 682743d68..1b8a28da7 100644 --- a/src/main/java/com/laytonsmith/abstraction/MCServer.java +++ b/src/main/java/com/laytonsmith/abstraction/MCServer.java @@ -22,6 +22,8 @@ public interface MCServer extends AbstractionObject { MCPluginManager getPluginManager(); + MCPlayer getPlayerExact(String name); + MCPlayer getPlayer(String name); MCPlayer getPlayer(UUID uuid); diff --git a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCServer.java b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCServer.java index 479b3e149..63f35beda 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCServer.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCServer.java @@ -172,6 +172,16 @@ public MCPluginManager getPluginManager() { return new BukkitMCPluginManager(s.getPluginManager()); } + @Override + @SuppressWarnings("deprecation") + public MCPlayer getPlayerExact(String name) { + Player p = s.getPlayerExact(name); + if(p == null) { + return null; + } + return new BukkitMCPlayer(p); + } + @Override @SuppressWarnings("deprecation") public MCPlayer getPlayer(String name) { diff --git a/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java b/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java index 6fe8f05e4..8cef78ef3 100644 --- a/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java +++ b/src/main/java/com/laytonsmith/core/functions/PlayerManagement.java @@ -2558,25 +2558,17 @@ public Boolean runAsync() { @Override public Construct exec(Target t, Environment env, Construct... args) throws ConfigRuntimeException { - //We have to use this method here, because we might be in the midst - //of an event, in which the player is offline, but not really. It will - //throw an exception if the player doesn't exist - MCPlayer p = null; try { - p = Static.GetPlayer(args[0], t); + //Static.GetPlayer() autocompletes names, which we don't want in this function, + //however we have to check if this is an injected player first. + MCPlayer p = Static.GetPlayer(args[0], t); + //Now we must check if the name was exact. Skip this if the argument is a UUID. + if(args[0].val().length() <= 16 && !p.getName().equalsIgnoreCase(args[0].val())) { + p = Static.getServer().getPlayerExact(args[0].val()); + } + return CBoolean.get(p != null); } catch (ConfigRuntimeException e) { //They aren't in the player list - } - //If the player we grabbed doesn't match exactly, we're referring to another player - //However, we had to check with Static.GetPlayer first, in case this is an injected player. - //Otherwise, we need to use the player returned from Static.GetPlayer, not the one returned - //from the server directly - if(p != null && !p.getName().equals(args[0].val())) { - MCOfflinePlayer player = Static.getServer().getOfflinePlayer(args[0].val()); - return CBoolean.get(player.isOnline()); - } else if(p != null) { - return CBoolean.get(p.isOnline()); - } else { return CBoolean.FALSE; } } From 27124a4613aff57451d7e8efa417a34caed3568c Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Sat, 27 Oct 2018 18:09:16 -0700 Subject: [PATCH 03/10] Add get_entity_riders() and clarify behavior of rider functions. Also fix core error when horse and rider are identical in set_entity_rider(). --- .../com/laytonsmith/abstraction/MCEntity.java | 2 +- .../bukkit/entities/BukkitMCEntity.java | 10 ++--- .../core/events/drivers/VehicleEvents.java | 17 ++++---- .../core/functions/EntityManagement.java | 43 ++++++++++++++++--- 4 files changed, 53 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/laytonsmith/abstraction/MCEntity.java b/src/main/java/com/laytonsmith/abstraction/MCEntity.java index 77fd65467..e10941cb0 100644 --- a/src/main/java/com/laytonsmith/abstraction/MCEntity.java +++ b/src/main/java/com/laytonsmith/abstraction/MCEntity.java @@ -25,7 +25,7 @@ public interface MCEntity extends MCMetadatable { List getNearbyEntities(double x, double y, double z); - MCEntity getPassenger(); + List getPassengers(); MCServer getServer(); diff --git a/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCEntity.java b/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCEntity.java index 313f89f9c..4ca3903e5 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCEntity.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/entities/BukkitMCEntity.java @@ -105,12 +105,12 @@ public List getNearbyEntities(double x, double y, double z) { } @Override - public MCEntity getPassenger() { - List passengers = e.getPassengers(); - if(passengers.isEmpty()) { - return null; + public List getPassengers() { + List passengers = new ArrayList<>(); + for(Entity passenger : e.getPassengers()) { + passengers.add(BukkitConvertor.BukkitGetCorrectEntity(passenger)); } - return BukkitConvertor.BukkitGetCorrectEntity(passengers.get(0)); + return passengers; } @Override diff --git a/src/main/java/com/laytonsmith/core/events/drivers/VehicleEvents.java b/src/main/java/com/laytonsmith/core/events/drivers/VehicleEvents.java index 1d4a91da4..66b461a0b 100644 --- a/src/main/java/com/laytonsmith/core/events/drivers/VehicleEvents.java +++ b/src/main/java/com/laytonsmith/core/events/drivers/VehicleEvents.java @@ -45,6 +45,7 @@ import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Set; import java.util.UUID; @@ -465,9 +466,9 @@ public boolean matches(Map prefilter, BindableEvent e) throws } Prefilters.match(prefilter, "vehicletype", event.getVehicle().getType().name(), PrefilterType.MACRO); - MCEntity passenger = event.getVehicle().getPassenger(); - if(passenger != null) { - Prefilters.match(prefilter, "passengertype", passenger.getType().name(), PrefilterType.MACRO); + List passengers = event.getVehicle().getPassengers(); + if(!passengers.isEmpty()) { + Prefilters.match(prefilter, "passengertype", passengers.get(0).getType().name(), PrefilterType.MACRO); } return true; @@ -500,21 +501,21 @@ public Map evaluate(BindableEvent event) throws EventExceptio ret.put("vehicletype", new CString(e.getVehicle().getType().name(), t)); ret.put("id", new CString(e.getVehicle().getUniqueId().toString(), t)); - MCEntity passenger = e.getVehicle().getPassenger(); + List passengers = e.getVehicle().getPassengers(); - if(passenger == null) { + if(passengers.isEmpty()) { ret.put("passenger", CNull.NULL); ret.put("passengertype", CNull.NULL); ret.put("player", CNull.NULL); } else { - - MCEntityType passengertype = e.getVehicle().getPassenger().getType(); + MCEntity passenger = passengers.get(0); + MCEntityType passengertype = passenger.getType(); ret.put("passengertype", new CString(passengertype.name(), t)); ret.put("passenger", new CString(passenger.getUniqueId().toString(), t)); if(passengertype.getAbstracted() == MCEntityType.MCVanillaEntityType.PLAYER) { - ret.put("player", new CString(((MCPlayer) e.getVehicle().getPassenger()).getName(), t)); + ret.put("player", new CString(((MCPlayer) passenger).getName(), t)); } else { ret.put("player", CNull.NULL); } diff --git a/src/main/java/com/laytonsmith/core/functions/EntityManagement.java b/src/main/java/com/laytonsmith/core/functions/EntityManagement.java index 32695fbb9..89ba50454 100644 --- a/src/main/java/com/laytonsmith/core/functions/EntityManagement.java +++ b/src/main/java/com/laytonsmith/core/functions/EntityManagement.java @@ -1267,7 +1267,7 @@ public Construct exec(Target t, Environment environment, Construct... args) thro } else { rider = Static.getEntity(args[1], t); } - if((horse == null && rider == null) || horse == rider) { + if((horse == null && rider == null) || args[0].val().equals(args[1].val())) { throw new CREFormatException("Horse and rider cannot be the same entity", t); } else if(horse == null) { success = rider.leaveVehicle(); @@ -1295,7 +1295,8 @@ public String docs() { + " If rider is null, horse will eject its current rider, if it has one. If horse is null," + " rider will leave whatever it is riding. If horse and rider are both valid entities," + " rider will ride horse. The function returns the success of whatever operation is done." - + " If horse and rider are both null, or otherwise the same, a FormatException is thrown."; + + " If horse and rider are both null, or otherwise the same, a FormatException is thrown." + + " If a horse already has a rider, this will add the new rider without ejecting the existing one."; } @Override @@ -1310,8 +1311,9 @@ public static class get_entity_rider extends EntityGetterFunction { @Override public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { MCEntity ent = Static.getEntity(args[0], t); - if(ent.getPassenger() != null) { - return new CString(ent.getPassenger().getUniqueId().toString(), t); + List passengers = ent.getPassengers(); + if(!passengers.isEmpty()) { + return new CString(passengers.get(0).getUniqueId().toString(), t); } return CNull.NULL; } @@ -1323,7 +1325,8 @@ public String getName() { @Override public String docs() { - return "string {entityUUID} Returns the UUID of the given entity's rider, or null if it doesn't have one."; + return "string {entityUUID} Returns the UUID of the given entity's rider, or null if it doesn't have one." + + " If there are multiple riders, only the first is returned."; } @Override @@ -1332,6 +1335,36 @@ public CHVersion since() { } } + @api + public static class get_entity_riders extends EntityGetterFunction { + + @Override + public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { + MCEntity ent = Static.getEntity(args[0], t); + List riders = ent.getPassengers(); + CArray ret = new CArray(t); + for(MCEntity rider : riders) { + ret.push(new CString(rider.getUniqueId().toString(), t), t); + } + return ret; + } + + @Override + public String getName() { + return "get_entity_riders"; + } + + @Override + public String docs() { + return "array {entityUUID} Returns an array of UUIDs for the given entity's riders."; + } + + @Override + public CHVersion since() { + return CHVersion.V3_3_3; + } + } + @api public static class get_entity_vehicle extends EntityGetterFunction { From 3fbde6f6f7e0c6f579034ad7a6ccd7701a6a1b86 Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Sun, 28 Oct 2018 21:55:50 -0700 Subject: [PATCH 04/10] Add "color" to scoreboard teams --- .../com/laytonsmith/abstraction/MCTeam.java | 5 ++++ .../abstraction/bukkit/BukkitMCTeam.java | 12 ++++++++ .../core/functions/Scoreboards.java | 29 ++++++++++++++----- 3 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/laytonsmith/abstraction/MCTeam.java b/src/main/java/com/laytonsmith/abstraction/MCTeam.java index f1857b2a1..afd0e6434 100644 --- a/src/main/java/com/laytonsmith/abstraction/MCTeam.java +++ b/src/main/java/com/laytonsmith/abstraction/MCTeam.java @@ -1,5 +1,6 @@ package com.laytonsmith.abstraction; +import com.laytonsmith.abstraction.enums.MCChatColor; import com.laytonsmith.abstraction.enums.MCOption; import com.laytonsmith.abstraction.enums.MCOptionStatus; @@ -29,6 +30,8 @@ public interface MCTeam { String getSuffix(); + MCChatColor getColor(); + boolean hasEntry(String entry); boolean removeEntry(String entry); @@ -45,5 +48,7 @@ public interface MCTeam { void setSuffix(String suffix); + void setColor(MCChatColor color); + void unregister(); } diff --git a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCTeam.java b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCTeam.java index def06f182..7706f1324 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCTeam.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCTeam.java @@ -2,8 +2,10 @@ import com.laytonsmith.abstraction.MCScoreboard; import com.laytonsmith.abstraction.MCTeam; +import com.laytonsmith.abstraction.enums.MCChatColor; import com.laytonsmith.abstraction.enums.MCOption; import com.laytonsmith.abstraction.enums.MCOptionStatus; +import com.laytonsmith.abstraction.enums.bukkit.BukkitMCChatColor; import com.laytonsmith.abstraction.enums.bukkit.BukkitMCOption; import com.laytonsmith.abstraction.enums.bukkit.BukkitMCOptionStatus; import org.bukkit.scoreboard.Team; @@ -78,6 +80,11 @@ public String getSuffix() { return t.getSuffix(); } + @Override + public MCChatColor getColor() { + return BukkitMCChatColor.getConvertor().getAbstractedEnum(t.getColor()); + } + @Override public boolean hasEntry(String entry) { return t.hasEntry(entry); @@ -118,6 +125,11 @@ public void setSuffix(String suffix) { t.setSuffix(suffix); } + @Override + public void setColor(MCChatColor color) { + t.setColor(BukkitMCChatColor.getConvertor().getConcreteEnum(color)); + } + @Override public void unregister() { t.unregister(); diff --git a/src/main/java/com/laytonsmith/core/functions/Scoreboards.java b/src/main/java/com/laytonsmith/core/functions/Scoreboards.java index 618d7e7e6..9d68277ef 100644 --- a/src/main/java/com/laytonsmith/core/functions/Scoreboards.java +++ b/src/main/java/com/laytonsmith/core/functions/Scoreboards.java @@ -6,6 +6,7 @@ import com.laytonsmith.abstraction.MCPlayer; import com.laytonsmith.abstraction.MCScoreboard; import com.laytonsmith.abstraction.MCTeam; +import com.laytonsmith.abstraction.enums.MCChatColor; import com.laytonsmith.abstraction.enums.MCCriteria; import com.laytonsmith.abstraction.enums.MCDisplaySlot; import com.laytonsmith.abstraction.enums.MCOption; @@ -25,6 +26,7 @@ import com.laytonsmith.core.constructs.Target; import com.laytonsmith.core.environments.Environment; import com.laytonsmith.core.exceptions.CRE.CREFormatException; +import com.laytonsmith.core.exceptions.CRE.CREIllegalArgumentException; import com.laytonsmith.core.exceptions.CRE.CRELengthException; import com.laytonsmith.core.exceptions.CRE.CRENullPointerException; import com.laytonsmith.core.exceptions.CRE.CREPlayerOfflineException; @@ -189,6 +191,7 @@ static CArray getTeam(MCTeam team, Target t) { to.set("displayname", new CString(team.getDisplayName(), t), t); to.set("prefix", new CString(team.getPrefix(), t), t); to.set("suffix", new CString(team.getSuffix(), t), t); + to.set("color", new CString(team.getColor().name(), t), t); to.set("size", new CInt(team.getSize(), t), t); CArray ops = CArray.GetAssociativeArray(t); ops.set("friendlyfire", CBoolean.get(team.allowFriendlyFire()), t); @@ -454,7 +457,7 @@ public String docs() { return "array {[scoreboard]} Returns an array of arrays about the teams on the given scoreboard," + " which defaults to '" + MAIN + "' if not given. The array keys are the team names," + " and each value is a team array containing the keys: name, displayname, prefix, suffix, size," - + " options, and players."; + + " color, options, and players."; } @Override @@ -692,7 +695,8 @@ public static class set_team_display extends SBFunction { @Override public Class[] thrown() { - return new Class[]{CRELengthException.class, CREScoreboardException.class}; + return new Class[]{CRELengthException.class, CREScoreboardException.class, + CREIllegalArgumentException.class}; } @Override @@ -747,6 +751,15 @@ public Construct exec(Target t, Environment environment, Construct... args) thro throw new CRELengthException(ex.getMessage(), t); } } + if(dis.containsKey("color")) { + try { + MCChatColor color = MCChatColor.valueOf(dis.get("color", t).val().toUpperCase()); + o.setColor(color); + } catch (IllegalArgumentException ex) { + throw new CREIllegalArgumentException("Invalid chat color: \"" + + dis.get("color", t).val() + "\"", t); + } + } return CVoid.VOID; } @@ -763,15 +776,16 @@ public Integer[] numArgs() { @Override public String docs() { return "void {teamName, array, [scoreboard] | teamName, displayname, [scoreboard]}" - + " Sets the display name, prefix, and/or suffix of the given team." + + " Sets the display name, color, prefix, and/or suffix of the given team." + " If arg 2 is not an array, it is assumed to be the displayname," - + " otherwise arg 2 should be an array with keys 'displayname', 'prefix'," + + " otherwise arg 2 should be an array with keys 'displayname', 'color', 'prefix'," + " and/or 'suffix', affecting their respective properties." - + " If the prefix, suffix, or displayname is too long, a LengthException will be thrown." + + " ---- If the prefix, suffix, or displayname is too long, a LengthException will be thrown." + " The max length may differ based on server implementation," + " but will probably be 64, 64, 128 respectively." + " Null name resets it to the actual name, and null prefix or suffix removes it from" - + " all displays. " + DEF_MSG; + + " all displays. Color can be one of " + + StringUtils.Join(MCChatColor.values(), ", ", " or ") + ". " + DEF_MSG; } @Override @@ -886,7 +900,8 @@ public Integer[] numArgs() { @Override public String docs() { return "array {player, [scoreboard]} Returns a team array for this player, or null if not in a team." - + " Contains the keys name, displayname, prefix, suffix, size, options, and players." + DEF_MSG; + + " Contains the keys name, displayname, color, prefix, suffix, size, options, and players." + + DEF_MSG; } @Override From 60036af6ac9afec42e6686ba19573cffa74d81c9 Mon Sep 17 00:00:00 2001 From: PseudoKnight Date: Wed, 31 Oct 2018 01:49:54 -0700 Subject: [PATCH 05/10] Fix furnace recipes --- .../laytonsmith/abstraction/bukkit/BukkitMCFurnaceRecipe.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCFurnaceRecipe.java b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCFurnaceRecipe.java index 8b91e466b..2012145fb 100644 --- a/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCFurnaceRecipe.java +++ b/src/main/java/com/laytonsmith/abstraction/bukkit/BukkitMCFurnaceRecipe.java @@ -44,7 +44,7 @@ public MCItemStack getInput() { @Override public void setInput(MCItemStack input) { - fr.setInput(((ItemStack) input.getHandle()).getData()); + fr.setInput(((ItemStack) input.getHandle()).getType()); } @Override From d68b63dcc124274224a7b26e13b8db00d11f07e6 Mon Sep 17 00:00:00 2001 From: LadyCailin Date: Tue, 6 Nov 2018 09:43:48 +0100 Subject: [PATCH 06/10] Add ByteArrayUtils class --- .../PureUtilities/Common/ByteArrayUtils.java | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java diff --git a/src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java b/src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java new file mode 100644 index 000000000..ed528f1a7 --- /dev/null +++ b/src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java @@ -0,0 +1,67 @@ +package com.laytonsmith.PureUtilities.Common; + +/** + * + * @author Cailin + */ +public class ByteArrayUtils { + private final boolean useUpper; + private final String middleUpper = " X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF "; + private final String middleLower = " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf "; + /** + * Creates a new ByteArrayUtils object with default options + */ + public ByteArrayUtils() { + useUpper = true; + } + + public ByteArrayUtils(boolean useUpperCase) { + this.useUpper = useUpperCase; + } + public String baToHexTable(byte [] ba) { + StringBuilder b = new StringBuilder(); + StringBuilder c1 = new StringBuilder(); + StringBuilder c2 = new StringBuilder(); + b.append("Address |").append(useUpper ? middleUpper : middleLower).append("| ASCII |\n"); + for(int i = 0; i < ba.length + (16 - (ba.length % 16)); i++) { + if(i % 16 == 0) { + // First line, the address + b.append(String.format("0x%07" + (useUpper?"X":"x"), i / 16)).append(useUpper ? "X " : "x "); + } + if(i < ba.length) { + byte by = ba[i]; + c1.append(toHex(by)).append(" "); + char w = '.'; + if(by != 0) { + w = (char) by; + } + if(Character.isISOControl(by)) { + w = '.'; + } + c2.append(w); + } else { + c1.append(".. "); + c2.append("."); + } + if(i % 16 == 15) { + // End of line, construct line + b.append("| ").append(c1.toString()).append("| ") + .append(c2.toString()).append(" |\n"); + c1 = new StringBuilder(); + c2 = new StringBuilder(); + } + } + return b.toString(); + } + + private final static char[] upperHexArray = "0123456789ABCDEF".toCharArray(); + private final static char[] lowerHexArray = "0123456789abcdef".toCharArray(); + private String toHex(byte b) { + int v = b & 0xFF; + if(useUpper) { + return new String(new char[]{upperHexArray[v >>> 4], upperHexArray[v & 0x0F]}); + } else { + return new String(new char[]{lowerHexArray[v >>> 4], lowerHexArray[v & 0x0F]}); + } + } +} From 52dd0c479f8fbd9aca4800f60837cbc58d03859f Mon Sep 17 00:00:00 2001 From: LadyCailin Date: Tue, 6 Nov 2018 09:51:03 +0100 Subject: [PATCH 07/10] Re-add array_subset_of, which disappeared somehow --- .../PureUtilities/Common/ByteArrayUtils.java | 92 +++++++------- .../core/functions/ArrayHandling.java | 112 ++++++++++++++++++ 2 files changed, 160 insertions(+), 44 deletions(-) diff --git a/src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java b/src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java index ed528f1a7..cd34d2c7e 100644 --- a/src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java +++ b/src/main/java/com/laytonsmith/PureUtilities/Common/ByteArrayUtils.java @@ -5,9 +5,11 @@ * @author Cailin */ public class ByteArrayUtils { + private final boolean useUpper; - private final String middleUpper = " X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF "; - private final String middleLower = " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf "; + private static final String MIDDLE_UPPER = " X0 X1 X2 X3 X4 X5 X6 X7 X8 X9 XA XB XC XD XE XF "; + private static final String MIDDLE_LOWER = " x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xa xb xc xd xe xf "; + /** * Creates a new ByteArrayUtils object with default options */ @@ -18,50 +20,52 @@ public ByteArrayUtils() { public ByteArrayUtils(boolean useUpperCase) { this.useUpper = useUpperCase; } - public String baToHexTable(byte [] ba) { - StringBuilder b = new StringBuilder(); - StringBuilder c1 = new StringBuilder(); - StringBuilder c2 = new StringBuilder(); - b.append("Address |").append(useUpper ? middleUpper : middleLower).append("| ASCII |\n"); - for(int i = 0; i < ba.length + (16 - (ba.length % 16)); i++) { - if(i % 16 == 0) { - // First line, the address - b.append(String.format("0x%07" + (useUpper?"X":"x"), i / 16)).append(useUpper ? "X " : "x "); - } - if(i < ba.length) { - byte by = ba[i]; - c1.append(toHex(by)).append(" "); - char w = '.'; - if(by != 0) { - w = (char) by; - } - if(Character.isISOControl(by)) { - w = '.'; - } - c2.append(w); - } else { - c1.append(".. "); - c2.append("."); - } - if(i % 16 == 15) { - // End of line, construct line - b.append("| ").append(c1.toString()).append("| ") - .append(c2.toString()).append(" |\n"); - c1 = new StringBuilder(); - c2 = new StringBuilder(); - } - } - return b.toString(); - } - private final static char[] upperHexArray = "0123456789ABCDEF".toCharArray(); - private final static char[] lowerHexArray = "0123456789abcdef".toCharArray(); - private String toHex(byte b) { - int v = b & 0xFF; + public String baToHexTable(byte[] ba) { + StringBuilder b = new StringBuilder(); + StringBuilder c1 = new StringBuilder(); + StringBuilder c2 = new StringBuilder(); + b.append("Address |").append(useUpper ? MIDDLE_UPPER : MIDDLE_LOWER).append("| ASCII |\n"); + for(int i = 0; i < ba.length + (16 - (ba.length % 16)); i++) { + if(i % 16 == 0) { + // First line, the address + b.append(String.format("0x%07" + (useUpper ? "X" : "x"), i / 16)).append(useUpper ? "X " : "x "); + } + if(i < ba.length) { + byte by = ba[i]; + c1.append(toHex(by)).append(" "); + char w = '.'; + if(by != 0) { + w = (char) by; + } + if(Character.isISOControl(by)) { + w = '.'; + } + c2.append(w); + } else { + c1.append(".. "); + c2.append("."); + } + if(i % 16 == 15) { + // End of line, construct line + b.append("| ").append(c1.toString()).append("| ") + .append(c2.toString()).append(" |\n"); + c1 = new StringBuilder(); + c2 = new StringBuilder(); + } + } + return b.toString(); + } + + private static final char[] UPPER_HEX_ARRAY = "0123456789ABCDEF".toCharArray(); + private static final char[] LOWER_HEX_ARRAY = "0123456789abcdef".toCharArray(); + + private String toHex(byte b) { + int v = b & 0xFF; if(useUpper) { - return new String(new char[]{upperHexArray[v >>> 4], upperHexArray[v & 0x0F]}); + return new String(new char[]{UPPER_HEX_ARRAY[v >>> 4], UPPER_HEX_ARRAY[v & 0x0F]}); } else { - return new String(new char[]{lowerHexArray[v >>> 4], lowerHexArray[v & 0x0F]}); + return new String(new char[]{LOWER_HEX_ARRAY[v >>> 4], LOWER_HEX_ARRAY[v & 0x0F]}); } - } + } } diff --git a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java index 69f780c6f..5bff7ce14 100644 --- a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java +++ b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java @@ -3208,7 +3208,119 @@ public ExampleScript[] examples() throws ConfigCompileException { }; } + @api + public static class array_subset_of extends AbstractFunction { + @Override + public Version since() { + return CHVersion.V3_3_2; + } + + @Override + public String getName() { + return "array_subset_of"; + } + + @Override + public Integer[] numArgs() { + return new Integer[]{2}; + } + + @Override + public Class[] thrown() { + return new Class[]{CREIllegalArgumentException.class}; + } + + @Override + public String docs() { + return "boolean {array, array} " + + "Returns true if first array is a subset of second array."; + } + + @Override + public boolean isRestricted() { + return false; + } + + @Override + public Boolean runAsync() { + return null; + } + + @Override + public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { + Construct constA = args[0]; + Construct constB = args[1]; + if(!(constA instanceof CArray)) { + throw new CREIllegalArgumentException("Expecting an array, but received " + constA, t); + } + if(!(constB instanceof CArray)) { + throw new CREIllegalArgumentException("Expecting an array, but received " + constB, t); + } + return CBoolean.get(subsetOf(constA, constB, t)); + } + + @Override + public ExampleScript[] examples() throws ConfigCompileException { + return new ExampleScript[]{ + new ExampleScript("Basic usage", + "@arrayA = array(0, 1)\n" + + "@arrayB = array(0, 1, 5, 9)\n" + + "array_subset_of(@arrayA, @arrayB)"), + new ExampleScript("Basic usage", + "@arrayA = array(0, 1)\n" + + "@arrayB = array(0, 2, 5, 9)\n" + + "array_subset_of(@arrayA, @arrayB)"), + new ExampleScript("Mix array", + "@arrayA = array(a: 1, b: array(one, two))\n" + + "@arrayB = array(a: 1, b: array(one, two, three), c: 3)\n" + + "array_subset_of(@arrayA, @arrayB)"), + new ExampleScript("Mix array", + "@arrayA = array(a: 1, b: array(one, two))\n" + + "@arrayB = array(a: 1, b: array(two, one, three), c: 3)\n" + + "array_subset_of(@arrayA, @arrayB)") + }; + } + + public boolean subsetOf(Construct constA, Construct constB, Target t) { + if(constA.getCType() != constB.getCType()) { + return false; + } + if(constA instanceof CArray) { + CArray arrA = (CArray) constA; + CArray arrB = (CArray) constB; + if(arrA.isAssociative() != arrB.isAssociative()) { + return false; + } + if(arrA.isAssociative()) { + for(String key : arrA.stringKeySet()) { + if(!arrB.containsKey(key)) { + return false; + } + Construct eltA = arrA.get(key, t); + Construct eltB = arrB.get(key, t); + if(!subsetOf(eltA, eltB, t)) { + return false; + } + } + } else { + for(int i = 0; i < arrA.size(); i++) { + if(!arrB.containsKey(i)) { + return false; + } + Construct eltA = arrA.get(i, t); + Construct eltB = arrB.get(i, t); + if(!subsetOf(eltA, eltB, t)) { + return false; + } + } + } + } else if(!equals.doEquals(constA, constB)) { + return false; + } + return true; + } + } } } From e84f42999f1cdbe9764d0665cc0a1113502f2ce8 Mon Sep 17 00:00:00 2001 From: LadyCailin Date: Tue, 6 Nov 2018 09:59:55 +0100 Subject: [PATCH 08/10] Move subset out of intersect --- .../core/functions/ArrayHandling.java | 193 +++++++++--------- 1 file changed, 97 insertions(+), 96 deletions(-) diff --git a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java index 5bff7ce14..e39b21a66 100644 --- a/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java +++ b/src/main/java/com/laytonsmith/core/functions/ArrayHandling.java @@ -3208,119 +3208,120 @@ public ExampleScript[] examples() throws ConfigCompileException { }; } - @api - public static class array_subset_of extends AbstractFunction { - @Override - public Version since() { - return CHVersion.V3_3_2; - } + } - @Override - public String getName() { - return "array_subset_of"; - } + @api + public static class array_subset_of extends AbstractFunction { - @Override - public Integer[] numArgs() { - return new Integer[]{2}; - } + @Override + public Version since() { + return CHVersion.V3_3_2; + } - @Override - public Class[] thrown() { - return new Class[]{CREIllegalArgumentException.class}; - } + @Override + public String getName() { + return "array_subset_of"; + } - @Override - public String docs() { - return "boolean {array, array} " - + "Returns true if first array is a subset of second array."; - } + @Override + public Integer[] numArgs() { + return new Integer[]{2}; + } - @Override - public boolean isRestricted() { - return false; - } + @Override + public Class[] thrown() { + return new Class[]{CREIllegalArgumentException.class}; + } - @Override - public Boolean runAsync() { - return null; + @Override + public String docs() { + return "boolean {array, array} " + + "Returns true if first array is a subset of second array."; + } + + @Override + public boolean isRestricted() { + return false; + } + + @Override + public Boolean runAsync() { + return null; + } + + @Override + public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { + Construct constA = args[0]; + Construct constB = args[1]; + if(!(constA instanceof CArray)) { + throw new CREIllegalArgumentException("Expecting an array, but received " + constA, t); } + if(!(constB instanceof CArray)) { + throw new CREIllegalArgumentException("Expecting an array, but received " + constB, t); + } + return CBoolean.get(subsetOf(constA, constB, t)); + } - @Override - public Construct exec(Target t, Environment environment, Construct... args) throws ConfigRuntimeException { - Construct constA = args[0]; - Construct constB = args[1]; - if(!(constA instanceof CArray)) { - throw new CREIllegalArgumentException("Expecting an array, but received " + constA, t); - } - if(!(constB instanceof CArray)) { - throw new CREIllegalArgumentException("Expecting an array, but received " + constB, t); - } - return CBoolean.get(subsetOf(constA, constB, t)); - } - - @Override - public ExampleScript[] examples() throws ConfigCompileException { - return new ExampleScript[]{ - new ExampleScript("Basic usage", - "@arrayA = array(0, 1)\n" - + "@arrayB = array(0, 1, 5, 9)\n" - + "array_subset_of(@arrayA, @arrayB)"), - new ExampleScript("Basic usage", - "@arrayA = array(0, 1)\n" - + "@arrayB = array(0, 2, 5, 9)\n" - + "array_subset_of(@arrayA, @arrayB)"), - new ExampleScript("Mix array", - "@arrayA = array(a: 1, b: array(one, two))\n" - + "@arrayB = array(a: 1, b: array(one, two, three), c: 3)\n" - + "array_subset_of(@arrayA, @arrayB)"), - new ExampleScript("Mix array", - "@arrayA = array(a: 1, b: array(one, two))\n" - + "@arrayB = array(a: 1, b: array(two, one, three), c: 3)\n" - + "array_subset_of(@arrayA, @arrayB)") - }; - } - - public boolean subsetOf(Construct constA, Construct constB, Target t) { - if(constA.getCType() != constB.getCType()) { + @Override + public ExampleScript[] examples() throws ConfigCompileException { + return new ExampleScript[]{ + new ExampleScript("Basic usage", + "@arrayA = array(0, 1)\n" + + "@arrayB = array(0, 1, 5, 9)\n" + + "array_subset_of(@arrayA, @arrayB)"), + new ExampleScript("Basic usage", + "@arrayA = array(0, 1)\n" + + "@arrayB = array(0, 2, 5, 9)\n" + + "array_subset_of(@arrayA, @arrayB)"), + new ExampleScript("Mix array", + "@arrayA = array(a: 1, b: array(one, two))\n" + + "@arrayB = array(a: 1, b: array(one, two, three), c: 3)\n" + + "array_subset_of(@arrayA, @arrayB)"), + new ExampleScript("Mix array", + "@arrayA = array(a: 1, b: array(one, two))\n" + + "@arrayB = array(a: 1, b: array(two, one, three), c: 3)\n" + + "array_subset_of(@arrayA, @arrayB)") + }; + } + + public boolean subsetOf(Construct constA, Construct constB, Target t) { + if(constA.getCType() != constB.getCType()) { + return false; + } + if(constA instanceof CArray) { + CArray arrA = (CArray) constA; + CArray arrB = (CArray) constB; + if(arrA.isAssociative() != arrB.isAssociative()) { return false; } - if(constA instanceof CArray) { - CArray arrA = (CArray) constA; - CArray arrB = (CArray) constB; - if(arrA.isAssociative() != arrB.isAssociative()) { - return false; + if(arrA.isAssociative()) { + for(String key : arrA.stringKeySet()) { + if(!arrB.containsKey(key)) { + return false; + } + Construct eltA = arrA.get(key, t); + Construct eltB = arrB.get(key, t); + if(!subsetOf(eltA, eltB, t)) { + return false; + } } - if(arrA.isAssociative()) { - for(String key : arrA.stringKeySet()) { - if(!arrB.containsKey(key)) { - return false; - } - Construct eltA = arrA.get(key, t); - Construct eltB = arrB.get(key, t); - if(!subsetOf(eltA, eltB, t)) { - return false; - } + } else { + for(int i = 0; i < arrA.size(); i++) { + if(!arrB.containsKey(i)) { + return false; } - } else { - for(int i = 0; i < arrA.size(); i++) { - if(!arrB.containsKey(i)) { - return false; - } - Construct eltA = arrA.get(i, t); - Construct eltB = arrB.get(i, t); - if(!subsetOf(eltA, eltB, t)) { - return false; - } + Construct eltA = arrA.get(i, t); + Construct eltB = arrB.get(i, t); + if(!subsetOf(eltA, eltB, t)) { + return false; } } - } else if(!equals.doEquals(constA, constB)) { - return false; } - return true; + } else if(!equals.doEquals(constA, constB)) { + return false; } + return true; } - } } From 4a2e6d35b12bc81cec81682a3cccf0387b7bce0b Mon Sep 17 00:00:00 2001 From: LadyCailin Date: Tue, 6 Nov 2018 17:02:12 +0100 Subject: [PATCH 09/10] Set up CI with Azure Pipelines --- azure-pipelines.yml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 azure-pipelines.yml diff --git a/azure-pipelines.yml b/azure-pipelines.yml new file mode 100644 index 000000000..7b8fc8be6 --- /dev/null +++ b/azure-pipelines.yml @@ -0,0 +1,19 @@ +# Maven +# Build your Java project and run tests with Apache Maven. +# Add steps that analyze code, save build artifacts, deploy, and more: +# https://docs.microsoft.com/azure/devops/pipelines/languages/java + +pool: + vmImage: 'Ubuntu 16.04' + +steps: +- task: Maven@3 + inputs: + mavenPomFile: 'pom.xml' + mavenOptions: '-Xmx3072m' + javaHomeOption: 'JDKVersion' + jdkVersionOption: '1.10' + jdkArchitectureOption: 'x64' + publishJUnitResults: false + testResultsFiles: '**/TEST-*.xml' + goals: 'package' From 9e883eaaf0d4728f24fdc5d4569835766176228e Mon Sep 17 00:00:00 2001 From: LadyCailin Date: Tue, 6 Nov 2018 17:07:39 +0100 Subject: [PATCH 10/10] Update azure-pipelines.yml --- azure-pipelines.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 7b8fc8be6..9f204b42c 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -12,7 +12,7 @@ steps: mavenPomFile: 'pom.xml' mavenOptions: '-Xmx3072m' javaHomeOption: 'JDKVersion' - jdkVersionOption: '1.10' + jdkVersionOption: '1.8' jdkArchitectureOption: 'x64' publishJUnitResults: false testResultsFiles: '**/TEST-*.xml'