Compare commits

..

2 Commits

Author SHA1 Message Date
acf08c7fa6 1.2.4
All checks were successful
SorceryCraft/pipeline/head This commit looks good
Optimize Packets
Allow Command Blocks to use ```/spell``` Command
Namespace Statistics
2020-03-24 09:38:29 -04:00
5552fe5cd8 Optimize Packets
Allow Command Blocks to use /spell Command
2020-03-24 09:35:42 -04:00
10 changed files with 90 additions and 30 deletions

2
API.md
View File

@ -8,7 +8,7 @@
} }
dependencies { dependencies {
modImplementation 'com.thebrokenrail:sorcerycraft:VERSION' modImplementation 'com.thebrokenrail:sorcerycraft:VERSION'
// VERSION = "<Mod Version>+<MC Version>", for example "1.2.3+20w12a" // VERSION = "<Mod Version>+<MC Version>", for example "1.2.4+20w12a"
} }
``` ```
2. Add Dependency to ```fabric.mod.json``` 2. Add Dependency to ```fabric.mod.json```

View File

@ -1,5 +1,10 @@
# Changelog # Changelog
**1.2.4**
* Optimize Packets
* Allow Command Blocks to use ```/spell``` Command
* Namespace Statistics
**1.2.3** **1.2.3**
* Tweak Cooling Spell * Tweak Cooling Spell
* Tweak Versioning * Tweak Versioning

View File

@ -10,7 +10,7 @@ org.gradle.jvmargs = -Xmx1G
fabric_loader_version = 0.7.8+build.189 fabric_loader_version = 0.7.8+build.189
# Mod Properties # Mod Properties
mod_version = 1.2.3 mod_version = 1.2.4
maven_group = com.thebrokenrail maven_group = com.thebrokenrail
archives_base_name = sorcerycraft archives_base_name = sorcerycraft

View File

@ -2,6 +2,7 @@ package com.thebrokenrail.sorcerycraft.block;
import com.thebrokenrail.sorcerycraft.SorceryCraft; import com.thebrokenrail.sorcerycraft.SorceryCraft;
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler; import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
import com.thebrokenrail.sorcerycraft.spell.util.SpellServerPlayerEntity;
import net.fabricmc.fabric.api.block.FabricBlockSettings; import net.fabricmc.fabric.api.block.FabricBlockSettings;
import net.fabricmc.fabric.api.container.ContainerProviderRegistry; import net.fabricmc.fabric.api.container.ContainerProviderRegistry;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -36,6 +37,11 @@ public class CastingTableBlock extends Block {
@Override @Override
public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) { public NamedScreenHandlerFactory createScreenHandlerFactory(BlockState state, World world, BlockPos pos) {
return new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> new CastingTableScreenHandler(i, playerInventory, ScreenHandlerContext.create(world, pos)), new TranslatableText("container." + SorceryCraft.NAMESPACE + ".casting_table")); return new SimpleNamedScreenHandlerFactory((i, playerInventory, playerEntity) -> {
if (!playerEntity.getEntityWorld().isClient()) {
((SpellServerPlayerEntity) playerEntity).sync();
}
return new CastingTableScreenHandler(i, playerInventory, ScreenHandlerContext.create(world, pos));
}, new TranslatableText("container." + SorceryCraft.NAMESPACE + ".casting_table"));
} }
} }

View File

@ -27,36 +27,41 @@ public class SpellCommand {
public static void register(CommandDispatcher<ServerCommandSource> dispatcher) { public static void register(CommandDispatcher<ServerCommandSource> dispatcher) {
dispatcher.register(CommandManager.literal("spell") dispatcher.register(CommandManager.literal("spell")
.requires(source -> source.hasPermissionLevel(4)) .requires(source -> source.hasPermissionLevel(2))
.then(CommandManager.literal("list") .then(CommandManager.literal("list")
.then(CommandManager.argument("player", EntityArgumentType.players()) .then(CommandManager.argument("player", EntityArgumentType.players())
.executes(ctx -> { .executes(ctx -> {
int i = 0;
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player"); Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
for (PlayerEntity player : players) { for (PlayerEntity player : players) {
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
Map<Identifier, Integer> spellMap = spellPlayer.getDiscoveredSpells(); Map<Identifier, Integer> spellMap = spellPlayer.getDiscoveredSpells();
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.listing_spells", player.getDisplayName(), Texts.join(spellMap.entrySet(), spell -> SpellHelper.getTranslatedSpell(spell.getKey(), spell.getValue()))), false); ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.listing_spells", player.getDisplayName(), Texts.join(spellMap.entrySet(), spell -> SpellHelper.getTranslatedSpell(spell.getKey(), spell.getValue()))), false);
i++;
} }
return 0; return i;
}) })
) )
) )
.then(CommandManager.literal("forget") .then(CommandManager.literal("forget")
.then(CommandManager.argument("player", EntityArgumentType.players()) .then(CommandManager.argument("player", EntityArgumentType.players())
.executes(ctx -> { .executes(ctx -> {
int i = 0;
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player"); Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
for (PlayerEntity player : players) { for (PlayerEntity player : players) {
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player; SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
Map<Identifier, Integer> spells = spellPlayer.getDiscoveredSpells(); Map<Identifier, Integer> spells = spellPlayer.getDiscoveredSpells();
for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) { for (Map.Entry<Identifier, Integer> entry : spells.entrySet()) {
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(entry.getKey(), entry.getValue())), true); ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(entry.getKey(), entry.getValue())), true);
i++;
} }
spellPlayer.setDiscoveredSpells(new HashMap<>()); spellPlayer.setDiscoveredSpells(new HashMap<>());
} }
return 1; return i;
}) })
.then(CommandManager.argument("spell", SpellArgumentType.spell()) .then(CommandManager.argument("spell", SpellArgumentType.spell())
.executes(ctx -> { .executes(ctx -> {
int i = 0;
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player"); Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
for (PlayerEntity player : players) { for (PlayerEntity player : players) {
Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
@ -65,10 +70,11 @@ public class SpellCommand {
if (spells.containsKey(spell)) { if (spells.containsKey(spell)) {
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(spell, spells.get(spell))), true); ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.forgotten_spell", player.getDisplayName(), SpellHelper.getTranslatedSpellChat(spell, spells.get(spell))), true);
spells.remove(spell); spells.remove(spell);
i++;
} }
spellPlayer.setDiscoveredSpells(spells); spellPlayer.setDiscoveredSpells(spells);
} }
return 1; return i;
}) })
) )
) )
@ -76,29 +82,33 @@ public class SpellCommand {
.then(CommandManager.literal("discover") .then(CommandManager.literal("discover")
.then(CommandManager.argument("player", EntityArgumentType.players()) .then(CommandManager.argument("player", EntityArgumentType.players())
.executes(ctx -> { .executes(ctx -> {
int i = 0;
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player"); Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
for (PlayerEntity player : players) { for (PlayerEntity player : players) {
Map<Identifier, Integer> spellMap = new HashMap<>(); Map<Identifier, Integer> spellMap = new HashMap<>();
Spell[] maxSpells = SpellRegistry.getMaxSpells(); Spell[] maxSpells = SpellRegistry.getMaxSpells();
for (Spell spell : maxSpells) { for (Spell spell : maxSpells) {
spellMap.put(spell.getID(), spell.getLevel()); spellMap.put(spell.getID(), spell.getLevel());
i++;
} }
SpellHelper.learnSpells(player, spellMap); SpellHelper.learnSpells(player, spellMap);
} }
return 1; return i;
}) })
.then(CommandManager.argument("spell", SpellArgumentType.spell()) .then(CommandManager.argument("spell", SpellArgumentType.spell())
.then(CommandManager.argument("level", IntegerArgumentType.integer()) .then(CommandManager.argument("level", IntegerArgumentType.integer())
.executes(ctx -> { .executes(ctx -> {
int i = 0;
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player"); Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
for (PlayerEntity player : players) { for (PlayerEntity player : players) {
Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
int level = IntegerArgumentType.getInteger(ctx, "level") - 1; int level = IntegerArgumentType.getInteger(ctx, "level") - 1;
Map<Identifier, Integer> spellMap = new HashMap<>(); Map<Identifier, Integer> spellMap = new HashMap<>();
spellMap.put(spell, level); spellMap.put(spell, level);
i++;
SpellHelper.learnSpells(player, spellMap); SpellHelper.learnSpells(player, spellMap);
} }
return 1; return i;
}) })
) )
) )
@ -109,6 +119,7 @@ public class SpellCommand {
.then(CommandManager.argument("spell", SpellArgumentType.spell()) .then(CommandManager.argument("spell", SpellArgumentType.spell())
.then(CommandManager.argument("level", IntegerArgumentType.integer()) .then(CommandManager.argument("level", IntegerArgumentType.integer())
.executes(ctx -> { .executes(ctx -> {
int i = 0;
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player"); Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
for (PlayerEntity player : players) { for (PlayerEntity player : players) {
Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
@ -122,11 +133,12 @@ public class SpellCommand {
Map<Identifier, Integer> spellMap = SpellHelper.getSpells(stack); Map<Identifier, Integer> spellMap = SpellHelper.getSpells(stack);
spellMap.put(spell, level); spellMap.put(spell, level);
i++;
SpellHelper.setSpells(stack, spellMap); SpellHelper.setSpells(stack, spellMap);
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.applied_spell", SpellHelper.getTranslatedSpell(spell, level)), true); ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.applied_spell", SpellHelper.getTranslatedSpell(spell, level)), true);
} }
return 1; return i;
}) })
) )
) )
@ -136,6 +148,7 @@ public class SpellCommand {
.then(CommandManager.argument("player", EntityArgumentType.players()) .then(CommandManager.argument("player", EntityArgumentType.players())
.then(CommandManager.argument("spell", SpellArgumentType.spell()) .then(CommandManager.argument("spell", SpellArgumentType.spell())
.executes(ctx -> { .executes(ctx -> {
int i = 0;
Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player"); Collection<ServerPlayerEntity> players = EntityArgumentType.getPlayers(ctx, "player");
for (PlayerEntity player : players) { for (PlayerEntity player : players) {
Identifier spell = SpellArgumentType.getSpell(ctx, "spell"); Identifier spell = SpellArgumentType.getSpell(ctx, "spell");
@ -150,10 +163,11 @@ public class SpellCommand {
if (spellMap.containsKey(spell)) { if (spellMap.containsKey(spell)) {
ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.removed_spell", SpellHelper.getTranslatedSpell(spell, spellMap.get(spell))), true); ctx.getSource().sendFeedback(new TranslatableText("command." + SorceryCraft.NAMESPACE + ".spell.removed_spell", SpellHelper.getTranslatedSpell(spell, spellMap.get(spell))), true);
spellMap.remove(spell); spellMap.remove(spell);
i++;
} }
SpellHelper.setSpells(stack, spellMap); SpellHelper.setSpells(stack, spellMap);
} }
return 1; return i;
}) })
) )
) )

View File

@ -28,7 +28,7 @@ import java.util.function.BiConsumer;
public class CastingTableScreenHandler extends ScreenHandler { public class CastingTableScreenHandler extends ScreenHandler {
private final Inventory inventory; private final Inventory inventory;
private final Inventory result; private final Inventory result;
private final Spell[] spells; private Spell[] spells = new Spell[0];
private final ScreenHandlerContext context; private final ScreenHandlerContext context;
private int index = 0; private int index = 0;
@ -44,21 +44,7 @@ public class CastingTableScreenHandler extends ScreenHandler {
context = blockContext; context = blockContext;
result = new CraftingResultInventory(); result = new CraftingResultInventory();
if (playerInventory.player.isCreative() ? SorceryCraft.getConfig().limitCastingTable.creative : SorceryCraft.getConfig().limitCastingTable.survival) { setSpells(playerInventory.player);
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) playerInventory.player;
Map<Identifier, Integer> spellsMap = spellPlayer.getDiscoveredSpells();
List<Spell> spellsArray = new ArrayList<>();
Spell[] allSpells = SpellRegistry.getSpells();
for (Spell spell : allSpells) {
if (spellsMap.containsKey(spell.getID()) && spellsMap.get(spell.getID()) >= spell.getLevel()) {
spellsArray.add(spell);
}
}
spells = spellsArray.toArray(new Spell[0]);
} else {
spells = SpellRegistry.getSpells();
}
addSlot(new Slot(inventory, 0, 136, 37) { addSlot(new Slot(inventory, 0, 136, 37) {
@Override @Override
@ -123,6 +109,26 @@ public class CastingTableScreenHandler extends ScreenHandler {
} }
} }
public void setSpells(PlayerEntity player) {
if (player.isCreative() ? SorceryCraft.getConfig().limitCastingTable.creative : SorceryCraft.getConfig().limitCastingTable.survival) {
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) player;
Map<Identifier, Integer> spellsMap = spellPlayer.getDiscoveredSpells();
List<Spell> spellsArray = new ArrayList<>();
Spell[] allSpells = SpellRegistry.getSpells();
for (Spell spell : allSpells) {
if (spellsMap.containsKey(spell.getID()) && spellsMap.get(spell.getID()) >= spell.getLevel()) {
spellsArray.add(spell);
}
}
spells = spellsArray.toArray(new Spell[0]);
} else {
spells = SpellRegistry.getSpells();
}
index = 0;
onContentChanged(inventory);
}
public boolean canTakeResult(PlayerEntity playerEntity) { public boolean canTakeResult(PlayerEntity playerEntity) {
return playerEntity.isCreative() || playerEntity.experienceLevel >= spells[index].getXPCost(); return playerEntity.isCreative() || playerEntity.experienceLevel >= spells[index].getXPCost();
} }

View File

@ -4,8 +4,10 @@ import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.screen.ScreenHandler;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@ -16,6 +18,7 @@ import java.util.Map;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Mixin(PlayerEntity.class) @Mixin(PlayerEntity.class)
public class MixinPlayerEntity implements SpellPlayerEntity { public class MixinPlayerEntity implements SpellPlayerEntity {
@Shadow public ScreenHandler currentScreenHandler;
// Namespace Fields // Namespace Fields
private Map<Identifier, Integer> sorceryCraftDiscoveredSpells = new HashMap<>(); private Map<Identifier, Integer> sorceryCraftDiscoveredSpells = new HashMap<>();

View File

@ -1,18 +1,24 @@
package com.thebrokenrail.sorcerycraft.mixin; package com.thebrokenrail.sorcerycraft.mixin;
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket; import com.thebrokenrail.sorcerycraft.packet.UpdateKnownSpellsS2CPacket;
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper; import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
import com.thebrokenrail.sorcerycraft.spell.util.SpellServerPlayerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.Identifier;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Map;
@SuppressWarnings("unused") @SuppressWarnings("unused")
@Mixin(ServerPlayerEntity.class) @Mixin(ServerPlayerEntity.class)
public abstract class MixinServerPlayerEntity implements SpellPlayerEntity { public abstract class MixinServerPlayerEntity extends MixinPlayerEntity implements SpellServerPlayerEntity {
@Inject(at = @At("HEAD"), method = "copyFrom") @Inject(at = @At("HEAD"), method = "copyFrom")
public void copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo info) { public void copyFrom(ServerPlayerEntity oldPlayer, boolean alive, CallbackInfo info) {
SpellPlayerEntity oldSpellPlayer = (SpellPlayerEntity) oldPlayer; SpellPlayerEntity oldSpellPlayer = (SpellPlayerEntity) oldPlayer;
@ -21,11 +27,22 @@ public abstract class MixinServerPlayerEntity implements SpellPlayerEntity {
newSpellPlayer.setDiscoveredSpells(oldSpellPlayer.getDiscoveredSpells()); newSpellPlayer.setDiscoveredSpells(oldSpellPlayer.getDiscoveredSpells());
} }
@Inject(at = @At("HEAD"), method = "playerTick") @Override
public void playerTick(CallbackInfo info) { public void setDiscoveredSpells(Map<Identifier, Integer> spells) {
super.setDiscoveredSpells(spells);
sync();
}
@Override
public void sync() {
CompoundTag tag = new CompoundTag(); CompoundTag tag = new CompoundTag();
tag.put(SpellHelper.SPELL_TAG, SpellHelper.createSpellsTag(getDiscoveredSpells())); tag.put(SpellHelper.SPELL_TAG, SpellHelper.createSpellsTag(getDiscoveredSpells()));
//noinspection ConstantConditions //noinspection ConstantConditions
UpdateKnownSpellsS2CPacket.send((ServerPlayerEntity) (Object) this, tag); UpdateKnownSpellsS2CPacket.send((ServerPlayerEntity) (Object) this, tag);
if (currentScreenHandler instanceof CastingTableScreenHandler) {
//noinspection ConstantConditions
((CastingTableScreenHandler) currentScreenHandler).setSpells((PlayerEntity) (Object) this);
}
} }
} }

View File

@ -1,6 +1,7 @@
package com.thebrokenrail.sorcerycraft.packet; package com.thebrokenrail.sorcerycraft.packet;
import com.thebrokenrail.sorcerycraft.SorceryCraft; import com.thebrokenrail.sorcerycraft.SorceryCraft;
import com.thebrokenrail.sorcerycraft.gui.CastingTableScreenHandler;
import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity; import com.thebrokenrail.sorcerycraft.spell.util.SpellPlayerEntity;
import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper; import com.thebrokenrail.sorcerycraft.spell.util.SpellHelper;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
@ -17,6 +18,9 @@ public class UpdateKnownSpellsS2CPacket {
if (context.getPlayer() != null) { if (context.getPlayer() != null) {
SpellPlayerEntity spellPlayer = (SpellPlayerEntity) context.getPlayer(); SpellPlayerEntity spellPlayer = (SpellPlayerEntity) context.getPlayer();
spellPlayer.setDiscoveredSpells(SpellHelper.getSpells(tag)); spellPlayer.setDiscoveredSpells(SpellHelper.getSpells(tag));
if (context.getPlayer().currentScreenHandler instanceof CastingTableScreenHandler) {
((CastingTableScreenHandler) context.getPlayer().currentScreenHandler).setSpells(context.getPlayer());
}
} }
} }

View File

@ -0,0 +1,5 @@
package com.thebrokenrail.sorcerycraft.spell.util;
public interface SpellServerPlayerEntity extends SpellPlayerEntity {
void sync();
}