当前位置:网站首页>Minecraft 1.18.1, 1.18.2 module development 22 Sniper rifle
Minecraft 1.18.1, 1.18.2 module development 22 Sniper rifle
2022-07-06 02:13:00 【Jay_ fearless】
Minecraft 1.18.1、1.18.2 Module development 05. The emitter + Missiles
Today we implement a sniper gun in the module .
1. With the first 5 This tutorial is similar , We need to make models of guns and bullets first :
However, this time we hope that the sniper gun will enter the opening state when the Deputy , So we need to set up a first person field of view of the sniper gun in the form of an assistant .
Then export as .json file , Will export .json File put in resources\assets\ Your module name \models\item
in :
2. stay Items Create a new item class of our bullets in the bag ItemSniperAmmo
:
ItemSniperAmmo
package com.joy187.re8joymod.items;
import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.entity.EntitySniperAmmo;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Item.Properties;
import net.minecraft.world.level.Level;
public class ItemSniperAmmo extends Item {
public ItemSniperAmmo() {
super(new Properties().tab(Main.TUTORIAL_TAB).stacksTo(16));
}
public EntitySniperAmmo createArrow(Level p_200887_1_, ItemStack p_200887_2_, LivingEntity p_200887_3_) {
EntitySniperAmmo arrowentity = new EntitySniperAmmo(p_200887_1_, p_200887_3_);
return arrowentity;
}
public boolean isInfinite(ItemStack stack, ItemStack bow, net.minecraft.world.entity.player.Player player) {
int enchant = net.minecraft.world.item.enchantment.EnchantmentHelper.getItemEnchantmentLevel(net.minecraft.world.item.enchantment.Enchantments.INFINITY_ARROWS, bow);
return enchant <= 0 ? false : this.getClass() == ItemSniperAmmo.class;
}
}
stay Init Bag ItemInit Class to add our throwing object declaration :
ItemInit.java
public class ItemInit {
public static final DeferredRegister<Item> ITEMS = DeferredRegister.create(ForgeRegistries.ITEMS,
Main.MOD_ID);
// Our throw item statement
public static RegistryObject<Item> SNIPERAMMO = ITEMS.register("sniperammo",()->
{
return new ItemSniperAmmo();
});
private static <T extends Item> RegistryObject<T> register(final String name, final Supplier<T> item) {
return ITEMS.register(name, item);
}
}
3. stay entity Create our bullet entity class in the package EntitySniperAmmo
EntitySniperAmmo.java
package com.joy187.re8joymod.entity;
import com.joy187.re8joymod.init.EntityInit;
import com.joy187.re8joymod.init.ItemInit;
import io.netty.buffer.Unpooled;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.protocol.Packet;
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.network.syncher.EntityDataSerializers;
import net.minecraft.network.syncher.SynchedEntityData;
import net.minecraft.world.damagesource.DamageSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.monster.AbstractSkeleton;
import net.minecraft.world.entity.monster.Blaze;
import net.minecraft.world.entity.monster.Ravager;
import net.minecraft.world.entity.projectile.ThrowableItemProjectile;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.Level;
import net.minecraft.world.phys.EntityHitResult;
import net.minecraftforge.network.NetworkHooks;
public class EntitySniperAmmo extends ThrowableItemProjectile{
public int explosionPower = 1,id=91082;
public double damage;
private int ticksInGround;
private static final EntityDataAccessor<Integer> ID_EFFECT_COLOR = SynchedEntityData.defineId(EntitySniperAmmo.class, EntityDataSerializers.INT);
public EntitySniperAmmo(EntityType<?> entityIn, Level level) {
super((EntityType<? extends EntitySniperAmmo>) entityIn, level);
//this.size(1.0F, 1.0F);
this.damage = 24D;
// TODO Auto-generated constructor stub
}
public EntitySniperAmmo(Level world, LivingEntity entity) {
super(EntityInit.SNIPERAMMO.get(), entity, world);
this.damage= 24D;
}
// Our bullets are bound to previous items
@Override
protected Item getDefaultItem() {
return ItemInit.SNIPERAMMO.get();
}
// Damage caused when an object strikes an entity
protected void onHitEntity(EntityHitResult result) {
super.onHitEntity(result);
Entity entity = result.getEntity();
int i = 24;
if(entity instanceof Blaze || entity instanceof Ravager){
i = 28;
}
if(entity instanceof EntityBei || entity instanceof EntityHeisen){
i= 35;
}
if(entity instanceof EntityUrias || entity instanceof EntityUriass){
i= 25;
}
if(entity instanceof EntityLycana || entity instanceof AbstractSkeleton){
i= 45;
}
entity.hurt(DamageSource.thrown(this, this.getOwner()), (float)(i+random.nextFloat()*0.5*this.damage));
}
protected void onHit(EntityHitResult p_70227_1_) {
super.onHit(p_70227_1_);
if (!this.level.isClientSide) {
this.level.broadcastEntityEvent(this, (byte)3);
this.remove(Entity.RemovalReason.KILLED);
}
}
@Override
public Packet<?> getAddEntityPacket() {
FriendlyByteBuf pack = new FriendlyByteBuf(Unpooled.buffer());
pack.writeDouble(getX());
pack.writeDouble(getY());
pack.writeDouble(getZ());
pack.writeInt(getId());
pack.writeUUID(getUUID());
return NetworkHooks.getEntitySpawningPacket(this);
}
}
4. Render our missiles ,render Create a new rendering class in the package RenderSniperAmmo
RenderSniperAmmo.java
package com.joy187.re8joymod.entity.render;
import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.entity.EntitySniperAmmo;
import com.mojang.blaze3d.vertex.PoseStack;
import com.mojang.blaze3d.vertex.VertexConsumer;
import com.mojang.math.Matrix3f;
import com.mojang.math.Matrix4f;
import com.mojang.math.Vector3f;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.block.model.ItemTransforms;
import net.minecraft.client.renderer.entity.EntityRenderer;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.ItemRenderer;
import net.minecraft.client.renderer.texture.OverlayTexture;
import net.minecraft.core.BlockPos;
import net.minecraft.resources.ResourceLocation;
public class RenderSniperAmmo extends EntityRenderer<EntitySniperAmmo> {
// The mapping position of your bullet
public static final ResourceLocation TEXTURE = new ResourceLocation(Main.MOD_ID ,"textures/item/zhihu.png");
private static final float MIN_CAMERA_DISTANCE_SQUARED = 12.25F;
private final ItemRenderer itemRenderer;
private final float scale;
private final boolean fullBright;
public RenderSniperAmmo(EntityRendererProvider.Context manager) {
//this.itemRenderer = manager.getItemRenderer();
super(manager);
this.itemRenderer=manager.getItemRenderer();
this.scale=0.25F;
this.fullBright=false;
}
private static final RenderType field_229044_e_ = RenderType.entityCutoutNoCull(TEXTURE);
protected int getSkyLightLevel(EntitySniperAmmo p_239381_1_, BlockPos p_239381_2_) {
return 1;
}
@Override
public ResourceLocation getTextureLocation(EntitySniperAmmo p_110775_1_) {
return TEXTURE;
}
public void render(EntitySniperAmmo entityIn, float entityYaw, float partialTicks, PoseStack poseStackIn, MultiBufferSource bufferIn, int packedLightIn) {
if (entityIn.tickCount >= 2 || !(this.entityRenderDispatcher.camera.getEntity().distanceToSqr(entityIn) < 12.25D)) {
poseStackIn.pushPose();
poseStackIn.scale(this.scale, this.scale, this.scale);
poseStackIn.mulPose(this.entityRenderDispatcher.cameraOrientation());
poseStackIn.mulPose(Vector3f.YP.rotationDegrees(180.0F));
this.itemRenderer.renderStatic(entityIn.getItem(), ItemTransforms.TransformType.GROUND, packedLightIn, OverlayTexture.NO_OVERLAY, poseStackIn, bufferIn, entityIn.getId());
poseStackIn.popPose();
super.render(entityIn, entityYaw, partialTicks, poseStackIn, bufferIn, packedLightIn);
}
}
private static void vertexRender(VertexConsumer p_229045_0_, Matrix4f p_229045_1_, Matrix3f p_229045_2_, int p_229045_3_, float p_229045_4_, int p_229045_5_, int p_229045_6_, int p_229045_7_) {
p_229045_0_.vertex(p_229045_1_, p_229045_4_ - 0.5F, (float)p_229045_5_ - 0.25F, 0.0F).color(255, 255, 255, 255).overlayCoords(OverlayTexture.NO_OVERLAY).normal(p_229045_2_, 0.0F, 1.0F, 0.0F).endVertex();
}
}
stay ClientModEventSubscriber.java
Add the rendering event registration of our throwing object :
ClientModEventSubscriber.java
package com.joy187.re8joymod;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.Mod.EventBusSubscriber;
import net.minecraftforge.fml.event.lifecycle.FMLClientSetupEvent;
import com.joy187.re8joymod.entity.EntityRe8Dimi;
import com.joy187.re8joymod.entity.model.ModelRe8Dimi;
import com.joy187.re8joymod.entity.render.RenderMoSpitter;
import com.joy187.re8joymod.entity.render.RenderRe8Dimi;
import com.joy187.re8joymod.init.EntityInit;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.entity.EntityRendererProvider;
import net.minecraft.client.renderer.entity.ThrownItemRenderer;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.EntityRenderersEvent;
import net.minecraftforge.event.entity.EntityAttributeCreationEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
@Mod.EventBusSubscriber(modid = Main.MOD_ID, value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public class ClientModEventSubscriber
{
@SubscribeEvent
public static void onRegisterLayers(EntityRenderersEvent.RegisterLayerDefinitions event) {
event.registerLayerDefinition(ModelRe8Dimi.LAYER_LOCATION, ModelRe8Dimi::createBodyLayer);
}
@SubscribeEvent
public static void onRegisterRenderer(EntityRenderersEvent.RegisterRenderers event) {
event.registerEntityRenderer(EntityInit.RE8DIMI.get(), RenderRe8Dimi::new);
// Add rendering events for our missiles
event.registerEntityRenderer(EntityInit.SNIPERAMMO.get(), RenderSniperAmmo::new);
}
@SubscribeEvent
public static void onAttributeCreate(EntityAttributeCreationEvent event) {
event.put(EntityInit.RE8DIMI.get(), EntityRe8Dimi.prepareAttributes().build());
}
}
5. The bullet is finished , Come to the firearms section . stay Item Our new sniper guns ItemF2
ItemF2.java
package com.joy187.re8joymod.items;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nullable;
import com.joy187.re8joymod.ClientModEventSubscriber;
import com.joy187.re8joymod.Main;
import com.joy187.re8joymod.entity.EntitySniperAmmo;
import com.joy187.re8joymod.init.ItemInit;
import com.joy187.re8joymod.init.SoundInit;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
import net.minecraft.core.particles.ParticleTypes;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.sounds.SoundSource;
import net.minecraft.stats.Stats;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.InteractionResultHolder;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.player.Player;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.ProjectileWeaponItem;
import net.minecraft.world.item.TooltipFlag;
import net.minecraft.world.item.Vanishable;
import net.minecraft.world.item.enchantment.EnchantmentHelper;
import net.minecraft.world.item.enchantment.Enchantments;
import net.minecraft.world.level.Level;
public class ItemF2 extends ProjectileWeaponItem implements Vanishable {
public ItemF2() {
super(new ItemF2.Properties().tab(Main.TUTORIAL_TAB).stacksTo(1));
}
public ItemF2(Item.Properties name) {
super(name);
}
public void releaseUsing(ItemStack p_77615_1_, Level level, LivingEntity p_77615_3_, int p_77615_4_) {
if (p_77615_3_ instanceof Player) {
Player Player = (Player)p_77615_3_;
//OneHandedPose.renderFirstPersonArms(Player, Player.HAND_SLOTS, p_77615_1_, Player.getPose(), Player.buffer, p_77615_4_, p_77615_4_);
boolean flag = Player.getAbilities().instabuild || EnchantmentHelper.getItemEnchantmentLevel(Enchantments.INFINITY_ARROWS, p_77615_1_) > 0;
// ItemStack itemstack = Player.getProjectile(p_77615_1_);
ItemStack itemstack = this.findAmmo(Player);
int i = this.getUseDuration(p_77615_1_) - p_77615_4_;
i = net.minecraftforge.event.ForgeEventFactory.onArrowLoose(p_77615_1_, level, Player, i, !itemstack.isEmpty() || flag);
if (i < 0) return;
if (!itemstack.isEmpty() || flag) {
if (itemstack.isEmpty()) {
itemstack = new ItemStack(ItemInit.SNIPERAMMO.get().asItem());
}
float f = getPowerForTime(i);
if (!((double)f < 0.1D)) {
boolean flag1 = Player.getAbilities().instabuild || (itemstack.getItem() instanceof ItemSniperAmmo && ((ItemSniperAmmo)itemstack.getItem()).isInfinite(itemstack, p_77615_1_, Player));
if (!level.isClientSide) {
ItemSniperAmmo arrowitem = (ItemSniperAmmo)(itemstack.getItem() instanceof ItemSniperAmmo ? itemstack.getItem() : ItemInit.SNIPERAMMO.get().asItem());
EntitySniperAmmo abstractarrowentity = arrowitem.createArrow(level, itemstack, Player);
abstractarrowentity = customArrow(abstractarrowentity);
//abstractarrowentity.setItem(itemstack);
abstractarrowentity.shootFromRotation(Player, Player.getXRot(), Player.getYRot(), 0.2F, f * 30.0F, 0.75F);
abstractarrowentity.level.addParticle(ParticleTypes.FLAME, abstractarrowentity.getX(), abstractarrowentity.getY(), abstractarrowentity.getZ(), abstractarrowentity.position().x , abstractarrowentity.position().y, abstractarrowentity.position().z);
abstractarrowentity.playSound(SoundInit.R2FIRE.get(), 4.5F,4.5F);
if (EnchantmentHelper.getItemEnchantmentLevel(Enchantments.FLAMING_ARROWS, p_77615_1_) > 0) {
abstractarrowentity.setSecondsOnFire(100);
}
p_77615_1_.hurtAndBreak(1, Player, (p_220009_1_) -> {
p_220009_1_.broadcastBreakEvent(Player.getUsedItemHand());
});
abstractarrowentity.level.addParticle(ParticleTypes.FLAME, abstractarrowentity.getX(), abstractarrowentity.getY(), abstractarrowentity.getZ(), abstractarrowentity.position().x * -0.2D, 0.08D, abstractarrowentity.position().z * -0.2D);
level.addFreshEntity(abstractarrowentity);
}
// The sound emitted
level.playSound((Player)null, Player.getX(), Player.getY(), Player.getZ(), SoundInit.R2FIRE.get(), SoundSource.PLAYERS, 4.5F, 4.5F / (Player.getRandom().nextFloat() * 0.2F + 1.2F) + f * 0.5F);
if (!flag1 && !Player.getAbilities().instabuild) {
itemstack.shrink(1);
if (itemstack.isEmpty()) {
Player.getInventory().removeItem(itemstack);
}
}
// After each successful launch, the interval 1.5s Launch again (30=20*1.5)
Player.getCooldowns().addCooldown(this, 30);
Player.awardStat(Stats.ITEM_USED.get(this));
}
}
}
}
public InteractionResultHolder<ItemStack> use(Level level, Player palyerIn, InteractionHand handIn) {
ItemStack itemstack = palyerIn.getItemInHand(handIn);
boolean flag = !this.findAmmo(palyerIn).isEmpty();
InteractionResultHolder<ItemStack> ret = net.minecraftforge.event.ForgeEventFactory.onArrowNock(itemstack, level, palyerIn, handIn, flag);
if (ret != null) return ret;
if (!palyerIn.getAbilities().instabuild && !flag) {
return InteractionResultHolder.fail(itemstack);
} else {
palyerIn.startUsingItem(handIn);
return InteractionResultHolder.consume(itemstack);
}
}
public static float getPowerForTime(int p_185059_0_) {
float f = (float)p_185059_0_ / 20.0F;
f = (f * f + f * 2.0F) / 3.0F;
if (f > 1.0F) {
f = 1.0F;
}
return f;
}
public int getUseDuration(ItemStack p_77626_1_) {
return 500;
}
public Predicate<ItemStack> getAllSupportedProjectiles() {
return ARROW_OR_FIREWORK;
}
public EntitySniperAmmo customArrow(EntitySniperAmmo arrow) {
return arrow;
}
public int getDefaultProjectileRange() {
return 15;
}
// Determine whether we can find our exclusive bullets
protected ItemStack findAmmo(Player player)
{
if (this.isSniperAmmo(player.getItemInHand(InteractionHand.OFF_HAND)))
{
return player.getItemInHand(InteractionHand.OFF_HAND);
}
else if (this.isSniperAmmo(player.getItemInHand(InteractionHand.MAIN_HAND)))
{
return player.getItemInHand(InteractionHand.MAIN_HAND);
}
else
{
for (int i = 0; i < player.getInventory().getContainerSize(); ++i)
{
ItemStack itemstack = player.getInventory().getItem(i);
if (this.isSniperAmmo(itemstack))
{
return itemstack;
}
}
return ItemStack.EMPTY;
}
}
protected boolean isSniperAmmo(ItemStack stack)
{
return stack.getItem() instanceof ItemSniperAmmo;
}
@Override
public boolean onEntitySwing(ItemStack stack, LivingEntity entity)
{
return true;
}
public void initializeClient(java.util.function.Consumer<net.minecraftforge.client.IItemRenderProperties> consumer) {
}
// Monitor the state of firearms
public void inventoryTick(ItemStack p_77663_1_, Level p_77663_2_, Entity p_77663_3_, int p_77663_4_, boolean p_77663_5_) {
if(p_77663_3_ instanceof Player)
{
ItemStack item = ((Player)p_77663_3_).getItemInHand(InteractionHand.OFF_HAND);
// If the player's deputy is equipped with this gun
if(item.getItem() == ItemInit.F2RIFLE.get())
{
// Let the field of vision become open ( The smaller the value, the larger the magnification )
Minecraft.getInstance().options.fov=12;
}
else {
// Return to the field of vision when you are not in the Deputy
Minecraft.getInstance().options.fov=70;
}
}
}
@Override
public void appendHoverText(ItemStack stack, @Nullable Level worldIn, List<Component> tooltip, TooltipFlag flagIn) {
tooltip.add(Component.nullToEmpty(ChatFormatting.GOLD+"Press 'F' to offhand for scoping."));
tooltip.add(Component.nullToEmpty(ChatFormatting.GOLD+"Ammo Type:Sniper Rifle Ammo"));
}
}
stay ItemInit
Class to add our gun declaration :
ItemInit.java
public static RegistryObject<Item> SA110 = ITEMS.register("sa110",()->
{
return new ItemF2();
});
6. We designed a special sound for our guns , stay SoundInit Register in :
SoundInit.java
package com.joy187.re8joymod.init;
import net.minecraftforge.registries.RegistryObject;
import com.joy187.re8joymod.Main;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.sounds.SoundEvent;
import net.minecraftforge.registries.DeferredRegister;
import net.minecraftforge.registries.ForgeRegistries;
public class SoundInit {
public static final DeferredRegister<SoundEvent> SOUNDS = DeferredRegister.create(ForgeRegistries.SOUND_EVENTS, Main.MOD_ID);
// The sound of our guns
public static final RegistryObject<SoundEvent> R2FIRE = build("entity.m1851.f2rifle");
private static RegistryObject<SoundEvent> build(String id)
{
return SOUNDS.register(id, () -> new SoundEvent(new ResourceLocation(Main.MOD_ID, id)));
}
}
In the main class of the project Main Function will be SoundInit
Class to register :
public Main() {
IEventBus bus = FMLJavaModLoadingContext.get().getModEventBus();
ItemInit.ITEMS.register(bus);
BlockInit.BLOCKS.register(bus);
EntityInit.ENTITY_TYPES.register(bus);
EffectInit.EFFECTS.register(bus);
PotionInit.POTIONS.register(bus);
// Add this
SoundInit.SOUNDS.register(bus);
}
Convert sound files to .ogg
Format , Put in src\main\resources\assets\ Yours modid\sounds\entity\m1851
Under the path .
7. The code section ends , Enter the resource pack production process . stay resources In bag sounds.json
Add our gun sound to the file :
sounds.json
"entity.m1851.f2rifle":{
"category":"entity",
"subtitle" :"entity.m1851.f2rifle.sub",
"sounds":[{ "name": "re8joymod:entity/m1851/f2rifle", "stream":true }]
},
stay lang In bag en_us.json
Add guns 、 Bullet items 、 English name of bullet entity :
en_us.json
"entity.re8joymod.sniperammo": "Sniper Rifle Ammo",
"item.re8joymod.f2rifle": "F2 Rifle",
"item.re8joymod.sniperammo": "Sniper Rifle Ammo",
stay lang In bag zh_cn.json
Add guns 、 Bullet items 、 Chinese name of bullet entity :
zh_cn.json
"item.re8joymod.sniperammo": " Sniper gun bullets ",
"item.re8joymod.f2rifle": "F2 sniper rifle ",
"entity.re8joymod.sniperammo": " Sniper gun bullets ",
8. Save the project , Run game tests :
The main hand is in the form of sniper gun :
Press ’F’ Key to switch to the sniper gun form when the second hand
Pong! Pong!
边栏推荐
- Comments on flowable source code (XXXV) timer activation process definition processor, process instance migration job processor
- 阿里测开面试题
- 正则表达式:示例(1)
- 抓包整理外篇——————状态栏[ 四]
- Unity learning notes -- 2D one-way platform production method
- Leetcode3, implémenter strstr ()
- TrueType字体文件提取关键信息
- Global and Chinese markets hitting traffic doors 2022-2028: Research Report on technology, participants, trends, market size and share
- [solution] add multiple directories in different parts of the same word document
- Thinking about the best practice of dynamics 365 development collaboration
猜你喜欢
Open source | Ctrip ticket BDD UI testing framework flybirds
Extracting key information from TrueType font files
RDD conversion operator of spark
【clickhouse】ClickHouse Practice in EOI
NiO related knowledge (II)
Computer graduation design PHP college classroom application management system
Spark accumulator
Blue Bridge Cup embedded_ STM32 learning_ Key_ Explain in detail
2022 PMP project management examination agile knowledge points (8)
安装php-zbarcode扩展时报错,不知道有没有哪位大神帮我解决一下呀 php 环境用的7.3
随机推荐
论文笔记: 图神经网络 GAT
Exness: Mercedes Benz's profits exceed expectations, and it is predicted that there will be a supply chain shortage in 2022
Tensorflow customize the whole training process
Leetcode3, implémenter strstr ()
Campus second-hand transaction based on wechat applet
Install redis
FTP server, ssh server (super brief)
国家级非遗传承人高清旺《四大美人》皮影数字藏品惊艳亮相!
leetcode3、實現 strStr()
500 lines of code to understand the principle of mecached cache client driver
01. Go language introduction
MySQL index
Bidding promotion process
Concept of storage engine
Genius storage uses documents, a browser caching tool
Have a look at this generation
Selenium waiting mode
Redis key operation
Xshell 7 Student Edition
Redis string type