the almighty state machine

This commit is contained in:
Bob 2024-09-08 17:45:57 +02:00
parent 49d49d47e3
commit 5d1d96e436
14 changed files with 4440 additions and 81 deletions

View File

@ -13,6 +13,7 @@ import com.hbm.packet.toserver.KeybindPacket;
import cpw.mods.fml.client.registry.ClientRegistry;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.InputEvent.KeyInputEvent;
import cpw.mods.fml.common.gameevent.InputEvent.MouseInputEvent;
import net.minecraft.client.settings.KeyBinding;
public class HbmKeybinds {
@ -55,6 +56,21 @@ public class HbmKeybinds {
ClientRegistry.registerKeyBinding(craneLoadKey);
}
@SubscribeEvent
public void mouseEvent(MouseInputEvent event) {
HbmPlayerProps props = HbmPlayerProps.getData(MainRegistry.proxy.me());
for(EnumKeybind key : EnumKeybind.values()) {
boolean last = props.getKeyPressed(key);
boolean current = MainRegistry.proxy.getIsKeyPressed(key);
if(last != current) {
PacketDispatcher.wrapper.sendToServer(new KeybindPacket(key, current));
props.setKeyPressed(key, current);
}
}
}
@SubscribeEvent
public void keyEvent(KeyInputEvent event) {
if (calculatorKey.getIsKeyPressed()) { // handle the calculator client-side only

View File

@ -19,7 +19,8 @@ public class HbmKeybindsServer {
// ITEM HANDLING
ItemStack held = player.getHeldItem();
if(held != null && held.getItem() instanceof IKeybindReceiver) {
((IKeybindReceiver) held.getItem()).handleKeybind(player, held, key, state);
IKeybindReceiver rec = (IKeybindReceiver) held.getItem();
if(rec.canHandleKeybind(player, held, key)) rec.handleKeybind(player, held, key, state);
}
}
}

View File

@ -7,5 +7,6 @@ import net.minecraft.item.ItemStack;
public interface IKeybindReceiver {
public boolean canHandleKeybind(EntityPlayer player, ItemStack stack, EnumKeybind keybind);
public void handleKeybind(EntityPlayer player, ItemStack stack, EnumKeybind keybind, boolean state);
}

View File

@ -2,6 +2,7 @@ package com.hbm.items.weapon.sedna;
import java.util.function.BiConsumer;
import com.hbm.items.weapon.sedna.ItemGunBase.LambdaContext;
import com.hbm.render.util.RenderScreenOverlay.Crosshair;
import net.minecraft.item.ItemStack;
@ -16,15 +17,17 @@ public class GunConfig {
protected int drawDuration = 0;
protected Crosshair crosshair;
/** Lambda functions for clicking shit */
protected BiConsumer<ItemStack, GunConfig> onPressPrimary;
protected BiConsumer<ItemStack, GunConfig> onPressSecondary;
protected BiConsumer<ItemStack, GunConfig> onPressTertiary;
protected BiConsumer<ItemStack, GunConfig> onPressReload;
protected BiConsumer<ItemStack, LambdaContext> onPressPrimary;
protected BiConsumer<ItemStack, LambdaContext> onPressSecondary;
protected BiConsumer<ItemStack, LambdaContext> onPressTertiary;
protected BiConsumer<ItemStack, LambdaContext> onPressReload;
/** Lambda functions for releasing the aforementioned shit */
protected BiConsumer<ItemStack, GunConfig> onReleasePrimary;
protected BiConsumer<ItemStack, GunConfig> onReleaseSecondary;
protected BiConsumer<ItemStack, GunConfig> onReleaseTertiary;
protected BiConsumer<ItemStack, GunConfig> onReleaseReload;
protected BiConsumer<ItemStack, LambdaContext> onReleasePrimary;
protected BiConsumer<ItemStack, LambdaContext> onReleaseSecondary;
protected BiConsumer<ItemStack, LambdaContext> onReleaseTertiary;
protected BiConsumer<ItemStack, LambdaContext> onReleaseReload;
/** The engine for the state machine that determines the gun's overall behavior */
protected BiConsumer<ItemStack, LambdaContext> decider;
/* GETTERS */
@ -33,15 +36,17 @@ public class GunConfig {
public int getDrawDuration(ItemStack stack) { return drawDuration; }
public Crosshair getCrosshair(ItemStack stack) { return crosshair; }
public BiConsumer<ItemStack, GunConfig> getPressPrimary(ItemStack stack) { return this.onPressPrimary; }
public BiConsumer<ItemStack, GunConfig> getPressSecondary(ItemStack stack) { return this.onPressSecondary; }
public BiConsumer<ItemStack, GunConfig> getPressTertiary(ItemStack stack) { return this.onPressTertiary; }
public BiConsumer<ItemStack, GunConfig> getPressReload(ItemStack stack) { return this.onPressReload; }
public BiConsumer<ItemStack, LambdaContext> getPressPrimary(ItemStack stack) { return this.onPressPrimary; }
public BiConsumer<ItemStack, LambdaContext> getPressSecondary(ItemStack stack) { return this.onPressSecondary; }
public BiConsumer<ItemStack, LambdaContext> getPressTertiary(ItemStack stack) { return this.onPressTertiary; }
public BiConsumer<ItemStack, LambdaContext> getPressReload(ItemStack stack) { return this.onPressReload; }
public BiConsumer<ItemStack, GunConfig> getReleasePrimary(ItemStack stack) { return this.onReleasePrimary; }
public BiConsumer<ItemStack, GunConfig> getReleaseSecondary(ItemStack stack) { return this.onReleaseSecondary; }
public BiConsumer<ItemStack, GunConfig> getReleaseTertiary(ItemStack stack) { return this.onReleaseTertiary; }
public BiConsumer<ItemStack, GunConfig> getReleaseReload(ItemStack stack) { return this.onReleaseReload; }
public BiConsumer<ItemStack, LambdaContext> getReleasePrimary(ItemStack stack) { return this.onReleasePrimary; }
public BiConsumer<ItemStack, LambdaContext> getReleaseSecondary(ItemStack stack) { return this.onReleaseSecondary; }
public BiConsumer<ItemStack, LambdaContext> getReleaseTertiary(ItemStack stack) { return this.onReleaseTertiary; }
public BiConsumer<ItemStack, LambdaContext> getReleaseReload(ItemStack stack) { return this.onReleaseReload; }
public BiConsumer<ItemStack, LambdaContext> getDecider(ItemStack stack) { return this.decider; }
/* SETTERS */
@ -50,13 +55,18 @@ public class GunConfig {
public GunConfig draw(int draw) { this.drawDuration = draw; return this; }
public GunConfig crosshair(Crosshair crosshair) { this.crosshair = crosshair; return this; }
public GunConfig pp(BiConsumer<ItemStack, GunConfig> lambda) { this.onPressPrimary = lambda; return this; }
public GunConfig ps(BiConsumer<ItemStack, GunConfig> lambda) { this.onPressSecondary = lambda; return this; }
public GunConfig pt(BiConsumer<ItemStack, GunConfig> lambda) { this.onPressTertiary = lambda; return this; }
public GunConfig pr(BiConsumer<ItemStack, GunConfig> lambda) { this.onPressReload = lambda; return this; }
//press
public GunConfig pp(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressPrimary = lambda; return this; }
public GunConfig ps(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressSecondary = lambda; return this; }
public GunConfig pt(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressTertiary = lambda; return this; }
public GunConfig pr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onPressReload = lambda; return this; }
public GunConfig rp(BiConsumer<ItemStack, GunConfig> lambda) { this.onReleasePrimary = lambda; return this; }
public GunConfig rs(BiConsumer<ItemStack, GunConfig> lambda) { this.onReleaseSecondary = lambda; return this; }
public GunConfig rt(BiConsumer<ItemStack, GunConfig> lambda) { this.onReleaseTertiary = lambda; return this; }
public GunConfig rr(BiConsumer<ItemStack, GunConfig> lambda) { this.onReleaseReload = lambda; return this; }
//release
public GunConfig rp(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleasePrimary = lambda; return this; }
public GunConfig rs(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseSecondary = lambda; return this; }
public GunConfig rt(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseTertiary = lambda; return this; }
public GunConfig rr(BiConsumer<ItemStack, LambdaContext> lambda) { this.onReleaseReload = lambda; return this; }
//decider
public GunConfig decider(BiConsumer<ItemStack, LambdaContext> lambda) { this.decider = lambda; return this; }
}

View File

@ -1,6 +1,8 @@
package com.hbm.items.weapon.sedna;
import com.hbm.items.ModItems;
import com.hbm.items.weapon.sedna.factory.GunStateDecider;
import com.hbm.items.weapon.sedna.factory.Lego;
import com.hbm.items.weapon.sedna.mags.MagazineRevolverDrum;
import com.hbm.lib.RefStrings;
import com.hbm.main.MainRegistry;
@ -19,7 +21,12 @@ public class GunFactory {
ModItems.gun_debug = new ItemGunBase(new GunConfig()
.dura(600).draw(15).crosshair(Crosshair.L_CLASSIC)
.rec(new Receiver()
.dmg(10F).delay(10).mag(new MagazineRevolverDrum(0, 6).addConfigs(ammo_debug)))
.dmg(10F).delay(10).mag(new MagazineRevolverDrum(0, 6).addConfigs(ammo_debug))
.canFire(Lego.LAMBDA_DEBUG_CAN_FIRE).fire(Lego.LAMBDA_DEBUG_FIRE))
.pr(Lego.LAMBDA_STANDARD_RELOAD)
.pp(Lego.LAMBDA_STANDARD_FIRE)
.pt(Lego.LAMBDA_TOGGLE_AIM)
.decider(GunStateDecider.LAMBDA_STANDARD_DECIDER)
).setUnlocalizedName("gun_debug").setCreativeTab(MainRegistry.weaponTab).setTextureName(RefStrings.MODID + ":gun_darter");
}
}

View File

@ -2,6 +2,7 @@ package com.hbm.items.weapon.sedna;
import com.hbm.handler.HbmKeybinds.EnumKeybind;
import com.hbm.items.IKeybindReceiver;
import com.hbm.main.MainRegistry;
import com.hbm.util.EnumUtil;
import net.minecraft.entity.Entity;
@ -9,17 +10,22 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
public class ItemGunBase extends Item implements IKeybindReceiver {
public static final String KEY_DRAWN = "drawn";
public static final String KEY_AIMING = "aiming";
public static final String KEY_TIMER = "timer";
public static final String KEY_STATE = "state";
public static final String KEY_PRIMARY = "mouse1";
public static final String KEY_SECONDARY = "mouse2";
public static final String KEY_TERTIARY = "mouse3";
public static final String KEY_RELOAD = "reload";
public static float prevAimingProgress;
public static float aimingProgress;
/** NEVER ACCESS DIRECTLY - USE GETTER */
private GunConfig config_DNA;
@ -41,40 +47,62 @@ public class ItemGunBase extends Item implements IKeybindReceiver {
RELOADING //gun is currently reloading
}
@Override
public boolean canHandleKeybind(EntityPlayer player, ItemStack stack, EnumKeybind keybind) {
return keybind == EnumKeybind.GUN_PRIMARY || keybind == EnumKeybind.GUN_SECONDARY || keybind == EnumKeybind.GUN_TERTIARY || keybind == EnumKeybind.RELOAD;
}
@Override
public void handleKeybind(EntityPlayer player, ItemStack stack, EnumKeybind keybind, boolean newState) {
GunConfig config = getConfig(stack);
LambdaContext ctx = new LambdaContext(config, player);
if(keybind == EnumKeybind.GUN_PRIMARY && newState && !getPrimary(stack)) { if(config.getPressPrimary(stack) != null) config.getPressPrimary(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.GUN_PRIMARY && !newState && getPrimary(stack)) { if(config.getReleasePrimary(stack) != null) config.getReleasePrimary(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.GUN_SECONDARY && newState && !getSecondary(stack)) { if(config.getPressSecondary(stack) != null) config.getPressSecondary(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.GUN_SECONDARY && !newState && getSecondary(stack)) { if(config.getReleaseSecondary(stack) != null) config.getReleaseSecondary(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.GUN_TERTIARY && newState && !getTertiary(stack)) { if(config.getPressTertiary(stack) != null) config.getPressTertiary(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.GUN_TERTIARY && !newState && getTertiary(stack)) { if(config.getReleaseTertiary(stack) != null) config.getReleaseTertiary(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.RELOAD && newState && !getReloadKey(stack)) { if(config.getPressReload(stack) != null) config.getPressReload(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.RELOAD && !newState && getReloadKey(stack)) { if(config.getReleaseReload(stack) != null) config.getReleaseReload(stack).accept(stack, config); return; }
if(keybind == EnumKeybind.GUN_PRIMARY && newState && !getPrimary(stack)) { if(config.getPressPrimary(stack) != null) config.getPressPrimary(stack).accept(stack, ctx); this.setPrimary(stack, newState); return; }
if(keybind == EnumKeybind.GUN_PRIMARY && !newState && getPrimary(stack)) { if(config.getReleasePrimary(stack) != null) config.getReleasePrimary(stack).accept(stack, ctx); this.setPrimary(stack, newState); return; }
if(keybind == EnumKeybind.GUN_SECONDARY && newState && !getSecondary(stack)) { if(config.getPressSecondary(stack) != null) config.getPressSecondary(stack).accept(stack, ctx); this.setSecondary(stack, newState); return; }
if(keybind == EnumKeybind.GUN_SECONDARY && !newState && getSecondary(stack)) { if(config.getReleaseSecondary(stack) != null) config.getReleaseSecondary(stack).accept(stack, ctx); this.setSecondary(stack, newState); return; }
if(keybind == EnumKeybind.GUN_TERTIARY && newState && !getTertiary(stack)) { if(config.getPressTertiary(stack) != null) config.getPressTertiary(stack).accept(stack, ctx); this.setTertiary(stack, newState); return; }
if(keybind == EnumKeybind.GUN_TERTIARY && !newState && getTertiary(stack)) { if(config.getReleaseTertiary(stack) != null) config.getReleaseTertiary(stack).accept(stack, ctx); this.setTertiary(stack, newState); return; }
if(keybind == EnumKeybind.RELOAD && newState && !getReloadKey(stack)) { if(config.getPressReload(stack) != null) config.getPressReload(stack).accept(stack, ctx); this.setReloadKey(stack, newState); return; }
if(keybind == EnumKeybind.RELOAD && !newState && getReloadKey(stack)) { if(config.getReleaseReload(stack) != null) config.getReleaseReload(stack).accept(stack, ctx); this.setReloadKey(stack, newState); return; }
}
@Override
public void onUpdate(ItemStack stack, World world, Entity entity, int slot, boolean isHeld) {
if(world.isRemote) return;
if(!(entity instanceof EntityPlayer)) return;
EntityPlayer player = (EntityPlayer) entity;
if(world.isRemote) {
if(isHeld && player == MainRegistry.proxy.me()) {
prevAimingProgress = aimingProgress;
boolean aiming = this.getIsAiming(stack);
float aimSpeed = 0.25F;
if(aiming && aimingProgress < 1F) aimingProgress += aimSpeed;
if(!aiming && aimingProgress > 0F) aimingProgress -= aimSpeed;
aimingProgress = MathHelper.clamp_float(aimingProgress, 0F, 1F);
}
return;
}
GunConfig config = this.getConfig(stack);
if(!isHeld) {
this.setState(stack, GunState.DRAWING);
this.setTimer(stack, config.getDrawDuration(stack));
this.setIsAiming(stack, false);
return;
}
int timer = this.getTimer(stack);
if(timer > 0) this.setTimer(stack, timer - 1);
if(timer <= 1) nextState();
if(timer <= 1) nextState(player, stack);
}
public void nextState() {
// run the decider
public void nextState(EntityPlayer player, ItemStack stack) {
GunConfig cfg = this.getConfig(stack);
cfg.getDecider(stack).accept(stack, new LambdaContext(cfg, player));
}
// GUN DRAWN //
@ -88,6 +116,10 @@ public class ItemGunBase extends Item implements IKeybindReceiver {
// GUN STATE //
public static GunState getState(ItemStack stack) { return EnumUtil.grabEnumSafely(GunState.class, getValueByte(stack, KEY_STATE)); }
public static void setState(ItemStack stack, GunState value) { setValueByte(stack, KEY_STATE, (byte) value.ordinal()); }
// GUN AIMING //
public static boolean getIsAiming(ItemStack stack) { return getValueBool(stack, KEY_AIMING); }
public static void setIsAiming(ItemStack stack, boolean value) { setValueBool(stack, KEY_AIMING, value); }
// BUTTON STATES //
public static boolean getPrimary(ItemStack stack) { return getValueBool(stack, KEY_PRIMARY); }
@ -101,12 +133,23 @@ public class ItemGunBase extends Item implements IKeybindReceiver {
/// UTIL ///
public static int getValueInt(ItemStack stack, String name) { if(stack.hasTagCompound()) stack.getTagCompound().getInteger(name); return 0; }
public static int getValueInt(ItemStack stack, String name) { if(stack.hasTagCompound()) return stack.getTagCompound().getInteger(name); return 0; }
public static void setValueInt(ItemStack stack, String name, int value) { if(!stack.hasTagCompound()) stack.stackTagCompound = new NBTTagCompound(); stack.getTagCompound().setInteger(name, value); }
public static byte getValueByte(ItemStack stack, String name) { if(stack.hasTagCompound()) stack.getTagCompound().getByte(name); return 0; }
public static byte getValueByte(ItemStack stack, String name) { if(stack.hasTagCompound()) return stack.getTagCompound().getByte(name); return 0; }
public static void setValueByte(ItemStack stack, String name, byte value) { if(!stack.hasTagCompound()) stack.stackTagCompound = new NBTTagCompound(); stack.getTagCompound().setByte(name, value); }
public static boolean getValueBool(ItemStack stack, String name) { if(stack.hasTagCompound()) stack.getTagCompound().getBoolean(name); return false; }
public static boolean getValueBool(ItemStack stack, String name) { if(stack.hasTagCompound()) return stack.getTagCompound().getBoolean(name); return false; }
public static void setValueBool(ItemStack stack, String name, boolean value) { if(!stack.hasTagCompound()) stack.stackTagCompound = new NBTTagCompound(); stack.getTagCompound().setBoolean(name, value); }
/** Wrapper for extra context used in most Consumer lambdas which are part of the guncfg */
public static class LambdaContext {
public final GunConfig config;
public final EntityPlayer player;
public LambdaContext(GunConfig config, EntityPlayer player) {
this.config = config;
this.player = player;
}
}
}

View File

@ -1,24 +1,47 @@
package com.hbm.items.weapon.sedna;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import com.hbm.handler.CasingEjector;
import com.hbm.items.weapon.sedna.ItemGunBase.LambdaContext;
import com.hbm.items.weapon.sedna.mags.IMagazine;
import net.minecraft.item.ItemStack;
public class Receiver {
protected float baseDamage;
protected int delayAfterFire;
protected int roundsPerCycle = 1;
protected boolean refireOnHold = false;
protected int burstSize = 1;
protected int delayAfterBurst = 0;
protected CasingEjector ejector = null;
protected int reloadDuration;
protected IMagazine magazine;
protected BiFunction<ItemStack, LambdaContext, Boolean> canFire;
protected BiConsumer<ItemStack, LambdaContext> onFire;
/* GETTERS */
public float getBaseDamage(ItemStack stack) { return this.baseDamage; }
public int getDelayAfterFire(ItemStack stack) { return this.delayAfterFire; }
public int getRoundsPerCycle(ItemStack stack) { return this.roundsPerCycle; }
public boolean getRefireOnHold(ItemStack stack) { return this.refireOnHold; }
public CasingEjector getEjector(ItemStack stack) { return this.ejector; }
public int getReloadDuration(ItemStack stack) { return this.reloadDuration; }
public IMagazine getMagazine(ItemStack stack) { return this.magazine; }
public BiFunction<ItemStack, LambdaContext, Boolean> getCanFire(ItemStack stack) { return this.canFire; }
public BiConsumer<ItemStack, LambdaContext> getOnFire(ItemStack stack) { return this.onFire; }
public Receiver dmg(float dmg) { this.baseDamage = dmg; return this; }
public Receiver delay(int delay) { this.delayAfterFire = delay; return this; }
public Receiver rounds(int rounds) { this.roundsPerCycle = rounds; return this; }
public Receiver auto(boolean auto) { this.refireOnHold = auto; return this; }
public Receiver burst(int size, int delay) { this.burstSize = size; this.delayAfterBurst = delay; return this; }
public Receiver burst(CasingEjector ejector) { this.ejector = ejector; return this; }
public Receiver mag(IMagazine magazine) { this.magazine = magazine; return this; }
/* SETTERS */
public Receiver dmg(float dmg) { this.baseDamage = dmg; return this; }
public Receiver delay(int delay) { this.delayAfterFire = delay; return this; }
public Receiver rounds(int rounds) { this.roundsPerCycle = rounds; return this; }
public Receiver auto(boolean auto) { this.refireOnHold = auto; return this; }
public Receiver burst(CasingEjector ejector) { this.ejector = ejector; return this; }
public Receiver reload(int delay) { this.reloadDuration = delay; return this; }
public Receiver mag(IMagazine magazine) { this.magazine = magazine; return this; }
public Receiver canFire(BiFunction<ItemStack, LambdaContext, Boolean> lambda) { this.canFire = lambda; return this; }
public Receiver fire(BiConsumer<ItemStack, LambdaContext> lambda) { this.onFire = lambda; return this; }
}

View File

@ -0,0 +1,89 @@
package com.hbm.items.weapon.sedna.factory;
import java.util.function.BiConsumer;
import java.util.function.BooleanSupplier;
import com.hbm.items.weapon.sedna.GunConfig;
import com.hbm.items.weapon.sedna.ItemGunBase;
import com.hbm.items.weapon.sedna.Receiver;
import com.hbm.items.weapon.sedna.ItemGunBase.GunState;
import com.hbm.items.weapon.sedna.ItemGunBase.LambdaContext;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
public class GunStateDecider {
/**
* The meat and bones of the gun system's state machine.
* This standard decider can handle guns with an automatic primary receiver, as well as one receiver's reloading state.
* It supports draw delays as well as semi and auto fire
*/
public static BiConsumer<ItemStack, LambdaContext> LAMBDA_STANDARD_DECIDER = (stack, ctx) -> {
GunState lastState = ItemGunBase.getState(stack);
deciderStandardFinishDraw(stack, lastState);
deciderStandardReload(stack, ctx, lastState, 0);
deciderAutoRefire(stack, ctx, lastState, 0, () -> { return ItemGunBase.getPrimary(stack); });
};
/** Transitions the gun from DRAWING to IDLE */
public static void deciderStandardFinishDraw(ItemStack stack, GunState lastState) {
//transition to idle
if(lastState == GunState.DRAWING) {
ItemGunBase.setState(stack, GunState.IDLE);
ItemGunBase.setTimer(stack, 0);
}
}
/** Triggers a reload action on the first receiver. If the mag is not full and reloading is still possible, set to RELOADING, otherwise IDLE */
public static void deciderStandardReload(ItemStack stack, LambdaContext ctx, GunState lastState, int recIndex) {
if(lastState == GunState.RELOADING) {
EntityPlayer player = ctx.player;
GunConfig cfg = ctx.config;
Receiver rec = cfg.getReceivers(stack)[recIndex];
rec.getMagazine(stack).reloadAction(stack, player);
//if after reloading the gun can still reload, assume a tube mag and resume reloading
if(cfg.getReceivers(stack)[recIndex].getMagazine(stack).canReload(stack, player)) {
ItemGunBase.setState(stack, GunState.RELOADING);
ItemGunBase.setTimer(stack, cfg.getReceivers(stack)[recIndex].getReloadDuration(stack));
//if no more reloading can be done, go idle
} else {
ItemGunBase.setState(stack, GunState.IDLE);
ItemGunBase.setTimer(stack, 0);
}
}
}
/** Triggers a re-fire of the primary if the fire delay has expired, the left mouse button is down and re-firing is enabled, otherwise switches to IDLE */
public static void deciderAutoRefire(ItemStack stack, LambdaContext ctx, GunState lastState, int recIndex, BooleanSupplier refireCondition) {
if(lastState == GunState.JUST_FIRED) {
GunConfig cfg = ctx.config;
Receiver rec = cfg.getReceivers(stack)[recIndex];
//if the gun supports re-fire (i.e. if it's an auto)
if(rec.getRefireOnHold(stack) && refireCondition.getAsBoolean()) {
//if there's a bullet loaded, fire again
if(rec.getCanFire(stack).apply(stack, ctx)) {
rec.getOnFire(stack).accept(stack, ctx);
ItemGunBase.setState(stack, GunState.JUST_FIRED);
ItemGunBase.setTimer(stack, rec.getDelayAfterFire(stack));
//if not, revert to idle
} else {
ItemGunBase.setState(stack, GunState.IDLE);
ItemGunBase.setTimer(stack, 0);
}
//if not, go idle
} else {
ItemGunBase.setState(stack, GunState.IDLE);
ItemGunBase.setTimer(stack, 0);
}
}
}
}

View File

@ -0,0 +1,57 @@
package com.hbm.items.weapon.sedna.factory;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import com.hbm.items.weapon.sedna.ItemGunBase;
import com.hbm.items.weapon.sedna.ItemGunBase.GunState;
import com.hbm.items.weapon.sedna.ItemGunBase.LambdaContext;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
/**
* "LEGO" - i.e. standardized building blocks which can be used to set up gun configs easily.
*
* @author hbm
*/
public class Lego {
/**
* If IDLE and the mag of receiver 0 can be loaded, set state to RELOADING. Used by keybinds. */
public static BiConsumer<ItemStack, LambdaContext> LAMBDA_STANDARD_RELOAD = (stack, ctx) -> {
if(ItemGunBase.getState(stack) == GunState.IDLE && ctx.config.getReceivers(stack)[0].getMagazine(stack).canReload(stack, ctx.player)) {
ItemGunBase.setState(stack, GunState.RELOADING);
ItemGunBase.setTimer(stack, ctx.config.getReceivers(stack)[0].getReloadDuration(stack));
}
};
/**
* If IDLE and ammo is loaded, fire and set to JUST_FIRED. */
public static BiConsumer<ItemStack, LambdaContext> LAMBDA_STANDARD_FIRE = (stack, ctx) -> {
if(ItemGunBase.getState(stack) == GunState.IDLE && ctx.config.getReceivers(stack)[0].getCanFire(stack).apply(stack, ctx)) {
ItemGunBase.setState(stack, GunState.JUST_FIRED);
ItemGunBase.setTimer(stack, ctx.config.getReceivers(stack)[0].getDelayAfterFire(stack));
ctx.config.getReceivers(stack)[0].getOnFire(stack).accept(stack, ctx);
}
};
/** Toggles isAiming. Used by keybinds. */
public static BiConsumer<ItemStack, LambdaContext> LAMBDA_TOGGLE_AIM = (stack, ctx) -> { ItemGunBase.setIsAiming(stack, !ItemGunBase.getIsAiming(stack)); };
/** Returns true if the mag has ammo in it. Used by keybind functions on whether to fire, and deciders on whether to trigger a refire, */
public static BiFunction<ItemStack, LambdaContext, Boolean> LAMBDA_STANDARD_CAN_FIRE = (stack, ctx) -> { return ctx.config.getReceivers(stack)[0].getMagazine(stack).getAmount(stack) > 0; };
/** JUMPER - bypasses mag testing and just allows constant fire */
public static BiFunction<ItemStack, LambdaContext, Boolean> LAMBDA_DEBUG_CAN_FIRE = (stack, ctx) -> { return true; };
/** simply plays a sound to indicate that the keybind has triggered */
public static BiConsumer<ItemStack, LambdaContext> LAMBDA_DEBUG_FIRE = (stack, ctx) -> {
EntityPlayer player = ctx.player;
player.worldObj.playSoundEffect(player.posX, player.posY, player.posZ, "hbm:weapon.shotgunShoot", 1F, 1F);
};
}

View File

@ -5,7 +5,6 @@ import java.util.List;
import com.hbm.items.weapon.sedna.BulletConfig;
import com.hbm.items.weapon.sedna.ItemGunBase;
import com.hbm.items.weapon.sedna.Receiver;
import net.minecraft.item.ItemStack;
@ -21,7 +20,6 @@ public abstract class MagazineStandardBase implements IMagazine {
public int index;
/** How much ammo this mag can hold */
public int capacity;
public Receiver parent;
public MagazineStandardBase(int index, int capacity) {
this.index = index;

View File

@ -2,6 +2,7 @@ package com.hbm.render.item.weapon.sedna;
import org.lwjgl.opengl.GL11;
import com.hbm.items.weapon.sedna.ItemGunBase;
import com.hbm.main.ResourceManager;
import net.minecraft.client.Minecraft;
@ -9,6 +10,19 @@ import net.minecraft.item.ItemStack;
public class ItemRenderDebug extends ItemRenderWeaponBase {
@Override
protected float getTurnMagnitude(ItemStack stack) { return ItemGunBase.getIsAiming(stack) ? 2.5F : -0.25F; }
@Override
protected void setupFirstPerson(ItemStack stack) {
GL11.glTranslated(0, 0, 1);
float offset = 0.8F;
standardAimingTransform(stack,
-1.0F * offset, -0.75F * offset, 1F * offset,
0, -3.875 / 8D, 0);
}
@Override
public void renderFirstPerson(ItemStack stack) {
@ -27,9 +41,22 @@ public class ItemRenderDebug extends ItemRenderWeaponBase {
GL11.glShadeModel(GL11.GL_FLAT);
}
@Override
protected void setupInv(ItemStack stack) {
super.setupInv(stack);
double scale = 1.25D;
GL11.glScaled(scale, scale, scale);
GL11.glRotated(25, 1, 0, 0);
GL11.glRotated(45, 0, 1, 0);
}
@Override
public void renderOther(ItemStack stack, ItemRenderType type) {
GL11.glRotated(90, 0, 1, 0);
GL11.glEnable(GL11.GL_LIGHTING);
GL11.glAlphaFunc(GL11.GL_GREATER, 0F);
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glShadeModel(GL11.GL_SMOOTH);
Minecraft.getMinecraft().renderEngine.bindTexture(ResourceManager.debug_gun_tex);

View File

@ -4,6 +4,8 @@ import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;
import org.lwjgl.util.glu.Project;
import com.hbm.items.weapon.sedna.ItemGunBase;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.client.Minecraft;
@ -14,7 +16,6 @@ import net.minecraft.client.renderer.OpenGlHelper;
import net.minecraft.client.renderer.RenderHelper;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.EnumAction;
import net.minecraft.item.ItemStack;
import net.minecraft.util.MathHelper;
import net.minecraftforge.client.IItemRenderer;
@ -96,62 +97,81 @@ public abstract class ItemRenderWeaponBase implements IItemRenderer {
return fov;
}
protected float getSwayMagnitude(ItemStack stack) { return 0.5F; }
protected float getSwayPeriod(ItemStack stack) { return 0.75F; }
protected float getTurnMagnitude(ItemStack stack) { return 2.75F; }
protected void setupTransformsAndRender(ItemStack itemstack) {
protected void setupTransformsAndRender(ItemStack stack) {
Minecraft mc = Minecraft.getMinecraft();
EntityPlayer player = mc.thePlayer;
float swayMagnitude = getSwayMagnitude(stack);
float swayPeriod = getSwayPeriod(stack);
float turnMagnitude = getTurnMagnitude(stack);
//lighting setup (item lighting changes based on player rotation)
float pitch = player.prevRotationPitch + (player.rotationPitch - player.prevRotationPitch) * interp;
float yaw = player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * interp;
GL11.glPushMatrix();
GL11.glRotatef(pitch, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(player.prevRotationYaw + (player.rotationYaw - player.prevRotationYaw) * interp, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(yaw, 0.0F, 1.0F, 0.0F);
RenderHelper.enableStandardItemLighting();
GL11.glPopMatrix();
//floppyness
EntityPlayerSP entityplayersp = (EntityPlayerSP) player;
float armPitch = entityplayersp.prevRenderArmPitch + (entityplayersp.renderArmPitch - entityplayersp.prevRenderArmPitch) * interp;
float armYaw = entityplayersp.prevRenderArmYaw + (entityplayersp.renderArmYaw - entityplayersp.prevRenderArmYaw) * interp;
GL11.glRotatef((player.rotationPitch - armPitch) * 0.1F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef((player.rotationYaw - armYaw) * 0.1F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef((player.rotationPitch - armPitch) * 0.1F * turnMagnitude, 1.0F, 0.0F, 0.0F);
GL11.glRotatef((player.rotationYaw - armYaw) * 0.1F * turnMagnitude, 0.0F, 1.0F, 0.0F);
int i = mc.theWorld.getLightBrightnessForSkyBlocks(MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ), 0);
int j = i % 65536;
int k = i / 65536;
//brightness setup
int brightness = mc.theWorld.getLightBrightnessForSkyBlocks(MathHelper.floor_double(player.posX), MathHelper.floor_double(player.posY), MathHelper.floor_double(player.posZ), 0);
int j = brightness % 65536;
int k = brightness / 65536;
OpenGlHelper.setLightmapTextureCoords(OpenGlHelper.lightmapTexUnit, (float) j / 1.0F, (float) k / 1.0F);
GL11.glColor4f(1.0F, 1.0F, 1.0F, 1.0F);
if(itemstack != null) {
int l = itemstack.getItem().getColorFromItemStack(itemstack, 0);
float r = (float) (l >> 16 & 255) / 255.0F;
float g = (float) (l >> 8 & 255) / 255.0F;
float b = (float) (l & 255) / 255.0F;
GL11.glColor4f(r, g, b, 1.0F);
}
float f8;
float f13;
//color setup
int color = stack.getItem().getColorFromItemStack(stack, 0);
float r = (float) (color >> 16 & 255) / 255.0F;
float g = (float) (color >> 8 & 255) / 255.0F;
float b = (float) (color & 255) / 255.0F;
GL11.glColor4f(r, g, b, 1.0F);
GL11.glPushMatrix();
f13 = 0.8F;
//swing
float swing = player.getSwingProgress(interp);
float swingZ = MathHelper.sin(swing * (float) Math.PI);
float swingX = MathHelper.sin(MathHelper.sqrt_float(swing) * (float) Math.PI);
GL11.glTranslatef(-swingX * 0.4F, MathHelper.sin(MathHelper.sqrt_float(swing) * (float) Math.PI * 2.0F) * 0.2F, -swingZ * 0.2F);
GL11.glTranslatef(0.7F * f13, -0.65F * f13 - (1.0F - 1/* raiseprogress */) * 0.6F, -0.9F * f13);
GL11.glRotatef(45.0F, 0.0F, 1.0F, 0.0F);
GL11.glEnable(GL12.GL_RESCALE_NORMAL);
float swingYaw = MathHelper.sin(swing * swing * (float) Math.PI);
float swingPitchRoll = MathHelper.sin(MathHelper.sqrt_float(swing) * (float) Math.PI);
GL11.glRotatef(-swingYaw * 20.0F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(-swingPitchRoll * 20.0F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(-swingPitchRoll * 80.0F, 1.0F, 0.0F, 0.0F);
f8 = 0.4F;
GL11.glScalef(f8, f8, f8);
this.renderItem(ItemRenderType.EQUIPPED_FIRST_PERSON, itemstack, null, player);
GL11.glRotated(180, 0, 1, 0);
//viewbob
if(mc.renderViewEntity instanceof EntityPlayer) {
EntityPlayer entityplayer = (EntityPlayer) mc.renderViewEntity;
float distanceDelta = entityplayer.distanceWalkedModified - entityplayer.prevDistanceWalkedModified;
float distanceInterp = -(entityplayer.distanceWalkedModified + distanceDelta * interp);
float camYaw = entityplayer.prevCameraYaw + (entityplayer.cameraYaw - entityplayer.prevCameraYaw) * interp;
float camPitch = entityplayer.prevCameraPitch + (entityplayer.cameraPitch - entityplayer.prevCameraPitch) * interp;
GL11.glTranslatef(MathHelper.sin(distanceInterp * (float) Math.PI * swayPeriod) * camYaw * 0.5F * swayMagnitude, -Math.abs(MathHelper.cos(distanceInterp * (float) Math.PI * swayPeriod) * camYaw) * swayMagnitude, 0.0F);
GL11.glRotatef(MathHelper.sin(distanceInterp * (float) Math.PI * swayPeriod) * camYaw * 3.0F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(Math.abs(MathHelper.cos(distanceInterp * (float) Math.PI * swayPeriod - 0.2F) * camYaw) * 5.0F, 1.0F, 0.0F, 0.0F);
GL11.glRotatef(camPitch, 1.0F, 0.0F, 0.0F);
}
this.renderItem(ItemRenderType.EQUIPPED_FIRST_PERSON, stack, null, player);
GL11.glPopMatrix();
@ -160,13 +180,28 @@ public abstract class ItemRenderWeaponBase implements IItemRenderer {
}
protected void setupFirstPerson(ItemStack stack) {
//GL11.glRotated(90, 0, 1, 0);
//GL11.glRotated(40, -1, 0, 0);
GL11.glTranslated(0, 0, 1);
if(Minecraft.getMinecraft().thePlayer.isSneaking()) {
GL11.glTranslated(0, -3.875 / 8D, 0);
} else {
float offset = 0.8F;
GL11.glRotated(180, 0, 1, 0);
GL11.glTranslatef(1.0F * offset, -0.75F * offset, -0.5F * offset);
GL11.glRotated(180, 0, 1, 0);
}
}
protected void setupThirdPerson(ItemStack stack) {
double scale = 0.125D;
GL11.glScaled(scale, scale, scale);
GL11.glRotatef(15.0F, 0.0F, 0.0F, 1.0F);
GL11.glRotatef(12.5F, 0.0F, 1.0F, 0.0F);
GL11.glRotatef(10.0F, 1.0F, 0.0F, 0.0F);
GL11.glTranslated(3.5, 0, 0);
}
protected void setupInv(ItemStack stack) {
@ -177,9 +212,18 @@ public abstract class ItemRenderWeaponBase implements IItemRenderer {
}
protected void setupEntity(ItemStack stack) {
double scale = 0.125D;
GL11.glScaled(scale, scale, scale);
}
public abstract void renderFirstPerson(ItemStack stack);
public abstract void renderOther(ItemStack stack, ItemRenderType type);
public static void standardAimingTransform(ItemStack stack, double sX, double sY, double sZ, double aX, double aY, double aZ) {
float aimingProgress = ItemGunBase.prevAimingProgress + (ItemGunBase.aimingProgress - ItemGunBase.prevAimingProgress) * interp;
double x = sX + (aX - sX) * aimingProgress;
double y = sY + (aY - sY) * aimingProgress;
double z = sZ + (aZ - sZ) * aimingProgress;
GL11.glTranslated(x, y, z);
}
}

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB