Browse Source

1.添加狗功能

slambb 4 years ago
parent
commit
e5275ed8aa
60 changed files with 2024 additions and 146 deletions
  1. 22 3
      src/main/java/com/td/boss/config/enums/ResultEnum.java
  2. 35 0
      src/main/java/com/td/boss/game/commallfood/controller/ComMallFoodController.java
  3. 36 0
      src/main/java/com/td/boss/game/commallfood/pojo/ComMallFood.java
  4. 9 0
      src/main/java/com/td/boss/game/commallfood/repository/ComMallFoodRepository.java
  5. 8 0
      src/main/java/com/td/boss/game/commallfood/service/ComMallFoodService.java
  6. 21 0
      src/main/java/com/td/boss/game/commallfood/service/ComMallFoodServiceImpl.java
  7. 33 0
      src/main/java/com/td/boss/game/commallfood/vo/ComMallFoodSimpleVo.java
  8. 31 0
      src/main/java/com/td/boss/game/commallfood/vo/ComMallFoodVo.java
  9. 34 0
      src/main/java/com/td/boss/game/commallother/controller/ComMallOtherController.java
  10. 36 0
      src/main/java/com/td/boss/game/commallother/pojo/ComMallOther.java
  11. 9 0
      src/main/java/com/td/boss/game/commallother/repository/ComMallOtherRepository.java
  12. 11 0
      src/main/java/com/td/boss/game/commallother/service/ComMallOtherService.java
  13. 21 0
      src/main/java/com/td/boss/game/commallother/service/ComMallOtherServiceImpl.java
  14. 33 0
      src/main/java/com/td/boss/game/commallother/vo/ComMallOtherSimpleVo.java
  15. 31 0
      src/main/java/com/td/boss/game/commallother/vo/ComMallOtherVo.java
  16. 80 53
      src/main/java/com/td/boss/game/commallseed/controller/ComMallSeedController.java
  17. 423 0
      src/main/java/com/td/boss/game/complayerdog/controller/ComPlayerDogController.java
  18. 43 0
      src/main/java/com/td/boss/game/complayerdog/pojo/ComPlayerDog.java
  19. 17 0
      src/main/java/com/td/boss/game/complayerdog/repository/ComPlayerDogRepository.java
  20. 14 0
      src/main/java/com/td/boss/game/complayerdog/service/ComPlayerDogService.java
  21. 35 0
      src/main/java/com/td/boss/game/complayerdog/service/ComPlayerDogServiceImpl.java
  22. 45 0
      src/main/java/com/td/boss/game/complayerdog/vo/ComPlayerDogSimpleVo.java
  23. 39 0
      src/main/java/com/td/boss/game/complayerdog/vo/ComPlayerDogVo.java
  24. 452 23
      src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java
  25. 11 8
      src/main/java/com/td/boss/game/complayerland/controller/ComPlayerLandController.java
  26. 2 0
      src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLand.java
  27. 3 1
      src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLandAndCanSteal.java
  28. 4 4
      src/main/java/com/td/boss/game/complayerland/repository/ComPlayerLandRepository.java
  29. 1 1
      src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandService.java
  30. 7 7
      src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandServiceImpl.java
  31. 5 1
      src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandAndPlantVo.java
  32. 4 0
      src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandSimpleVo.java
  33. 2 0
      src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandVo.java
  34. 2 1
      src/main/java/com/td/boss/game/complayerlog/vo/ComPlayerLogVo.java
  35. 4 2
      src/main/java/com/td/boss/game/complayerprofit/repository/ComPlayerProfitRepository.java
  36. 3 1
      src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitService.java
  37. 7 2
      src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java
  38. 5 3
      src/main/java/com/td/boss/game/complayersattri/controller/ComPlayersAttriController.java
  39. 7 1
      src/main/java/com/td/boss/game/comsetting/pojo/ComSetting.java
  40. 7 1
      src/main/java/com/td/boss/game/comsetting/vo/ComSettingSimpleVo.java
  41. 7 1
      src/main/java/com/td/boss/game/comsetting/vo/ComSettingVo.java
  42. 54 2
      src/main/java/com/td/boss/game/comsnbfreeze/controller/ComSnbFreezeController.java
  43. 8 0
      src/main/java/com/td/boss/game/comsnbtran/pojo/ComSnbTran.java
  44. 8 0
      src/main/java/com/td/boss/game/comsnbtran/vo/ComSnbTranVo.java
  45. 30 9
      src/main/java/com/td/boss/game/comusers/controller/ComUsersController.java
  46. 2 0
      src/main/java/com/td/boss/game/comusers/pojo/ComUsers.java
  47. 3 0
      src/main/java/com/td/boss/game/comusers/service/ComUsersService.java
  48. 15 0
      src/main/java/com/td/boss/game/comusers/service/ComUsersServiceImpl.java
  49. 2 0
      src/main/java/com/td/boss/game/comusers/vo/ComUsersSimpleVo.java
  50. 2 0
      src/main/java/com/td/boss/game/comusers/vo/ComUsersVo.java
  51. 14 0
      src/main/java/com/td/boss/sys/sysGame/controller/sysGameUsersController.java
  52. 2 2
      src/main/java/com/td/boss/util/CodeDOM.java
  53. 88 0
      src/main/java/com/td/boss/util/DappUtil.java
  54. 4 0
      src/main/java/com/td/boss/util/DateUtil.java
  55. 33 0
      src/main/java/com/td/boss/util/RedisData.java
  56. 2 2
      src/main/resources/application.yml
  57. 1 11
      src/main/resources/banner.txt
  58. 16 4
      src/main/resources/static/sys/aComUser/js/user.js
  59. 117 3
      src/main/resources/static/sys/aComUser/js/userPlayerGoods.js
  60. 24 0
      src/main/resources/view/sys/aComUser/userPlayerGoods.html

+ 22 - 3
src/main/java/com/td/boss/config/enums/ResultEnum.java

@@ -19,6 +19,8 @@ public enum ResultEnum {
     NO_PARAMETERS_CARRIED(305,"输入对应参数"),
     //setting部分
     SETTING_IS_NULL(306,"配置信息不存在"),
+    //redis部分
+    REDIS_IS_LOCK(307,"操作过于频繁,稍后再试!"),
     //用户数据
     USER_DOES_NOT_EXIST(400,"不能存在用户信息!"),
     USER_ENERGY_IS_INSUFFICIENT(401,"用户能量不足!"),
@@ -27,6 +29,7 @@ public enum ResultEnum {
     USER_NOT_ADDRESS(403,"用户地址不存在!"),
     USER_LIMIT_LOGIN(404,"用户限制登录!"),
 
+    USER_LOGIN_LOCK(405,"用户保存繁忙,请重试操作!"),
     //角色数据
     PLAYER_DOES_NOT_EXIST(500,"不存在角色信息!"),
     PLAYER_DOES_NOT_ATTRIBUTES(501,"battle player 数据不存在!"),
@@ -42,6 +45,8 @@ public enum ResultEnum {
     PLAYER_GOODS_SEEDS_AMOUNT_ERROR(517,"土地消耗种子数量不足"),
 
     PLAYER_ATTRIBUTE_STRENGTH_IS_NOT(518,"用户体力不足"),
+
+    PLAYER_GOODS_SAVE_LOCK(520,"操作繁忙,保存背包失败,稍后再试!"),
     //钱包数据
     WALLET_CNT_PLAY_ERROR(601,"钱包CNT支付参数数据错误!"),
     WALLET_SNB_INSUFFICIENT_QUANTITY(602,"snb不足以支付!"),
@@ -55,11 +60,14 @@ public enum ResultEnum {
     LAND_IS_PLANT(704,"土地已种植!"),
     LAND_NOT_PLANT(705,"土地未种植!"),
     LAND_LEASE_EXPIRED(706,"土地租赁已过期!"),
-    LAND_HARVEST_STOLEN(707,"土地收成已偷了!"),
-    LAND_STEAL_ALL(708,"土地已被偷取完!"),
+    LAND_HARVEST_STOLEN(707,"土地已收成过!"),
+    LAND_STEAL_ALL(708,"土地已无多余收成!"),
     LAND_STEAL_LOCK(709,"当前偷取人数过多,稍后再试!"),
     LAND_PLANT_FLAG_IS_NULL(710,"土地标识为空,不能偷取"),
-    LAND_CAN_STEAL_IS_ZERO(711,"没有可收取果实的土地!"),
+    LAND_CAN_STEAL_IS_ZERO(711,"没有可收取果实的土地不存在!"),
+    LAND_CAN_STEAL_IS_NULL(712,"没有可收取果实的土地!"),
+
+    LAND_CAN_STEAL_IS_MAX(713,"已无多余利润!"),//达到最大值
     //种子数据不能存在
     SEED_DATA_ERROR(801,"种子数据不存在!"),
     FRUIT_DATA_ERROR(802,"果实数据不存在!"),
@@ -71,6 +79,17 @@ public enum ResultEnum {
     SEED_PLAY_DIAMOND_ERROR(808,"钻石不足以兑换支付!"),
     SEED_IS_EXCHANGE(809,"种子已经兑换过!"),
 
+    FOOD_DATA_ERROR(810,"食物数据不存在"),
+    FOOD_DOT_NOT(811,"狗粮不足!"),
+
+    SEED_SALE_SAVE_LOCK(810,"操作繁忙,出售失败,稍后再试!"),
+    //装备相关
+    MALL_OTHER_IS_NULL(810,"商城装备不存在!"),
+    MALL_OTHER_IS_HAVE(811,"商城装备已经存在!"),
+    PLAYER_OTHER_IS_NULL(812,"商城装备不存在!"),
+    PLAYER_OTHER_IS_HAVE(813,"商城装备已经存在!"),
+
+
     FRUIT_AMOUNT_IS_ZERO_AND_NOT_MULTIPLE(808,"请输入出售果实的数量!"),
     ;
     private Integer code;

+ 35 - 0
src/main/java/com/td/boss/game/commallfood/controller/ComMallFoodController.java

@@ -0,0 +1,35 @@
+package com.td.boss.game.commallfood.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.game.commallfood.pojo.ComMallFood;
+import com.td.boss.game.commallfood.vo.ComMallFoodSimpleVo;
+import com.td.boss.game.commallfood.vo.ComMallFoodVo;
+import com.td.boss.game.commallfood.service.ComMallFoodService;
+import com.td.boss.util.CopyUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+@RestController
+@RequestMapping("/game/comMallFood/")
+public class ComMallFoodController extends CommonController<ComMallFoodVo, ComMallFood, Integer> {
+    @Autowired
+    private ComMallFoodService comMallFoodService;
+
+
+
+    @GetMapping("getMallFoodList")
+    public Result<List<ComMallFoodSimpleVo>> getEquipmentByTypeFunction(@RequestParam(value = "userId") String userId) {
+
+        ComMallFoodVo comMallFoodVo = new ComMallFoodVo();
+
+        List<ComMallFoodSimpleVo> comMallFoodSimpleVoList = comMallFoodService.list(comMallFoodVo).getData().stream().map(e->{
+            return  CopyUtil.copy(e, ComMallFoodSimpleVo.class);
+        }).collect(Collectors.toList());
+
+        return Result.of(comMallFoodSimpleVoList);
+    }
+}

+ 36 - 0
src/main/java/com/td/boss/game/commallfood/pojo/ComMallFood.java

@@ -0,0 +1,36 @@
+package com.td.boss.game.commallfood.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_mall_food")
+@Data
+public class ComMallFood implements Serializable {
+    @Id
+    @GeneratedValue(strategy= GenerationType.IDENTITY)
+    private Integer id;//
+
+    private String mallType;//商城类型,默认是狗粮0
+
+    private String picture;//图片名字,前端存储
+
+    private String name;//
+
+    private Integer weight;//大包食物
+
+    private Integer priceCnt;//
+
+    private Integer priceSnb;//
+
+    private Integer amount;//库存数量
+
+    private String foodDescribe;//描述一下
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/commallfood/repository/ComMallFoodRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.commallfood.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.commallfood.pojo.ComMallFood;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComMallFoodRepository extends CommonRepository<ComMallFood, Integer> {
+}

+ 8 - 0
src/main/java/com/td/boss/game/commallfood/service/ComMallFoodService.java

@@ -0,0 +1,8 @@
+package com.td.boss.game.commallfood.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.commallfood.pojo.ComMallFood;
+import com.td.boss.game.commallfood.vo.ComMallFoodVo;
+
+public interface ComMallFoodService extends CommonService<ComMallFoodVo, ComMallFood, Integer> {
+}

+ 21 - 0
src/main/java/com/td/boss/game/commallfood/service/ComMallFoodServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.commallfood.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.commallfood.pojo.ComMallFood;
+import com.td.boss.game.commallfood.vo.ComMallFoodVo;
+import com.td.boss.game.commallfood.repository.ComMallFoodRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComMallFoodServiceImpl extends CommonServiceImpl<ComMallFoodVo, ComMallFood, Integer> implements ComMallFoodService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComMallFoodRepository comMallFoodRepository;
+}

+ 33 - 0
src/main/java/com/td/boss/game/commallfood/vo/ComMallFoodSimpleVo.java

@@ -0,0 +1,33 @@
+package com.td.boss.game.commallfood.vo;
+
+import com.td.boss.common.pojo.PageCondition;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComMallFoodSimpleVo implements Serializable {
+    private Integer id;//
+
+    private String mallType;//商城类型,默认是狗粮0
+
+    private String picture;//图片名字,前端存储
+
+    private String name;//
+
+    private Integer weight;//大包食物
+
+    private Integer priceCnt;//
+
+    private Integer priceSnb;//
+
+    private Integer amount;//库存数量
+
+    private String foodDescribe;//描述一下
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 31 - 0
src/main/java/com/td/boss/game/commallfood/vo/ComMallFoodVo.java

@@ -0,0 +1,31 @@
+package com.td.boss.game.commallfood.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComMallFoodVo extends PageCondition implements Serializable {
+    private Integer id;//
+
+    private String mallType;//商城类型,默认是狗粮0
+
+    private String picture;//图片名字,前端存储
+
+    private String name;//
+
+    private Integer weight;//大包食物
+
+    private Integer priceCnt;//
+
+    private Integer priceSnb;//
+
+    private Integer amount;//库存数量
+
+    private String foodDescribe;//描述一下
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 34 - 0
src/main/java/com/td/boss/game/commallother/controller/ComMallOtherController.java

@@ -0,0 +1,34 @@
+package com.td.boss.game.commallother.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.game.commallother.pojo.ComMallOther;
+import com.td.boss.game.commallother.vo.ComMallOtherSimpleVo;
+import com.td.boss.game.commallother.vo.ComMallOtherVo;
+import com.td.boss.game.commallother.service.ComMallOtherService;
+import com.td.boss.util.CopyUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+
+@RestController
+@RequestMapping("/game/comMallOther/")
+public class ComMallOtherController extends CommonController<ComMallOtherVo, ComMallOther, Integer> {
+    @Autowired
+    private ComMallOtherService comMallOtherService;
+
+    /**
+     * 获取商城装备栏列表
+     *
+     * @param userId
+     * @return
+     */
+    @GetMapping("getMallEquipmentList")
+    public Result<List<ComMallOtherSimpleVo>> getEquipmentListFunction(@RequestParam(value = "userId") String userId) {
+        ComMallOtherVo comMallOtherVo = new ComMallOtherVo();
+        Result result = comMallOtherService.list(comMallOtherVo);
+        List<ComMallOtherSimpleVo> comMallOtherSimpleVos = CopyUtil.copyList((List<ComMallOtherSimpleVo>) result.getData(), ComMallOtherSimpleVo.class);
+        return Result.of(comMallOtherSimpleVos);
+    }
+}

+ 36 - 0
src/main/java/com/td/boss/game/commallother/pojo/ComMallOther.java

@@ -0,0 +1,36 @@
+package com.td.boss.game.commallother.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_mall_other")
+@Data
+public class ComMallOther implements Serializable {
+    @Id
+    @GeneratedValue(strategy= GenerationType.IDENTITY)
+    private Integer id;//
+
+    private Integer otherType;//商城类型,默认是小狗0,1打狗棒
+
+    private String picture;//图片名字,前端存储
+
+    private String name;//
+
+    private Integer priceSnb;//
+
+    private Integer amount;//库存数量
+
+    private String itemDescribe;//描述一下生产周期
+
+    private Integer effectiveDay;//物品的有效时间
+
+    private Double triggerPro;//触发概率,狗就是触发咬的事件
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 9 - 0
src/main/java/com/td/boss/game/commallother/repository/ComMallOtherRepository.java

@@ -0,0 +1,9 @@
+package com.td.boss.game.commallother.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.commallother.pojo.ComMallOther;
+import org.springframework.stereotype.Repository;
+
+@Repository
+public interface ComMallOtherRepository extends CommonRepository<ComMallOther, Integer> {
+}

+ 11 - 0
src/main/java/com/td/boss/game/commallother/service/ComMallOtherService.java

@@ -0,0 +1,11 @@
+package com.td.boss.game.commallother.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.commallother.pojo.ComMallOther;
+import com.td.boss.game.commallother.vo.ComMallOtherVo;
+
+public interface ComMallOtherService extends CommonService<ComMallOtherVo, ComMallOther, Integer> {
+
+
+
+}

+ 21 - 0
src/main/java/com/td/boss/game/commallother/service/ComMallOtherServiceImpl.java

@@ -0,0 +1,21 @@
+package com.td.boss.game.commallother.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.commallother.pojo.ComMallOther;
+import com.td.boss.game.commallother.vo.ComMallOtherVo;
+import com.td.boss.game.commallother.repository.ComMallOtherRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+
+@Service
+@Transactional
+public class ComMallOtherServiceImpl extends CommonServiceImpl<ComMallOtherVo, ComMallOther, Integer> implements ComMallOtherService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComMallOtherRepository comMallOtherRepository;
+}

+ 33 - 0
src/main/java/com/td/boss/game/commallother/vo/ComMallOtherSimpleVo.java

@@ -0,0 +1,33 @@
+package com.td.boss.game.commallother.vo;
+
+import com.td.boss.common.pojo.PageCondition;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComMallOtherSimpleVo  implements Serializable {
+    private Integer id;//
+
+    private Integer otherType;//商城类型,默认是小狗0,1打狗棒
+
+    private String picture;//图片名字,前端存储
+
+    private String name;//
+
+    private Integer priceSnb;//
+
+    private Integer amount;//库存数量
+
+    private String itemDescribe;//描述一下生产周期
+
+    private Integer effectiveDay;//物品的有效时间
+
+    private Double triggerPro;//触发概率,狗就是触发咬的事件
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 31 - 0
src/main/java/com/td/boss/game/commallother/vo/ComMallOtherVo.java

@@ -0,0 +1,31 @@
+package com.td.boss.game.commallother.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComMallOtherVo extends PageCondition implements Serializable {
+    private Integer id;//
+
+    private Integer otherType;//商城类型,默认是小狗0,1打狗棒
+
+    private String picture;//图片名字,前端存储
+
+    private String name;//
+
+    private Integer priceSnb;//
+
+    private Integer amount;//库存数量
+
+    private String itemDescribe;//描述一下生产周期
+
+    private Integer effectiveDay;//物品的有效时间
+
+    private Double triggerPro;//触发概率,狗就是触发咬的事件
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 80 - 53
src/main/java/com/td/boss/game/commallseed/controller/ComMallSeedController.java

@@ -22,8 +22,11 @@ import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import com.td.boss.game.comusers.service.ComUsersService;
 import com.td.boss.game.comusers.vo.ComUsersVo;
 import com.td.boss.util.CopyUtil;
+import com.td.boss.util.RedisData;
+import com.td.boss.util.RedisLock;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.HashMap;
@@ -51,6 +54,8 @@ public class ComMallSeedController extends CommonController<ComMallSeedVo, ComMa
     @Autowired
     private ComPlayersService comPlayersService;
 
+    @Autowired
+    private RedisLock redisLock;
     /**
      * 获取商城种子
      *
@@ -90,69 +95,90 @@ public class ComMallSeedController extends CommonController<ComMallSeedVo, ComMa
             //return Result.of(map);
             return Result.of(map, false, ResultEnum.SEED_DATA_ERROR.getMessage(), ResultEnum.SEED_DATA_ERROR.getCode());
         }
-        if (payAmount.equals(0) || payAmount % seedVo.getPriceSnb() != 0) {
+        if (!StringUtils.hasText(payAmount.toString())||payAmount.equals(0) || payAmount % seedVo.getPriceSnb() != 0 ) {
             //支付价格不能为零,如果价格 不和种子相当,也不是种子的倍数,也是不行的
             map.put("msg", "订单非法操作,已记录相关信息!");
             //return Result.of(map);
             return Result.of(map, false, ResultEnum.SEED_PLAY_ERROR.getMessage(), ResultEnum.SEED_PLAY_ERROR.getCode());
         }
 
-        //todo 操作snb数量
-        ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
-        if (comUsersVo.getSnb() < payAmount) {
-            map.put("msg", "账户snb不足");
-            //WALLET_SNB_INSUFFICIENT_QUANTITY(602,"snb不足以支付!")
-            return Result.of(map, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
-        }
-        //如果数量够,写入修改对应操作
-        Integer _oldSnb = comUsersVo.getSnb();
-        Integer _snb = comUsersVo.getSnb() - payAmount;
-        comUsersVo.setSnb(_snb);
-        comUsersService.save(comUsersVo);
+        //todo snb冻结加锁
+        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
+        String _redisKey = "SNB_SAVE_" + userId;
 
-        //合法操作记录到仓库中
-        ComPlayerGoods entityVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, itemType, 0);
-        //这里计算一个购买种子的数量,用种子除去单价
-        int _paySeedAmount = (int) (payAmount / seedVo.getPriceSnb());
-        if (entityVo == null) {
-            //创建一个新种子
-            entityVo = new ComPlayerGoods();
-            entityVo.setGoodsIndex(itemType);
-            entityVo.setGoodsType(0);
-            entityVo.setAmount(_paySeedAmount);
-            entityVo.setName(seedVo.getName());
-            entityVo.setPictureName(seedVo.getPicture());
-            entityVo.setUserId(userId);
-        } else {
-            Integer _amount = entityVo.getAmount() + _paySeedAmount;
-            entityVo.setAmount(_amount);
-        }
-        /** 购买成功后,记录到仓库中*/
-        ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(entityVo, ComPlayerGoodsVo.class);
-        comPlayerGoodsService.save(comPlayerGoodsVo);
+        try{
+            //todo snb冻结加锁
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                return Result.of(null, false, ResultEnum.SEED_SALE_SAVE_LOCK.getMessage(), ResultEnum.SEED_SALE_SAVE_LOCK.getCode());
+            }
 
-        /**
-         * todo 购买种子的交易记录
-         */
-        ComSnbTranVo _snbTran = new ComSnbTranVo();
-        //记录兑换id
-        _snbTran.setTranId(itemType.toString());
-        _snbTran.setUserId(userId);
-        _snbTran.setTranName("使用SNB购买种子");
-        _snbTran.setTranType(3);
-        _snbTran.setTranAmount(_paySeedAmount); //此数量会操作背包记录
-        _snbTran.setTranPrice(payAmount);
-        _snbTran.setTranDescribe("SNB购买种子的价格:"+seedVo.getPriceSnb()+",支付金额:"+payAmount);
-        _snbTran.setIsAdd(0);//减少snb
-        _snbTran.setBeforeSnb(_oldSnb);
-        _snbTran.setTranSnb(payAmount);
-        _snbTran.setAfterSnb(_snb);
-        comSnbTranService.save(_snbTran);
+            //todo 操作snb数量
+            ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+            if (comUsersVo.getSnb() < payAmount) {
+                map.put("msg", "账户snb不足");
+                //WALLET_SNB_INSUFFICIENT_QUANTITY(602,"snb不足以支付!")
+                return Result.of(map, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
+            }
+            //如果数量够,写入修改对应操作
+            Integer _oldSnb = comUsersVo.getSnb();
+            Integer _snb = comUsersVo.getSnb() - payAmount;
+            comUsersVo.setSnb(_snb);
+            comUsersService.save(comUsersVo);
 
+            //合法操作记录到仓库中
+            ComPlayerGoods entityVo = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, itemType, 0);
+            //这里计算一个购买种子的数量,用种子除去单价
+            int _paySeedAmount = (int) (payAmount / seedVo.getPriceSnb());
+            if (entityVo == null) {
+                //创建一个新种子
+                entityVo = new ComPlayerGoods();
+                entityVo.setGoodsIndex(itemType);
+                entityVo.setGoodsType(0);
+                entityVo.setAmount(_paySeedAmount);
+                entityVo.setAmountPart(0d);
+                entityVo.setName(seedVo.getName());
+                entityVo.setPictureName(seedVo.getPicture());
+                entityVo.setUserId(userId);
+            } else {
+                Integer _amount = entityVo.getAmount() + _paySeedAmount;
+                entityVo.setAmount(_amount);
+            }
+            /** 购买成功后,记录到仓库中*/
+            ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(entityVo, ComPlayerGoodsVo.class);
+            comPlayerGoodsService.save(comPlayerGoodsVo);
+
+            /**
+             * todo 购买种子的交易记录
+             */
+            ComSnbTranVo _snbTran = new ComSnbTranVo();
+            //记录兑换id
+            _snbTran.setTranId(itemType.toString());
+            _snbTran.setUserId(userId);
+            _snbTran.setTranName("使用SNB购买种子");
+            _snbTran.setTranType(3);
+            _snbTran.setTranAmount(_paySeedAmount); //此数量会操作背包记录
+            _snbTran.setTranPrice(payAmount);
+            _snbTran.setTranDescribe("SNB购买种子的价格:"+seedVo.getPriceSnb()+",支付金额:"+payAmount);
+            _snbTran.setIsAdd(0);//减少snb
+            _snbTran.setBeforeSnb(_oldSnb);
+            _snbTran.setTranSnb(payAmount);
+            _snbTran.setAfterSnb(_snb);
+            //不涉及交易的设置为0
+            _snbTran.setTranAmountPart(0d);
+            _snbTran.setTranSnbPart(0d);
+            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
+            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
+            comSnbTranService.save(_snbTran);
+
+            redisLock.unlock(_redisKey, String.valueOf(time));
+            map.put("seed", entityVo.getGoodsIndex());
+            map.put("snb",comUsersVo.getSnb());
+            return Result.of(map);
+        }catch (Exception e) {
+            redisLock.unlock(_redisKey, String.valueOf(time));
+            throw new RuntimeException(e.getMessage());
+        }
 
-        map.put("seed", entityVo.getGoodsIndex());
-        map.put("snb",comUsersVo.getSnb());
-        return Result.of(map);
     }
 
 
@@ -208,6 +234,7 @@ public class ComMallSeedController extends CommonController<ComMallSeedVo, ComMa
             entityVo.setGoodsIndex(itemType);
             entityVo.setGoodsType(0);
             entityVo.setAmount(1);
+            entityVo.setAmountPart(0d);
             entityVo.setName(seedVo.getName());
             entityVo.setPictureName(seedVo.getPicture());
             entityVo.setUserId(userId);

+ 423 - 0
src/main/java/com/td/boss/game/complayerdog/controller/ComPlayerDogController.java

@@ -0,0 +1,423 @@
+package com.td.boss.game.complayerdog.controller;
+
+import com.td.boss.common.controller.*;
+import com.td.boss.common.pojo.Result;
+import com.td.boss.config.enums.ResultEnum;
+import com.td.boss.game.commallfood.service.ComMallFoodService;
+import com.td.boss.game.commallfood.vo.ComMallFoodVo;
+import com.td.boss.game.commallother.pojo.ComMallOther;
+import com.td.boss.game.commallother.service.ComMallOtherService;
+import com.td.boss.game.commallother.vo.ComMallOtherSimpleVo;
+import com.td.boss.game.commallother.vo.ComMallOtherVo;
+import com.td.boss.game.complayerdog.pojo.ComPlayerDog;
+import com.td.boss.game.complayerdog.vo.ComPlayerDogSimpleVo;
+import com.td.boss.game.complayerdog.vo.ComPlayerDogVo;
+import com.td.boss.game.complayerdog.service.ComPlayerDogService;
+import com.td.boss.game.comsnbtran.service.ComSnbTranService;
+import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
+import com.td.boss.game.comusers.pojo.ComUsers;
+import com.td.boss.game.comusers.service.ComUsersService;
+import com.td.boss.game.comusers.vo.ComUsersVo;
+import com.td.boss.util.*;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+@RestController
+@Slf4j
+@RequestMapping("/game/comPlayerDog/")
+public class ComPlayerDogController extends CommonController<ComPlayerDogVo, ComPlayerDog, String> {
+    @Autowired
+    private ComPlayerDogService comPlayerDogService;
+
+    @Autowired
+    private ComMallOtherService comMallOtherService;
+
+    @Autowired
+    private ComUsersService comUsersService;
+
+    @Autowired
+    private ComSnbTranService comSnbTranService;
+
+    @Autowired
+    private ComMallFoodService comMallFoodService;
+
+    @Autowired
+    private RedisLock redisLock;
+
+    /**
+     * 买狗和打狗棒
+     *
+     * @param userId
+     * @param mallOtherId
+     * @return
+     */
+    @PostMapping("addEquipment")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Map> addEquipmentFunction(@RequestParam(value = "userId") String userId,
+                                            @RequestParam(value = "mallOtherId") Integer mallOtherId) {
+        Map map = new HashMap();
+        //需要redis 加锁
+        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
+        String _redisKey = "SNB_SAVE_" + userId;
+        try {
+            ComMallOtherVo comMallOtherVo = comMallOtherService.get(mallOtherId).getData();
+            if (comMallOtherVo == null) {
+                return Result.of(null, false, ResultEnum.MALL_OTHER_IS_NULL.getMessage(), ResultEnum.MALL_OTHER_IS_NULL.getCode());
+            }
+            ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, comMallOtherVo.getOtherType());
+            if (comPlayerDog != null) {
+                //todo 计算狗和打狗棒是否到期,未到期给提示,到期下面直接给新的计算时间
+                long _runDay = DateUtil.getDays(DateUtil.getNowDate().getTime() - comPlayerDog.getEffectiveStartTime().getTime());
+                int _remainingDay = comPlayerDog.getEffectiveDay() - (int) _runDay;
+                if (_remainingDay > 0) {
+                    return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_HAVE.getMessage(), ResultEnum.PLAYER_OTHER_IS_HAVE.getCode());
+                }
+            }
+            // 防止重复操作
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                return Result.of(null, false, ResultEnum.REDIS_IS_LOCK.getMessage(), ResultEnum.REDIS_IS_LOCK.getCode());
+            }
+
+            ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+            Double _allSnb = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
+            //如果有snb,扣除对应的snb
+            Integer _allSnbMaxInt = (int) Math.floor(_allSnb);
+            if (_allSnbMaxInt < comMallOtherVo.getPriceSnb()) {
+                return Result.of(null, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
+            }
+            /**
+             * todo 购买装备时候snb变动
+             */
+            ComSnbTranVo _snbTran = new ComSnbTranVo();
+            _snbTran.setBeforeSnb(comUsersVo.getSnb());
+            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
+
+            Integer _tranSnb = _allSnbMaxInt - comMallOtherVo.getPriceSnb();
+            comUsersVo.setSnb(_tranSnb);
+            Double _SnbPart = DoubleUtil.sub(_allSnb, Math.floor(_allSnb));
+            comUsersVo.setSnbPart(_SnbPart);
+            //记录修改的数据
+            comUsersService.save(comUsersVo);
+
+            //记录交易数据
+            _snbTran.setTranId(mallOtherId.toString());
+            _snbTran.setUserId(userId);
+            if (comMallOtherVo.getOtherType().equals(0)) {
+                _snbTran.setTranName("购买狗");
+                _snbTran.setTranType(5);
+                _snbTran.setTranDescribe("购买了一只狗");
+            } else if (comMallOtherVo.getOtherType().equals(1)) {
+                _snbTran.setTranName("购买棒子");
+                _snbTran.setTranType(6);
+                _snbTran.setTranDescribe("购买了一根打狗棒");
+            }
+            _snbTran.setTranAmount(1);
+            _snbTran.setTranAmountPart(0d);
+            _snbTran.setTranPrice(comMallOtherVo.getPriceSnb());
+            _snbTran.setIsAdd(0);//减少
+            _snbTran.setTranSnb(comMallOtherVo.getPriceSnb());
+            _snbTran.setTranSnbPart(0d);
+            _snbTran.setAfterSnb(comUsersVo.getSnb());
+            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
+            comSnbTranService.save(_snbTran);
+
+            Date _nowDate = DateUtil.getNowDate();
+            if (comPlayerDog == null) {
+                comPlayerDog = new ComPlayerDog();
+                comPlayerDog.setOtherIndex(mallOtherId);
+                comPlayerDog.setOtherType(comMallOtherVo.getOtherType());
+                comPlayerDog.setUserId(userId);
+                comPlayerDog.setAmount(1);
+                comPlayerDog.setAmountPart(0d);
+                comPlayerDog.setEffectiveDay(comMallOtherVo.getEffectiveDay());
+                comPlayerDog.setEffectiveStartTime(_nowDate);
+                comPlayerDog.setConsumption(0);//狗的消耗品是狗粮
+                comPlayerDog.setConsumptionUpdate(_nowDate);
+                //记录一个最大值
+                comPlayerDog.setTotalConsumption(0);
+                comPlayerDog.setIsShow(1);//默认显示
+                comPlayerDog.setStartShowTime(_nowDate);
+            } else {
+                //重置新狗的有效时间
+                comPlayerDog.setEffectiveDay(comMallOtherVo.getEffectiveDay());
+                comPlayerDog.setEffectiveStartTime(_nowDate);
+            }
+            comPlayerDogService.save(CopyUtil.copy(comPlayerDog, ComPlayerDogVo.class));
+
+            //加入是否显示判断
+            long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
+            //隐藏计算
+            if (comPlayerDog.getIsShow().equals(0)) {
+                //计算双倍的时间
+                _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
+            }
+            long _consumptionHours = DateUtil.getDiffHours(_allTime);
+            int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;
+
+            ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
+            comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
+            comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
+
+            long _runDay = DateUtil.getDays(_nowDate.getTime() - comPlayerDog.getEffectiveStartTime().getTime());
+            int _remainingDay = comPlayerDog.getEffectiveDay() - (int) _runDay;
+            comPlayerDogSimpleVo.setRemainingDay(_remainingDay < 0 ? 0 : _remainingDay);
+            comPlayerDogSimpleVo.setTotalDay(comPlayerDog.getEffectiveDay());
+
+            redisLock.unlock(_redisKey, String.valueOf(time));
+
+            map.put("equip", comPlayerDogSimpleVo);
+            return Result.of(map);
+        } catch (Exception e) {
+            redisLock.unlock(_redisKey, String.valueOf(time));
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+
+    /**
+     * 添加狗粮
+     *
+     * @param userId
+     * @return
+     */
+    @PostMapping("addFood")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Map> addFoodFunction(@RequestParam(value = "userId") String userId,
+                                       @RequestParam(value = "foodId") Integer foodId,
+                                       @RequestParam(value = "buyAmount", defaultValue = "1") Integer buyAmount) {
+
+
+        //查看用户是否有狗
+        ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, 0);
+        if (comPlayerDog == null) {
+            return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_NULL.getMessage(), ResultEnum.PLAYER_OTHER_IS_NULL.getCode());
+        }
+
+        ComMallFoodVo comMallFoodVo = comMallFoodService.get(foodId).getData();
+        Map map = new HashMap();
+        if (comMallFoodVo == null) {
+            map.put("msg", "非法操作:所修改的种子不存在服务器中!");
+            return Result.of(map, false, ResultEnum.FOOD_DATA_ERROR.getMessage(), ResultEnum.FOOD_DATA_ERROR.getCode());
+        }
+        //todo snb加锁
+        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
+        String _redisKey = "SNB_SAVE_" + userId;
+        try {
+            //todo snb冻结加锁
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                return Result.of(null, false, ResultEnum.SEED_SALE_SAVE_LOCK.getMessage(), ResultEnum.SEED_SALE_SAVE_LOCK.getCode());
+            }
+            //todo 操作snb数量
+            ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+            /**
+             * todo 购买狗粮时候snb变动
+             */
+            ComSnbTranVo _snbTran = new ComSnbTranVo();
+            _snbTran.setBeforeSnb(comUsersVo.getSnb());
+            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
+            //计算
+            Double _allSnb = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
+            //如果有snb,扣除对应的snb
+            Integer _allSnbMaxInt = (int) Math.floor(_allSnb);
+            Integer _needPrice = buyAmount * comMallFoodVo.getPriceSnb();
+            if (_allSnbMaxInt < _needPrice) {
+                return Result.of(null, false, ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getMessage(), ResultEnum.WALLET_SNB_INSUFFICIENT_QUANTITY.getCode());
+            }
+            Integer _tranSnb = _allSnbMaxInt - _needPrice;
+            comUsersVo.setSnb(_tranSnb);
+            Double _SnbPart = DoubleUtil.sub(_allSnb, Math.floor(_allSnb));
+            comUsersVo.setSnbPart(_SnbPart);
+            //记录修改的数据
+            comUsersService.save(comUsersVo);
+
+            //修改狗的数据
+            Date _nowDate = DateUtil.getNowDate();
+            //加入是否显示判断
+            long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
+            //隐藏计算
+            if (comPlayerDog.getIsShow().equals(0)) {
+                //计算双倍的时间
+                _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
+                //计算了一次双时间,记录
+                comPlayerDog.setStartShowTime(_nowDate);
+            }
+            long _consumptionHours = DateUtil.getDiffHours(_allTime);
+            int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;
+
+            //判断狗粮是否消耗完,未消耗完叠加,消耗完重新设置
+            Integer _addWeight = buyAmount * comMallFoodVo.getWeight();
+            if (_remainingConsumption < 0) {
+                comPlayerDog.setConsumption(_addWeight);
+                //记录一个最大值
+                comPlayerDog.setTotalConsumption(_addWeight);
+            } else {
+                comPlayerDog.setConsumption(_remainingConsumption + _addWeight);
+                //记录一个最大值,已当前更新为主
+                comPlayerDog.setTotalConsumption(_remainingConsumption + _addWeight);
+            }
+
+            comPlayerDog.setConsumptionUpdate(_nowDate);
+            comPlayerDogService.save(CopyUtil.copy(comPlayerDog, ComPlayerDogVo.class));
+
+            //记录交易数据
+            _snbTran.setTranId(foodId.toString());
+            _snbTran.setUserId(userId);
+            _snbTran.setTranName("购买狗粮");
+            _snbTran.setTranType(7);
+            _snbTran.setTranDescribe("购买狗粮类型:" + comMallFoodVo.getMallType() + ",Weight:" + comMallFoodVo.getWeight());
+            _snbTran.setTranAmount(comMallFoodVo.getWeight());
+            _snbTran.setTranAmountPart(0d);
+            _snbTran.setTranPrice(comMallFoodVo.getPriceSnb());
+            _snbTran.setIsAdd(0);//减少
+            _snbTran.setTranSnb(_needPrice);
+            _snbTran.setTranSnbPart(0d);
+            _snbTran.setAfterSnb(comUsersVo.getSnb());
+            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
+            comSnbTranService.save(_snbTran);
+
+            redisLock.unlock(_redisKey, String.valueOf(time));
+
+            ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
+            comPlayerDogSimpleVo.setRemainingConsumption(comPlayerDog.getConsumption());
+            ComMallOtherVo comMallOtherVo = comMallOtherService.get(comPlayerDog.getOtherIndex()).getData();
+            comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
+            long _runDay = DateUtil.getDays(_nowDate.getTime() - comPlayerDog.getEffectiveStartTime().getTime());
+            int _remainingDay = comPlayerDog.getEffectiveDay() - (int) _runDay;
+            comPlayerDogSimpleVo.setRemainingDay(_remainingDay < 0 ? 0 : _remainingDay);
+            comPlayerDogSimpleVo.setTotalDay(comPlayerDog.getEffectiveDay());
+
+            map.put("dog", comPlayerDogSimpleVo);
+            map.put("snb", comUsersVo.getSnb().doubleValue());
+            map.put("snbPart", comUsersVo.getSnbPart());
+
+            return Result.of(map);
+        } catch (Exception e) {
+            redisLock.unlock(_redisKey, String.valueOf(time));
+            throw new RuntimeException(e.getMessage());
+        }
+    }
+
+    @GetMapping("getEquipmentByType")
+    public Result<ComPlayerDogSimpleVo> getEquipmentByTypeFunction(@RequestParam(value = "userId") String userId,
+                                                                   @RequestParam(value = "type") Integer type) {
+
+        ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, type);
+        if (comPlayerDog == null) {
+            return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_NULL.getMessage(), ResultEnum.PLAYER_OTHER_IS_NULL.getCode());
+        }
+        ComMallOtherVo comMallOtherVo = comMallOtherService.get(comPlayerDog.getOtherIndex()).getData();
+        if (comMallOtherVo == null) {
+            return Result.of(null, false, ResultEnum.MALL_OTHER_IS_NULL.getMessage(), ResultEnum.MALL_OTHER_IS_NULL.getCode());
+        }
+        Date _nowDate = DateUtil.getNowDate();
+        //加入是否显示判断
+        long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
+        //隐藏计算
+        if (comPlayerDog.getIsShow().equals(0)) {
+            //计算双倍的时间
+            _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
+        }
+        long _consumptionHours = DateUtil.getDiffHours(_allTime);
+        int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;
+        ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
+        comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
+        comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
+
+        return Result.of(comPlayerDogSimpleVo);
+    }
+
+    @GetMapping("getListEquipment")
+    public Result<List<ComPlayerDogSimpleVo>> getListEquipmentFunction(@RequestParam(value = "userId") String userId,
+                                                                       @RequestParam(value = "otherUserId", required = false) String otherUserId) {
+
+        String currentUserId = userId;
+        if (StringUtils.hasText(otherUserId)) {
+            currentUserId = otherUserId;
+        }
+
+
+        List<ComPlayerDog> comPlayerDogList = comPlayerDogService.findAllByUserId(currentUserId);
+        List<ComPlayerDogSimpleVo> comPlayerDogSimpleVos = new ArrayList<>();
+
+        Date _nowDate = DateUtil.getNowDate();
+        comPlayerDogList.stream().map(e -> {
+            ComMallOtherVo comMallOtherVo = comMallOtherService.get(e.getOtherIndex()).getData();
+            if (comMallOtherVo == null) {
+                return null;
+            }
+            ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(e, ComPlayerDogSimpleVo.class);
+            comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
+            long _runDay = DateUtil.getDays(_nowDate.getTime() - e.getEffectiveStartTime().getTime());
+            int _remainingDay = e.getEffectiveDay() - (int) _runDay;
+            comPlayerDogSimpleVo.setRemainingDay(_remainingDay < 0 ? 0 : _remainingDay);
+            comPlayerDogSimpleVo.setTotalDay(e.getEffectiveDay());
+            //加入是否显示判断
+            long _allTime = _nowDate.getTime() - e.getConsumptionUpdate().getTime();
+            //隐藏计算
+            if (e.getIsShow().equals(0)) {
+                //计算双倍的时间
+                _allTime = _nowDate.getTime() * 2 - e.getConsumptionUpdate().getTime() - e.getStartShowTime().getTime();
+            }
+            long _consumptionHours = DateUtil.getDiffHours(_allTime);
+            int _remainingConsumption = e.getConsumption() - (int) _consumptionHours;
+            comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
+            return comPlayerDogSimpleVos.add(comPlayerDogSimpleVo);
+
+        }).collect(Collectors.toList());
+
+        return Result.of(comPlayerDogSimpleVos);
+    }
+
+
+    /**
+     * 设置狗的显示状态
+     *
+     * @param userId
+     * @param isShow
+     * @return
+     */
+    @PostMapping("setDogShowState")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Map> setDogShowStateFunction(@RequestParam(value = "userId") String userId,
+                                               @RequestParam(value = "isShow") Integer isShow) {
+
+        //查看用户是否有狗
+        ComPlayerDog comPlayerDog = comPlayerDogService.findByUserIdAndType(userId, 0);
+        if (comPlayerDog == null) {
+            return Result.of(null, false, ResultEnum.PLAYER_OTHER_IS_NULL.getMessage(), ResultEnum.PLAYER_OTHER_IS_NULL.getCode());
+        }
+        Map map = new HashMap();
+        //todo 判断是否是隐藏属性,更新一次狗的狗粮数据。隐藏需要双倍处理扣除
+        //修改狗的数据
+        Date _nowDate = DateUtil.getNowDate();
+        //加入是否显示判断
+        long _allTime = _nowDate.getTime() - comPlayerDog.getConsumptionUpdate().getTime();
+        //隐藏计算
+        if (comPlayerDog.getIsShow().equals(0)) {
+            //计算双倍的时间
+            _allTime = _nowDate.getTime() * 2 - comPlayerDog.getConsumptionUpdate().getTime() - comPlayerDog.getStartShowTime().getTime();
+        }
+        long _consumptionHours = DateUtil.getDiffHours(_allTime);
+        int _remainingConsumption = comPlayerDog.getConsumption() - (int) _consumptionHours;
+        //计算对应的狗粮
+        comPlayerDog.setConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
+        comPlayerDog.setConsumptionUpdate(_nowDate);
+        //更新状态
+        comPlayerDog.setIsShow(isShow);
+        comPlayerDog.setStartShowTime(_nowDate);
+        comPlayerDogService.save(CopyUtil.copy(comPlayerDog, ComPlayerDogVo.class));
+        ComPlayerDogSimpleVo comPlayerDogSimpleVo = CopyUtil.copy(comPlayerDog, ComPlayerDogSimpleVo.class);
+        comPlayerDogSimpleVo.setRemainingConsumption(_remainingConsumption < 0 ? 0 : _remainingConsumption);
+        ComMallOtherVo comMallOtherVo = comMallOtherService.get(comPlayerDog.getOtherIndex()).getData();
+        comPlayerDogSimpleVo.setMallOther(CopyUtil.copy(comMallOtherVo, ComMallOtherSimpleVo.class));
+        map.put("dog", comPlayerDogSimpleVo);
+        return Result.of(map);
+    }
+
+}

+ 43 - 0
src/main/java/com/td/boss/game/complayerdog/pojo/ComPlayerDog.java

@@ -0,0 +1,43 @@
+package com.td.boss.game.complayerdog.pojo;
+
+import lombok.Data;
+import javax.persistence.*;
+import java.io.Serializable;
+import java.util.Date;
+
+@Entity
+@Table(name = "com_player_dog")
+@Data
+public class ComPlayerDog implements Serializable {
+    @Id
+    private String id;//物品id,字符串
+
+    private Integer otherIndex;//仓库物品下标, 根据类型区分。比如狗type=0,index=狗id,
+
+    private Integer otherType;//对应类型(0:看护狗,1:打狗棒)
+
+    private String userId;//
+
+    private Integer amount;//数量
+
+    private Double amountPart;//amount增加部分,目前用于收取其他用户部分处理数据
+
+    private Integer effectiveDay;//物品的有效时间
+
+    private Date effectiveStartTime;//有效的开始时间,比如买狗了,生效时间
+
+    private Integer consumption;//当前物品对应的消耗品数量
+
+    private Date consumptionUpdate;//消耗品的更新时间
+
+    private Integer totalConsumption;//使用过的狗粮总量
+
+    private Integer isShow;//是否显示狗,用户其他农场显示 默认显示: 1 ,隐藏:0
+
+    private Date startShowTime;//切换状态时候,更新一下这个显示的时间,用来计算双倍狗粮
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 17 - 0
src/main/java/com/td/boss/game/complayerdog/repository/ComPlayerDogRepository.java

@@ -0,0 +1,17 @@
+package com.td.boss.game.complayerdog.repository;
+
+import com.td.boss.common.repository.*;
+import com.td.boss.game.complayerdog.pojo.ComPlayerDog;
+import org.springframework.stereotype.Repository;
+import org.springframework.util.StringUtils;
+
+import java.util.List;
+import java.util.Optional;
+
+@Repository
+public interface ComPlayerDogRepository extends CommonRepository<ComPlayerDog, String> {
+
+    Optional<ComPlayerDog> findByUserIdAndOtherType(String userId,Integer OtherType);
+
+    List<ComPlayerDog> findAllByUserId(String userId);
+}

+ 14 - 0
src/main/java/com/td/boss/game/complayerdog/service/ComPlayerDogService.java

@@ -0,0 +1,14 @@
+package com.td.boss.game.complayerdog.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayerdog.pojo.ComPlayerDog;
+import com.td.boss.game.complayerdog.vo.ComPlayerDogVo;
+
+import java.util.List;
+
+public interface ComPlayerDogService extends CommonService<ComPlayerDogVo, ComPlayerDog, String> {
+
+    ComPlayerDog findByUserIdAndType(String userId,Integer otherType);
+
+    List<ComPlayerDog> findAllByUserId(String userId);
+}

+ 35 - 0
src/main/java/com/td/boss/game/complayerdog/service/ComPlayerDogServiceImpl.java

@@ -0,0 +1,35 @@
+package com.td.boss.game.complayerdog.service;
+
+import com.td.boss.common.service.*;
+import com.td.boss.game.complayerdog.pojo.ComPlayerDog;
+import com.td.boss.game.complayerdog.vo.ComPlayerDogVo;
+import com.td.boss.game.complayerdog.repository.ComPlayerDogRepository;
+import com.td.boss.util.CopyUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import javax.persistence.EntityManager;
+import javax.persistence.PersistenceContext;
+import java.util.List;
+
+@Service
+@Transactional
+public class ComPlayerDogServiceImpl extends CommonServiceImpl<ComPlayerDogVo, ComPlayerDog, String> implements ComPlayerDogService{
+
+    @PersistenceContext
+    private EntityManager em;
+    @Autowired
+    private ComPlayerDogRepository comPlayerDogRepository;
+
+
+    @Override
+    public ComPlayerDog findByUserIdAndType(String userId, Integer otherType) {
+        ComPlayerDog comPlayerDog = comPlayerDogRepository.findByUserIdAndOtherType(userId, otherType).orElse(null);
+        return comPlayerDog;
+    }
+
+    @Override
+    public List<ComPlayerDog> findAllByUserId(String userId) {
+        return comPlayerDogRepository.findAllByUserId(userId);
+    }
+}

+ 45 - 0
src/main/java/com/td/boss/game/complayerdog/vo/ComPlayerDogSimpleVo.java

@@ -0,0 +1,45 @@
+package com.td.boss.game.complayerdog.vo;
+
+import com.td.boss.common.pojo.PageCondition;
+import com.td.boss.game.commallother.vo.ComMallOtherSimpleVo;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComPlayerDogSimpleVo implements Serializable {
+
+    private ComMallOtherSimpleVo mallOther; //返回一个对象
+
+    private Integer otherType;//商城类型,默认是小狗0,1打狗棒
+
+    private Integer amount;//数量
+
+    private Double amountPart;//amount增加部分,目前用于收取其他用户部分处理数据
+
+    //private Integer effectiveDay;//物品的有效时间
+    //
+    //private Date effectiveStartTime;//有效的开始时间,比如买狗了,生效时间
+
+    private Integer remainingDay; //剩余天数
+
+    private Integer totalDay;//全部天数
+
+    //private Integer consumption;//当前物品对应的消耗品数量
+    //
+    //private Date consumptionUpdate;//消耗品的更新时间
+
+    private Integer remainingConsumption; //剩余消耗品。狗粮
+
+    private Integer totalConsumption;//当前全部的狗粮
+
+    private Integer isShow;//是否显示狗,用户其他农场显示 默认显示: 1 ,隐藏:0
+
+    //private Date startShowTime;//切换状态时候,更新一下这个显示的时间,用来计算双倍狗粮
+
+    //private Date createTime;//
+
+    //private Date updateTime;//
+
+}

+ 39 - 0
src/main/java/com/td/boss/game/complayerdog/vo/ComPlayerDogVo.java

@@ -0,0 +1,39 @@
+package com.td.boss.game.complayerdog.vo;
+
+import com.td.boss. common.pojo.PageCondition;import lombok.Data;
+import java.io.Serializable;
+import java.util.Date;
+
+@Data
+public class ComPlayerDogVo extends PageCondition implements Serializable {
+    private String id;//物品id,字符串
+
+    private Integer otherIndex;//仓库物品下标, 根据类型区分。比如狗type=0,index=狗id,
+
+    private Integer otherType;//对应类型(0:看护狗,1:打狗棒)
+
+    private String userId;//
+
+    private Integer amount;//数量
+
+    private Double amountPart;//amount增加部分,目前用于收取其他用户部分处理数据
+
+    private Integer effectiveDay;//物品的有效时间
+
+    private Date effectiveStartTime;//有效的开始时间,比如买狗了,生效时间
+
+    private Integer consumption;//当前物品对应的消耗品数量
+
+    private Date consumptionUpdate;//消耗品的更新时间
+
+    private Integer totalConsumption;//当前全部的狗粮
+
+    private Integer isShow;//是否显示狗,用户其他农场显示 默认显示: 1 ,隐藏:0
+
+    private Date startShowTime;//切换状态时候,更新一下这个显示的时间,用来计算双倍狗粮
+
+    private Date createTime;//
+
+    private Date updateTime;//
+
+}

+ 452 - 23
src/main/java/com/td/boss/game/complayergoods/controller/ComPlayerGoodsController.java

@@ -9,13 +9,20 @@ import com.td.boss.game.comfruit.pojo.ComFruit;
 import com.td.boss.game.comfruit.service.ComFruitService;
 import com.td.boss.game.comfruit.vo.ComFruitAmountVo;
 import com.td.boss.game.comfruit.vo.ComFruitVo;
+import com.td.boss.game.commallother.pojo.ComMallOther;
+import com.td.boss.game.commallother.service.ComMallOtherService;
+import com.td.boss.game.commallother.vo.ComMallOtherVo;
 import com.td.boss.game.commallseed.service.ComMallSeedService;
 import com.td.boss.game.commallseed.vo.ComMallSeedVo;
+import com.td.boss.game.complayerdog.pojo.ComPlayerDog;
+import com.td.boss.game.complayerdog.service.ComPlayerDogService;
+import com.td.boss.game.complayerdog.vo.ComPlayerDogVo;
 import com.td.boss.game.complayergoods.pojo.ComPlayerGoods;
 import com.td.boss.game.complayergoods.vo.ComPlayerGoodsSimpleVo;
 import com.td.boss.game.complayergoods.vo.ComPlayerGoodsVo;
 import com.td.boss.game.complayergoods.service.ComPlayerGoodsService;
 import com.td.boss.game.complayerland.pojo.ComPlayerLand;
+import com.td.boss.game.complayerland.pojo.ComPlayerLandAndCanSteal;
 import com.td.boss.game.complayerland.service.ComPlayerLandService;
 import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
 import com.td.boss.game.complayerlog.pojo.ComPlayerLog;
@@ -84,8 +91,12 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
     @Autowired
     private ComSettingService comSettingService;
 
+    @Autowired
+    private ComPlayerDogService comPlayerDogService;
+
+    @Autowired
+    private ComMallOtherService comMallOtherService;
 
-    private static final int TIMEOUT = 10 * 1000; //超时时间 10s
 
     @Autowired
     private RedisLock redisLock;
@@ -234,13 +245,14 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
         }
 
         //需要redis 加锁
-        long time = System.currentTimeMillis() + TIMEOUT;
+        long time = System.currentTimeMillis() + RedisData.getPlayerGoodsTimeout();
         //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
         String _redisKey = comPlayerLand.getPlantFlag();
         if (!StringUtils.hasText(_redisKey)) {
             //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
             _redisKey = comPlayerLand.getUserId() + "or" + comPlayerLand.getConfigLandId();
         }
+        Map map = new HashMap();
         //todo 总共偷去的数量
         Double _stealProfits = 0d;
         try {
@@ -275,7 +287,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             Double _stealAmount = DoubleUtil.sub(_profitDouble, _residualProfit); //可偷取的利润
 
             //todo 计算总共损失的数量
-            List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(userId, comPlayerLand.getPlantFlag(), comPlayerLand.getConfigLandId());
+            List<ComPlayerProfit> comPlayerProfits = comPlayerProfitService.findByUserIdAndPlantFlagAndLandId(userId, _redisKey, comPlayerLand.getConfigLandId());
             for (int i = 0; i < comPlayerProfits.size(); i++) {
                 ComPlayerProfit temp = comPlayerProfits.get(i);
                 _stealProfits = DoubleUtil.add(_stealProfits, temp.getStolen());
@@ -284,7 +296,13 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             if (_userHarvestPart < 0.0) {
                 //差值不能为负数
                 _userHarvestPart = 0d;
+                //相当于被偷取全部利润,这里返回一个被偷去的全部利润值
+                map.put("lossAmount", _stealAmount);
+            } else {
+                //todo 返回一个被偷的数量
+                map.put("lossAmount", _stealProfits);
             }
+
             //todo 利润
             _amount -= _profit;
             //用户收取的对应数量,固定收入+被偷取后剩余的部分
@@ -348,14 +366,374 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             redisLock.unlock(_redisKey, String.valueOf(time));
             throw new RuntimeException(e.getMessage());
         }
-
-        Map map = new HashMap();
         map.put("msg", "成功收取果实!");
-        //todo 返回一个被偷的数量
-        map.put("lossAmount",_stealProfits);
         return Result.of(map);
     }
 
+    /**
+     * 按土地收取水果果实时候,传入对方用户id 和土地id
+     * <p>
+     * <p>
+     * 收获时候,操作用户snb时候,需要加锁,防止用户收取时候遗漏计算snb
+     *
+     * @param otherUserId
+     * @param otherLandId
+     * @return
+     */
+    @PostMapping("stealFruit")
+    @ResponseBody
+    @Transactional(rollbackFor = Exception.class)
+    public Result<Map> stealFruitFunction(
+            @RequestParam(value = "userId") String userId,
+            @RequestParam(value = "otherUserId") String otherUserId,
+            @RequestParam(value = "otherLandId") Integer otherLandId) {
+        Map map = new HashMap();
+
+        //todo 计入狗和打狗棒
+        Boolean _dogWork = false;//狗是否工作,默认不工作
+        Boolean _wasTheDogBitten = false; //默认没有被狗咬
+        Boolean _holdTheStick = false;//默认没持有棒子
+        Boolean _hasReduceSnb = false;//是否可以扣除偷菜的snb
+        //对方的狗
+        ComPlayerDog _otherDogVo = comPlayerDogService.findByUserIdAndType(otherUserId, 0);
+        if (_otherDogVo != null) {
+            //有狗或者有狗粮时候,处理狗的事件
+            //todo 计算狗是否到期
+            long _runDay = DateUtil.getDays(DateUtil.getNowDate().getTime() - _otherDogVo.getEffectiveStartTime().getTime());
+            int _remainingDay = _otherDogVo.getEffectiveDay() - (int) _runDay;
+            // 存在时间
+            if (_remainingDay > 0) {
+                //todo 这里判断狗粮是否足够
+                long _diffConsumptionMill = _otherDogVo.getConsumptionUpdate().getTime() - DateUtil.getNowDate().getTime();
+                long _workHours = DateUtil.getHours(_diffConsumptionMill);
+                //工作多少个小时,消耗多少狗粮
+                long _needConsumption = _otherDogVo.getConsumption() - _workHours;
+                if (_needConsumption > 0) {
+                    //口粮足够,工作
+                    _dogWork = true;
+                    //狗存在并工作,获取狗的数据
+                    ComMallOtherVo _mallDogData = comMallOtherService.get(_otherDogVo.getOtherIndex()).getData();
+                    Double _triggerPro = _mallDogData.getTriggerPro();//触发概率
+                    if (new Random().nextDouble() <= _triggerPro) {
+                        //被狗咬了
+                        _wasTheDogBitten = true;
+                    }
+                }
+            }
+
+        }
+
+        //
+        //己方的打狗棒
+        ComPlayerDog _beatDogStick = comPlayerDogService.findByUserIdAndType(userId, 1);
+
+        if (_beatDogStick != null) {
+            //todo 判断打狗棒是否到期
+            long _stickRunDay = DateUtil.getDays(DateUtil.getNowDate().getTime() - _beatDogStick.getEffectiveStartTime().getTime());
+            int _stickRemainingDay = _beatDogStick.getEffectiveDay() - (int) _stickRunDay;
+            if(_stickRemainingDay>0){
+                //持有打狗棒
+                _holdTheStick = true;
+            }
+        }
+
+        //获取数据库相关配置
+        ComSettingVo comSettingVo = comSettingService.get("1").getData();
+        if (comSettingVo.equals(null)) {
+            return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
+        }
+        //todo 后台可配置,获取一个链上数据
+        Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = DappUtil.getChildrenCount(userId);
+        //前端的显示,输出一个不小于0的体力值
+        Integer _maxStrength = _configStrength + _chainStrength;
+        //1.先判断用户是否有足够的体力,根据snb判断。2. 收取到果实,扣除用户一个体力值
+        ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+        ComPlayersAttriVo playersAttribute = comPlayersAttriService.findByUserId(userId);
+        Integer _out = _maxStrength - Math.abs(playersAttribute.getStrength());
+        Double _userAllSnb = DoubleUtil.add(comUsersVo.getSnb().doubleValue(), comUsersVo.getSnbPart());
+        //判断是否有足够的snb
+        if (DoubleUtil.compare(_userAllSnb, comSettingVo.getDeductSnb()) == -1) {
+            _hasReduceSnb = false;
+            //没有足够的snb
+            //如果没有被狗咬,,正常扣除1点体力
+            //如果被狗咬了,除了正常扣除1点体力外,额外扣除1点体力
+            if (_wasTheDogBitten) {
+                //判断是否有双倍体力
+                if (_out < comSettingVo.getSnbUnitStrength()) {
+                    map.put("msg", "需要双倍体力:" + comSettingVo.getSnbUnitStrength());
+                    return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
+                }
+            }
+        } else {
+            _hasReduceSnb = true;
+            //正常判断体力
+            if (_out < comSettingVo.getUnitStrength()) {
+                map.put("msg", "需要单倍体力:" + comSettingVo.getUnitStrength());
+                return Result.of(map, false, ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getMessage(), ResultEnum.PLAYER_ATTRIBUTE_STRENGTH_IS_NOT.getCode());
+            }
+        }
+
+        //List<Map> _stealLandInfos = new ArrayList<>();
+        Double _finalStealAmountSum = 0d;
+        //todo 偷取用户目标的信息,即otherUserId和otherLandId
+        ComPlayerLand otherPlayerLand = comPlayerLandService.findByUserIdAndLandId(otherUserId, otherLandId);
+        if (otherPlayerLand == null) {
+            return Result.of(null, false, ResultEnum.LAND_CAN_STEAL_IS_NULL.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_NULL.getCode());
+        }
+        //snb 的key
+        String _redisSNBKey = "SNB_SAVE_" + userId;
+        //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
+        String _redisKey = otherPlayerLand.getPlantFlag();
+        if (!StringUtils.hasText(_redisKey)) {
+            //return Result.of(null, false, ResultEnum.LAND_PLANT_FLAG_IS_NULL.getMessage(), ResultEnum.LAND_PLANT_FLAG_IS_NULL.getCode());
+            _redisKey = otherPlayerLand.getUserId() + "or" + otherPlayerLand.getConfigLandId();
+        }
+        //todo 先判断是否偷取过
+        ComPlayerProfit comPlayerProfit = comPlayerProfitService.findByUserIdAndOtherUserIdAndPlantFlag(userId, otherUserId, _redisKey);
+        if (comPlayerProfit != null) {
+            return Result.of(null, false, ResultEnum.LAND_HARVEST_STOLEN.getMessage(), ResultEnum.LAND_HARVEST_STOLEN.getCode());
+        }
+        //获取当前种植的种子
+        ComMallSeedVo comMallSeedVo = comMallSeedService.findById(otherPlayerLand.getPlantId());
+        //需要redis 加锁
+        long time = System.currentTimeMillis() + RedisData.getPlayerGoodsTimeout();
+
+        try {
+            if (!redisLock.lock(_redisSNBKey, String.valueOf(time))) {
+                //如果有snb冲突锁
+                return Result.of(null, false, ResultEnum.USER_LOGIN_LOCK.getMessage(), ResultEnum.USER_LOGIN_LOCK.getCode());
+
+            }
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                //如果有冲突锁
+                return Result.of(null, false, ResultEnum.LAND_STEAL_LOCK.getMessage(), ResultEnum.LAND_STEAL_LOCK.getCode());
+            }
+            //todo 如果当前人员偷窃水果。记录一个信息,存储当前玩家已偷过的水果的信息
+            //计算一个偷取的收获量, 租赁倍数* 租赁日期下的产量
+            Integer _otherAmount = 0;
+            if (otherPlayerLand.getLeaseDate().equals(1)) {
+                _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest1();
+            } else if (otherPlayerLand.getLeaseDate().equals(2)) {
+                _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest2();
+            } else if (otherPlayerLand.getLeaseDate().equals(3)) {
+                _otherAmount = otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getHarvest3();
+            }
+            //todo 拿出计算利润,收获量减去种子的成本(snb)后的百分之30 ,后面需要后台可调整
+            Integer _profit = _otherAmount - otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb();
+            // 配置的参数。这里先直接定义
+            // 需要根据 狗是否生效,小偷是否装备打狗棒来确定参数
+            Double profitConfig = _dogWork ? comSettingVo.getProfitDog() : comSettingVo.getProfit(),
+                    stealRatioMaxConfig = comSettingVo.getStealMaxRatio(),
+                    stealRatioMinConfig = comSettingVo.getStealMinRatio(),
+                    finallyGetRatioConfig = comSettingVo.getFinalRatio();
+            Double _stealRatio = new Random().nextDouble() * DoubleUtil.sub(stealRatioMaxConfig, stealRatioMinConfig) + stealRatioMinConfig;// 1%-3%
+            //todo 被偷取的人扣除 一个损失量,初利润算 _profit
+            //  如果狗生效,根据装备了打狗棒,设置对应的偷窃比例
+            if (_dogWork) {
+                _stealRatio = _holdTheStick ? comSettingVo.getStealRatioHasStick() : comSettingVo.getStealRatioNoStick();
+            }
+            Double _stolenAmount = DoubleUtil.mul(_profit.doubleValue(), _stealRatio);
+            //这里根据plantFlag判断目标用户当前种植被偷取完,记录更新用户 comPlayerLand plantSteal 字段;保存一个偷取状态
+            Double _sumStolen = comPlayerProfitService.getStolenSumByOtherUserIdAndPlantFlag(otherUserId, _redisKey);
+            //todo 这里的可偷利润应该是最大值,用户不能超过这个,需要限制判断
+            Double _maxAmount = DoubleUtil.mul(_profit.doubleValue(), profitConfig); //可偷取的利润
+            //1 单偷操作 就是 _sumStolen>_maxAmount 或者 _sumStolen == _maxAmount ,被偷完了
+            if (!DoubleUtil.compare(_sumStolen, _maxAmount).equals(-1)) {
+                // 需要redis 解锁
+                redisLock.unlock(_redisKey, String.valueOf(time));
+                redisLock.unlock(_redisSNBKey, String.valueOf(time));
+                //记录一个不可偷取的状态
+                otherPlayerLand.setPlantSteal(0);
+                comPlayerLandService.save(CopyUtil.copy(otherPlayerLand, ComPlayerLandVo.class));
+                map.put("plant_steal", otherPlayerLand.getPlantSteal());
+                return Result.of(map, false, ResultEnum.LAND_CAN_STEAL_IS_MAX.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_MAX.getCode());
+            }
+            //计算剩下可偷利润的差,防止过多偷取用户利润 _stolenAmount
+            Double _diff = Math.abs(DoubleUtil.sub(_maxAmount, _sumStolen));
+            if (DoubleUtil.compare(_stolenAmount, _diff).equals(1)) {
+                //_stolenAmount>_diff
+                _stolenAmount = _diff;
+            }
+            //最终偷窃人获取的是偷取的是目标用户损失量的10% finallyGetRatioConfig
+            Double _finalStealAmount = DoubleUtil.mul(_stolenAmount, finallyGetRatioConfig);
+            //偷窃后,系统回收部分
+            Double _lostStealAmount = DoubleUtil.sub(1d, finallyGetRatioConfig) * _stolenAmount;
+            //果实 Type =1
+            //todo 增加一个字段处理背包果实,拿出当前用户背包果实
+            ComPlayerGoods comPlayerGoods = comPlayerGoodsService.findByUserIdAndIndexAndType(userId, comMallSeedVo.getHarvestId(), 1);
+            Double _beforeStealAmount = 0.0;
+            if (comPlayerGoods == null) {
+                //背包增加收取到别的用户对应的类型数量。比如当前是偷取到的果实
+                comPlayerGoods = new ComPlayerGoods();
+                comPlayerGoods.setUserId(userId);
+                comPlayerGoods.setGoodsIndex(comMallSeedVo.getHarvestId());
+                comPlayerGoods.setGoodsType(1);
+                comPlayerGoods.setName(comMallSeedVo.getHarvestName());
+                //用种子的picture
+                comPlayerGoods.setPictureName(comMallSeedVo.getPicture());
+                //amount 设置0
+                comPlayerGoods.setAmount(0);
+                comPlayerGoods.setAmountPart(_finalStealAmount);
+                _beforeStealAmount = 0.0;
+            } else {
+                _beforeStealAmount = comPlayerGoods.getAmountPart();
+                //修改偷取字段
+                comPlayerGoods.setAmountPart(DoubleUtil.add(comPlayerGoods.getAmountPart(), _finalStealAmount));
+            }
+            ComPlayerGoodsVo comPlayerGoodsVo = CopyUtil.copy(comPlayerGoods, ComPlayerGoodsVo.class);
+            comPlayerGoodsService.save(comPlayerGoodsVo);
+
+            //todo 偷窃损失,处理目标用户收取果实时候,减扣一部分被偷取的数量
+            comPlayerProfit = new ComPlayerProfit();
+            comPlayerProfit.setUserId(userId);
+            comPlayerProfit.setTargetId(otherUserId);
+            comPlayerProfit.setPlantFlag(_redisKey);
+            comPlayerProfit.setLandId(otherPlayerLand.getConfigLandId());
+            comPlayerProfit.setLeaseMultiple(otherPlayerLand.getLeaseMultiple());
+            comPlayerProfit.setLeaseDate(otherPlayerLand.getLeaseDate());
+            comPlayerProfit.setHarvest(_otherAmount);
+            comPlayerProfit.setProfit(_profit.doubleValue());//目标用户可偷的初始利润值
+            comPlayerProfit.setStolen(_stolenAmount);//目标用户被偷的数量
+            comPlayerProfit.setFinalSteal(_finalStealAmount);//用户最终偷取的量,是被偷的数量 10%左右
+            comPlayerProfit.setProfitAfter(DoubleUtil.sub(_profit.doubleValue(), DoubleUtil.add(_stolenAmount, _sumStolen))); //可偷的减去被偷的
+            //记录相关比例
+            comPlayerProfit.setProfitRatio(profitConfig);
+            comPlayerProfit.setStealRatio(_stealRatio);
+            comPlayerProfit.setFinalRatio(finallyGetRatioConfig);
+            ComPlayerProfitVo comPlayerProfitVo = CopyUtil.copy(comPlayerProfit, ComPlayerProfitVo.class);
+            comPlayerProfitService.save(comPlayerProfitVo);
+
+            //todo 记录一个收获的操作日志,这里的数量都与偷窃知道相关。amountPart,注意不是果实实际总数 amount
+            ComPlayerLog _playerLog = new ComPlayerLog();
+            _playerLog.setUserId(userId);
+            _playerLog.setTId(comMallSeedVo.getHarvestId());
+            _playerLog.setTName(comMallSeedVo.getHarvestName());
+            _playerLog.setTType(6);//偷取果实时候,type设置6
+            //偷水果时候这部分数据应该是不变的
+            _playerLog.setTAmount(0);
+            _playerLog.setBeforeAmount(comPlayerGoods.getAmount());
+            _playerLog.setAfterAmount(comPlayerGoods.getAmount());
+            //偷取用户果实时候,收取时候信息记录
+            _playerLog.setBeforePart(_beforeStealAmount);
+            _playerLog.setTPart(_finalStealAmount);
+            _playerLog.setTLoss(_lostStealAmount); //损失的部分
+            _playerLog.setAfterPart(comPlayerGoods.getAmountPart());
+            _playerLog.setLMultiple(otherPlayerLand.getLeaseMultiple());
+            ComPlayerLogVo _playerLogVo = CopyUtil.copy(_playerLog, ComPlayerLogVo.class);
+            comPlayerLogService.save(_playerLogVo);
+
+            //todo 成功收取记录一个土地id
+            Map _landMap = new HashMap();
+            //记录一个id
+            _landMap.put("landId", otherPlayerLand.getConfigLandId());
+            //
+            _landMap.put("stealAmount", _finalStealAmount);
+
+            //固定成本
+            _landMap.put("cost", otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb());
+            //当前利润
+            _landMap.put("profit", _profit);
+            //打印一个比例
+            _landMap.put("profitRatio", profitConfig);
+            _landMap.put("intervalStealRatio", _stealRatio);
+            _landMap.put("finallyGetRatioConfig", finallyGetRatioConfig);
+
+            _finalStealAmountSum = DoubleUtil.add(_finalStealAmount, _finalStealAmountSum);
+            // 需要redis 解锁
+            redisLock.unlock(_redisKey, String.valueOf(time));
+
+            map.put("msg", "偷取果实.");
+            map.put("stealInfo", _landMap);
+            map.put("stealSum", _finalStealAmountSum);
+
+            //todo 体力值可以后台配置
+            Integer _addStrength = comSettingVo.getUnitStrength();
+            if (_hasReduceSnb) {
+                /**
+                 * todo 偷取果实时候snb变动
+                 */
+                ComSnbTranVo _snbTran = new ComSnbTranVo();
+                _snbTran.setBeforeSnb(comUsersVo.getSnb());
+                _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
+
+                //如果有snb,扣除对应的snb
+                //先判断 SnbPart 部分是否有足够来扣取
+                if (DoubleUtil.compare(comUsersVo.getSnbPart(), comSettingVo.getDeductSnb()) == -1) {
+                    //如果不足,取1扣取
+                    Integer _deductSnbMaxInt = (int) Math.ceil(comSettingVo.getDeductSnb());
+                    comUsersVo.setSnb(comUsersVo.getSnb() - _deductSnbMaxInt);
+                    Double _deductSnbPart = DoubleUtil.sub(1d, comSettingVo.getDeductSnb());
+                    comUsersVo.setSnbPart(DoubleUtil.add(comUsersVo.getSnbPart(), _deductSnbPart));
+
+                    _snbTran.setTranSnb(0);
+                    _snbTran.setTranSnbPart(comSettingVo.getDeductSnb());
+                } else {
+                    //直接用snbPart 减去小数点部分即可
+                    Double _deductSnbPart = DoubleUtil.sub(comUsersVo.getSnbPart(), comSettingVo.getDeductSnb());
+                    comUsersVo.setSnbPart(_deductSnbPart);
+                    _snbTran.setTranSnb(0);//整数部分没有进行交易
+                    _snbTran.setTranSnbPart(comSettingVo.getDeductSnb());
+                }
+                //记录修改的数据
+                comUsersService.save(comUsersVo);
+
+                //记录果实id,记录交易数据
+                _snbTran.setTranId(comMallSeedVo.getHarvestId().toString());
+                _snbTran.setUserId(userId);
+                _snbTran.setTranName("偷取果实");
+                _snbTran.setTranType(4);
+                _snbTran.setTranAmount(0); //此数量会操作背包记录
+                _snbTran.setTranAmountPart(_finalStealAmount);
+                _snbTran.setTranPrice(0);
+                _snbTran.setTranDescribe("偷取用户果实消耗的snb");
+                _snbTran.setIsAdd(0);//减少
+                _snbTran.setAfterSnb(comUsersVo.getSnb());
+                _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
+                comSnbTranService.save(_snbTran);
+
+            } else {
+                //被狗咬掉双倍体力
+                if (_wasTheDogBitten) {
+                    _addStrength = comSettingVo.getSnbUnitStrength();
+                }
+            }
+
+            playersAttribute.setStrength(playersAttribute.getStrength() + _addStrength);
+            comPlayersAttriService.save(playersAttribute);
+            ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
+            //前端的显示,输出一个不小于0的体力值
+            Integer _outEnd = _maxStrength - Math.abs(playersAttribute.getStrength());
+            comPlayersAttriSimpleVo.setCurrentStrength(_outEnd < 0 ? 0 : _outEnd);
+            //最大值是配置的值和链上数据的值相加
+            comPlayersAttriSimpleVo.setMaxStrength(_maxStrength);
+
+            map.put("playerAttribute", comPlayersAttriSimpleVo);
+
+            //输出对应的判定值
+            map.put("dogWork", _dogWork);
+            map.put("wasTheDogBitten", _wasTheDogBitten);
+            map.put("holdTheStick", _holdTheStick);
+            map.put("hasReduceSnb", _hasReduceSnb);
+            //如果被狗咬后扣除的snb,和对应扣除的体力
+            map.put("deductSnb", comSettingVo.getDeductSnb());
+            map.put("deductStrength", _addStrength);
+
+            //用户snb
+            map.put("snb", comUsersVo.getSnb());
+            map.put("snbPart", comUsersVo.getSnbPart());
+
+            //解除snb锁
+            redisLock.unlock(_redisSNBKey, String.valueOf(time));
+            return Result.of(map);
+        } catch (Exception e) {
+            // 需要redis 解锁
+            redisLock.unlock(_redisKey, String.valueOf(time));
+            redisLock.unlock(_redisSNBKey, String.valueOf(time));
+            throw new RuntimeException(e.getMessage());
+        }
+
+    }
+
 
     /**
      * 处理一键收取水果果实时候,传入对方用户id 即可
@@ -381,12 +759,14 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
         }
         //todo 后台可配置,获取一个链上数据
-        Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = 0;
+        Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = DappUtil.getChildrenCount(userId);
+        //前端的显示,输出一个不小于0的体力值
+        Integer _maxStrength = _configStrength + _chainStrength;
         //1.先判断用户是否有足够的体力,根据snb判断。2. 收取到果实,扣除用户一个体力值
         ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
         ComPlayersAttriVo playersAttribute = comPlayersAttriService.findByUserId(userId);
-        Integer _out = _configStrength - Math.abs(playersAttribute.getStrength());
-        if (comUsersVo.getSnb() < comSettingVo.getLeastSnb()) {
+        Integer _out = _maxStrength - Math.abs(playersAttribute.getStrength());
+        if (comUsersVo.getSnb() < comSettingVo.getDeductSnb()) {
             //判断是否有双倍体力
             if (_out < comSettingVo.getSnbUnitStrength()) {
                 map.put("msg", "需要双倍体力:" + comSettingVo.getSnbUnitStrength());
@@ -402,8 +782,15 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
 
         List<Map> _stealLandInfos = new ArrayList<>();
         Double _finalStealAmountSum = 0d;
-        //偷取用户的id
-        List<ComPlayerLand> otherPlayerLands = comPlayerLandService.findAllByCanStealOtherLands(userId, otherUserId);
+        //todo 偷取用户的对象信息等id
+        List<ComPlayerLandAndCanSteal> otherPlayerLandAndCanSteal = comPlayerLandService.findCanStealByUserIdAndOtherUserId(userId, otherUserId);
+        //List<ComPlayerLand> otherPlayerLands = comPlayerLandService.findAllByCanStealOtherLands(userId, otherUserId);
+        List<ComPlayerLand> otherPlayerLands = new ArrayList<>();
+        for (int i = 0; i < otherPlayerLandAndCanSteal.size(); i++) {
+            if (otherPlayerLandAndCanSteal.get(i).getCanSteal().equals(1)) {
+                otherPlayerLands.add(CopyUtil.copy(otherPlayerLandAndCanSteal.get(i), ComPlayerLand.class));
+            }
+        }
         if (otherPlayerLands.size() == 0) {
             return Result.of(null, false, ResultEnum.LAND_CAN_STEAL_IS_ZERO.getMessage(), ResultEnum.LAND_CAN_STEAL_IS_ZERO.getCode());
         }
@@ -413,7 +800,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             //获取当前种植的种子
             ComMallSeedVo comMallSeedVo = comMallSeedService.findById(otherPlayerLand.getPlantId());
             //需要redis 加锁
-            long time = System.currentTimeMillis() + TIMEOUT;
+            long time = System.currentTimeMillis() + RedisData.getPlayerGoodsTimeout();
             //获取用户的plantFlag,因为之前的用户没有设置这个flag,所以设为第一次,用 userId 和 landId 组合成key
             String _redisKey = otherPlayerLand.getPlantFlag();
             if (!StringUtils.hasText(_redisKey)) {
@@ -443,15 +830,24 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 //todo 被偷取的人扣除 一个损失量,初利润算 _profit
                 Double _stolenAmount = DoubleUtil.mul(_profit.doubleValue(), _stealRatio);
                 //这里根据plantFlag判断目标用户当前种植被偷取完,看下是否需要处理更新前端信息,暂不处理
-                Double _sumStolen = comPlayerProfitService.getStolenSumByPlantFlag(otherPlayerLand.getPlantFlag());
+                Double _sumStolen = comPlayerProfitService.getStolenSumByOtherUserIdAndPlantFlag(otherUserId, _redisKey);
                 //todo 这里的可偷利润应该是最大值,用户不能超过这个,需要限制判断
                 Double _maxAmount = DoubleUtil.mul(_profit.doubleValue(), profitConfig); //可偷取的利润
-                //1 就是 _sumStolen>_maxAmount
-                if (DoubleUtil.compare(_sumStolen, _maxAmount).equals(1)) {
+                //1 一键 就是 _sumStolen>_maxAmount 或者 _sumStolen == _maxAmount ,被偷完了
+                if (!DoubleUtil.compare(_sumStolen, _maxAmount).equals(-1)) {
                     // 需要redis 解锁
                     redisLock.unlock(_redisKey, String.valueOf(time));
+                    //记录一个不可偷取的状态
+                    otherPlayerLand.setPlantSteal(0);
+                    comPlayerLandService.save(CopyUtil.copy(otherPlayerLand, ComPlayerLandVo.class));
                     continue;
                 }
+                //计算剩下可偷利润的差,防止过多偷取用户利润 _stolenAmount
+                Double _diff = Math.abs(DoubleUtil.sub(_maxAmount, _sumStolen));
+                if (DoubleUtil.compare(_stolenAmount, _diff).equals(1)) {
+                    //_stolenAmount>_diff
+                    _stolenAmount = _diff;
+                }
                 //最终偷窃人获取的是偷取的是目标用户损失量的10% finallyGetRatioConfig
                 Double _finalStealAmount = DoubleUtil.mul(_stolenAmount, finallyGetRatioConfig);
                 //偷窃后,系统回收部分
@@ -485,7 +881,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 ComPlayerProfit comPlayerProfit = new ComPlayerProfit();
                 comPlayerProfit.setUserId(userId);
                 comPlayerProfit.setTargetId(otherUserId);
-                comPlayerProfit.setPlantFlag(otherPlayerLand.getPlantFlag());
+                comPlayerProfit.setPlantFlag(_redisKey);
                 comPlayerProfit.setLandId(otherPlayerLand.getConfigLandId());
                 comPlayerProfit.setLeaseMultiple(otherPlayerLand.getLeaseMultiple());
                 comPlayerProfit.setLeaseDate(otherPlayerLand.getLeaseDate());
@@ -508,13 +904,14 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 _playerLog.setTId(comMallSeedVo.getHarvestId());
                 _playerLog.setTName(comMallSeedVo.getHarvestName());
                 _playerLog.setTType(6);//偷取果实时候,type设置6
+                //偷水果时候这部分数据应该是不变的
                 _playerLog.setTAmount(0);
                 _playerLog.setBeforeAmount(comPlayerGoods.getAmount());
                 _playerLog.setAfterAmount(comPlayerGoods.getAmount());
-                //收取时候信息记录
+                //偷取用户果实时候,收取时候信息记录
+                _playerLog.setBeforePart(_beforeStealAmount);
                 _playerLog.setTPart(_finalStealAmount);
                 _playerLog.setTLoss(_lostStealAmount); //损失的部分
-                _playerLog.setBeforePart(_beforeStealAmount);
                 _playerLog.setAfterPart(comPlayerGoods.getAmountPart());
                 _playerLog.setLMultiple(otherPlayerLand.getLeaseMultiple());
                 ComPlayerLogVo _playerLogVo = CopyUtil.copy(_playerLog, ComPlayerLogVo.class);
@@ -526,6 +923,16 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 _landMap.put("landId", otherPlayerLand.getConfigLandId());
                 //
                 _landMap.put("stealAmount", _finalStealAmount);
+
+                //固定成本
+                _landMap.put("cost", otherPlayerLand.getLeaseMultiple() * comMallSeedVo.getPriceSnb());
+                //当前利润
+                _landMap.put("profit", _profit);
+                //打印一个比例
+                _landMap.put("profitRatio", profitConfig);
+                _landMap.put("intervalStealRatio", _stealRatio);
+                _landMap.put("finallyGetRatioConfig", finallyGetRatioConfig);
+
                 _finalStealAmountSum = DoubleUtil.add(_finalStealAmount, _finalStealAmountSum);
                 _stealLandInfos.add(_landMap);
                 // 需要redis 解锁
@@ -543,15 +950,15 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
 
         if (_stealLandInfos.size() > 0) {
             //todo 体力值可以后台配置
-            Integer _addStrength = comUsersVo.getSnb() < comSettingVo.getLeastSnb() ? comSettingVo.getSnbUnitStrength() : comSettingVo.getUnitStrength();
+            Integer _addStrength = comUsersVo.getSnb() < comSettingVo.getDeductSnb() ? comSettingVo.getSnbUnitStrength() : comSettingVo.getUnitStrength();
             playersAttribute.setStrength(playersAttribute.getStrength() + _addStrength);
             comPlayersAttriService.save(playersAttribute);
             ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
             //前端的显示,输出一个不小于0的体力值
-            Integer _outEnd = _configStrength - Math.abs(playersAttribute.getStrength());
+            Integer _outEnd = _maxStrength - Math.abs(playersAttribute.getStrength());
             comPlayersAttriSimpleVo.setCurrentStrength(_outEnd < 0 ? 0 : _outEnd);
             //最大值是配置的值和链上数据的值相加
-            comPlayersAttriSimpleVo.setMaxStrength(_configStrength + _chainStrength);
+            comPlayersAttriSimpleVo.setMaxStrength(_maxStrength);
 
             map.put("playerAttribute", comPlayersAttriSimpleVo);
         }
@@ -602,7 +1009,16 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
         if (amount.equals(0)) {
             return Result.of(null, false, ResultEnum.FRUIT_AMOUNT_IS_ZERO_AND_NOT_MULTIPLE.getMessage(), ResultEnum.FRUIT_AMOUNT_IS_ZERO_AND_NOT_MULTIPLE.getCode());
         }
+        //todo snb冻结加锁
+        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
+        String _redisKey = "SNB_SAVE_" + userId;
+
         try {
+            //todo snb冻结加锁
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                return Result.of(null, false, ResultEnum.PLAYER_GOODS_SAVE_LOCK.getMessage(), ResultEnum.PLAYER_GOODS_SAVE_LOCK.getCode());
+            }
+
             Integer _selfBeforeFruitAmount = comPlayerGoodsSimpleVo.getAmount();
             Integer _selfAfterFruitAmount = 0;
             Double _selfBeforeFruitAmountPart = comPlayerGoodsSimpleVo.getAmountPart();
@@ -662,6 +1078,8 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             int _endAmount = (int) (amount * 1);
             //添加SNB
             ComUsersVo comUsersVo = comUsersService.findByUserId(userId);
+            ComSnbTranVo _snbTran = new ComSnbTranVo();
+            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
             //交易前的snb数据
             Integer _beforeSnb = comUsersVo.getSnb();
             //数量乘以售价
@@ -670,16 +1088,18 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             Integer _currentSnb = comUsersVo.getSnb() + _saleSnb;
             comUsersVo.setSnb(_currentSnb);
             comUsersService.save(comUsersVo);
+
             /**
              * todo 果实出售snb数据记录
              */
-            ComSnbTranVo _snbTran = new ComSnbTranVo();
+
             //记录果实id
             _snbTran.setTranId(comFruitVo.getId().toString());
             _snbTran.setUserId(userId);
             _snbTran.setTranName(comFruitVo.getName());
             _snbTran.setTranType(0);
             _snbTran.setTranAmount(amount); //此数量会操作背包记录
+            _snbTran.setTranAmountPart(0d);
             _snbTran.setTranPrice(comFruitVo.getPriceSnb());
             //"出售果实价格:" + comFruitVo.getPriceSnb() + ",数量:" + amount
             _snbTran.setTranDescribe("手续费系数:1,最终果实数量为:" + _endAmount + ",销售价格:" + _saleSnb);
@@ -687,6 +1107,10 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             _snbTran.setBeforeSnb(_beforeSnb);
             _snbTran.setTranSnb(_saleSnb);
             _snbTran.setAfterSnb(_currentSnb);
+
+            _snbTran.setTranSnbPart(0d);
+            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
+
             comSnbTranService.save(_snbTran);
 
             /**
@@ -710,7 +1134,11 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
             _saleFruitPlayerLog.setLMultiple(0);//收获时候,会有一个倍数
             ComPlayerLogVo _saleFruitPlayerLogVo = CopyUtil.copy(_saleFruitPlayerLog, ComPlayerLogVo.class);
             comPlayerLogService.save(_saleFruitPlayerLogVo);
+
+
+            redisLock.unlock(_redisKey, String.valueOf(time));
         } catch (Exception e) {
+            redisLock.unlock(_redisKey, String.valueOf(time));
             throw new RuntimeException(e.getMessage());
         }
 
@@ -848,6 +1276,7 @@ public class ComPlayerGoodsController extends CommonController<ComPlayerGoodsVo,
                 //用种子的picture
                 _targetGoods.setPictureName(comFruitVo.getPicture());
                 _targetGoods.setAmount(amount);
+                _targetGoods.setAmountPart(0d);
                 _targetAfterAmount = _targetGoods.getAmount();
             } else {
                 _targetBeforeAmount = _targetGoods.getAmount();

+ 11 - 8
src/main/java/com/td/boss/game/complayerland/controller/ComPlayerLandController.java

@@ -152,14 +152,11 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
      * @return 返回的是已经过滤租赁过期但未删除的的列表
      */
     @GetMapping("getCanStealDetailList")
-    public Result<List<ComPlayerLandAndPlantVo>> getCanStealListFunction(@RequestParam(value = "userId") String userId,
-                                                                 @RequestParam(value = "otherUserId", required = false) String otherUserId) {
-        String _currentUserId = userId;
-        //todo 新增获取其他用户信息
-        if (StringUtils.hasText(otherUserId)) {
-            _currentUserId = otherUserId;
-        }
-        List<ComPlayerLandAndCanSteal> comPlayerLands = comPlayerLandService.findCanStealByUserId(_currentUserId);
+    public Result<List<ComPlayerLandAndPlantVo>> getCanStealListFunction(
+                                                                 @RequestParam(value = "userId") String userId,
+                                                                 @RequestParam(value = "otherUserId") String otherUserId) {
+
+        List<ComPlayerLandAndCanSteal> comPlayerLands = comPlayerLandService.findCanStealByUserIdAndOtherUserId(userId,otherUserId);
         List<ComPlayerLandAndPlantVo> _simpleVoList = CopyUtil.copyList(comPlayerLands, ComPlayerLandAndPlantVo.class);
         List<ComPlayerLandAndPlantVo> _list = new ArrayList<>();
         try {
@@ -370,6 +367,12 @@ public class ComPlayerLandController extends CommonController<ComPlayerLandVo, C
             _afterAmount = _afterAmount < 0 ? 0 : _afterAmount;
             _playerLogVo.setAfterAmount(_afterAmount);
             _playerLogVo.setLMultiple(comPlayerLand.getLeaseMultiple());
+
+            //收取时候信息记录
+            _playerLogVo.setTPart(0d);
+            _playerLogVo.setTLoss(0d); //损失的部分
+            _playerLogVo.setBeforePart(0d);
+            _playerLogVo.setAfterPart(0d);
             comPlayerLogService.save(_playerLogVo);
 
             ComPlayerLandAndPlantVo comPlayerLandAndPlantVo = CopyUtil.copy(comPlayerLand, ComPlayerLandAndPlantVo.class);

+ 2 - 0
src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLand.java

@@ -38,6 +38,8 @@ public class ComPlayerLand implements Serializable {
 
     private String plantFlag;//每次种植生成一个唯一标识
 
+    private Integer plantSteal;//是否可以偷取,默认 成熟后可以被其他用户收取1
+
     private String landDescribe;//土地描述
 
     private Double rentalExpenses;

+ 3 - 1
src/main/java/com/td/boss/game/complayerland/pojo/ComPlayerLandAndCanSteal.java

@@ -42,6 +42,8 @@ public class ComPlayerLandAndCanSteal implements Serializable {
 
     private String plantFlag;//每次种植生成一个唯一标识
 
+    private Integer plantSteal;//是否可以偷取,默认 成熟后可以被其他用户收取1
+
     private String landDescribe;//土地描述
 
     private Double rentalExpenses;
@@ -50,5 +52,5 @@ public class ComPlayerLandAndCanSteal implements Serializable {
 
     private Date updateTime;
 
-    private Integer canSteal;
+    private Integer canSteal; //这个是当前用户的偷取状态
 }

+ 4 - 4
src/main/java/com/td/boss/game/complayerland/repository/ComPlayerLandRepository.java

@@ -23,13 +23,13 @@ public interface ComPlayerLandRepository extends CommonRepository<ComPlayerLand,
             "a.plant_mature,\n" +
             "DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) AS mature_date,\n" +
             "b.address,\n" +
-            "(CASE WHEN c.id IS NULL THEN 1 ELSE c.id END) AS can_steal\n" +
+            "(CASE WHEN c.id IS NULL AND a.plant_steal = 1  THEN 1 ELSE 0 END) AS can_steal\n" +
             "FROM\n" +
             "com_player_land AS a \n" +
             "LEFT JOIN com_users AS b ON a.user_id = b.user_id\n" +
-            "LEFT JOIN com_player_profit AS c ON c.user_id = :userId  AND a.config_land_id = c.land_id AND (ISNULL(c.plant_flag) = 1 OR a.plant_flag = c.plant_flag) \n" +
-            "WHERE NOT(a.user_id = :userId) AND is_lease = 1 AND is_plant = 1 AND DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) <= NOW()\n" +
-            "AND DATE(a.lease_time) > DATE(NOW()) GROUP BY a.user_id , can_steal HAVING can_steal = 1", nativeQuery = true)
+            "LEFT JOIN com_player_profit AS c ON c.user_id = :userId AND c.target_id = a.user_id AND a.config_land_id = c.land_id AND (  ( ISNULL(a.plant_flag) = 1 AND c.plant_flag = CONCAT(a.user_id,'or',a.config_land_id)) OR a.plant_flag = c.plant_flag )\n" +
+            "WHERE NOT(a.user_id = :userId) AND is_lease = 1 AND is_plant = 1 AND a.plant_steal = 1 AND DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) <= NOW()\n" +
+            "AND DATE(a.lease_time) > DATE(NOW()) GROUP BY a.user_id,can_steal HAVING can_steal = 1  ", nativeQuery = true)
     List<Object> findAllIsStealComPlayerLandAndUserInfo(String userId,Pageable pageable);
 
 

+ 1 - 1
src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandService.java

@@ -18,7 +18,7 @@ public interface ComPlayerLandService extends CommonService<ComPlayerLandVo, Com
     List<ComPlayerLandAndUserInfoVo> findAllByCanStealNotSelf(String userId, Pageable pageable);
 
     //根据userId 获取可偷取的参数
-    List<ComPlayerLandAndCanSteal> findCanStealByUserId(String userId);
+    List<ComPlayerLandAndCanSteal> findCanStealByUserIdAndOtherUserId(String userId,String otherUserId);
 
     List<ComPlayerLandAndUserInfoVo> findAllByCanStealAndOtherUser(String userId);
 

+ 7 - 7
src/main/java/com/td/boss/game/complayerland/service/ComPlayerLandServiceImpl.java

@@ -42,8 +42,8 @@ public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo,
 
 
     @Override
-    public List<ComPlayerLandAndUserInfoVo> findAllByCanStealNotSelf(String userId,Pageable pageable) {
-        List<Object> objects = comPlayerLandRepository.findAllIsStealComPlayerLandAndUserInfo(userId,pageable);
+    public List<ComPlayerLandAndUserInfoVo> findAllByCanStealNotSelf(String userId, Pageable pageable) {
+        List<Object> objects = comPlayerLandRepository.findAllIsStealComPlayerLandAndUserInfo(userId, pageable);
         List<ComPlayerLandAndUserInfoVo> landAndUserInfoVos = new ArrayList<>();
         for (int i = 0; i < objects.size(); i++) {
             Object[] tempObj = (Object[]) objects.get(i);
@@ -53,14 +53,14 @@ public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo,
     }
 
     @Override
-    public List<ComPlayerLandAndCanSteal> findCanStealByUserId(String userId) {
+    public List<ComPlayerLandAndCanSteal> findCanStealByUserIdAndOtherUserId(String userId, String otherUserId) {
         String sql = "SELECT\n" +
                 "a.*,\n" +
                 "(CASE WHEN c.id IS NULL THEN 1 ELSE 0 END ) AS can_steal\n" +
                 "FROM\n" +
                 "com_player_land AS a \n" +
-                "LEFT JOIN com_player_profit AS c ON a.user_id = c.target_id  AND a.config_land_id = c.land_id AND (ISNULL(c.plant_flag) = 1 OR a.plant_flag = c.plant_flag)\n" +
-                "WHERE a.user_id = "+userId+" AND is_lease = 1 AND is_plant = 1 AND DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) <= NOW()\n" +
+                "LEFT JOIN com_player_profit AS c ON a.user_id = c.target_id AND c.user_id = " + userId + " AND a.config_land_id = c.land_id AND (( ISNULL(a.plant_flag) = 1 AND c.plant_flag = CONCAT(a.user_id,'or',a.config_land_id)) OR a.plant_flag = c.plant_flag )\n" +
+                "WHERE a.user_id = " + otherUserId + " AND is_lease = 1 AND is_plant = 1 AND DATE_ADD(a.plant_start,INTERVAL a.plant_mature DAY) <= NOW()\n" +
                 "AND a.lease_time > NOW()";
         Query nativeQuery = em.createNativeQuery(sql, ComPlayerLandAndCanSteal.class);
         List list = nativeQuery.getResultList();
@@ -73,7 +73,7 @@ public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo,
     }
 
     @Override
-    public List<ComPlayerLand> findAllByCanStealOtherLands(String userId,String otherUserId) {
+    public List<ComPlayerLand> findAllByCanStealOtherLands(String userId, String otherUserId) {
         //查找目标
         List<ComPlayerLand> comPlayerLandList = comPlayerLandRepository.findAllByUserIdAndIsLeaseAndIsPlant(otherUserId, 1, 1).stream()
                 .filter(
@@ -83,7 +83,7 @@ public class ComPlayerLandServiceImpl extends CommonServiceImpl<ComPlayerLandVo,
                                 DateUtil.getOldDateAddDay(e.getPlantStart(), e.getPlantMature()).getTime() <= DateUtil.getNowDate().getTime()
                                         &&
                                         //判断是否偷取过目标的土地
-                                        comPlayerProfitService.findByUserIdAndTargetIdAndLandIdAndPlantFlag(userId,e.getUserId(), e.getConfigLandId(), e.getPlantFlag()) == null
+                                        comPlayerProfitService.findByUserIdAndTargetIdAndLandIdAndPlantFlag(userId, e.getUserId(), e.getConfigLandId(), e.getPlantFlag()) == null
 
                 )
                 .collect(Collectors.toList());

+ 5 - 1
src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandAndPlantVo.java

@@ -47,6 +47,10 @@ public class ComPlayerLandAndPlantVo implements Serializable {
 
     private Integer plantMature;//成熟期
 
+    private String plantFlag;//每次种植生成一个唯一标识
+
+    private Integer plantSteal;//是否可以偷取,默认 成熟后可以被其他用户收取1
+
     private String landDescribe;//土地描述
 
     private Double rentalExpenses;
@@ -55,5 +59,5 @@ public class ComPlayerLandAndPlantVo implements Serializable {
 
     private Date updateTime;
 
-    private Integer canSteal;
+    private Integer canSteal; //这个是当前用户的偷取状态
 }

+ 4 - 0
src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandSimpleVo.java

@@ -46,6 +46,10 @@ public class ComPlayerLandSimpleVo implements Serializable {
 
     private Integer plantMature;//成熟期
 
+    private String plantFlag;//每次种植生成一个唯一标识
+
+    private Integer plantSteal;//是否可以偷取,默认 成熟后可以被其他用户收取1
+
     private String landDescribe;//土地描述
 
     private Double rentalExpenses;

+ 2 - 0
src/main/java/com/td/boss/game/complayerland/vo/ComPlayerLandVo.java

@@ -35,6 +35,8 @@ public class ComPlayerLandVo extends PageCondition implements Serializable {
 
     private String plantFlag;//每次种植生成一个唯一标识
 
+    private Integer plantSteal;//是否可以偷取,默认 成熟后可以被其他用户收取1
+
     private String landDescribe;//土地描述
 
     private Double rentalExpenses;

+ 2 - 1
src/main/java/com/td/boss/game/complayerlog/vo/ComPlayerLogVo.java

@@ -27,8 +27,9 @@ public class ComPlayerLogVo extends PageCondition implements Serializable {
     @JsonProperty
     private Integer lMultiple;//如果是操作土地相关,land 数据,记录一下倍数
 
+    @JsonProperty
     private Double tPart;//收取数量
-
+    @JsonProperty
     private Double tLoss;//损失的果实部分
 
     private Double beforePart;//收取交易前的数量

+ 4 - 2
src/main/java/com/td/boss/game/complayerprofit/repository/ComPlayerProfitRepository.java

@@ -22,8 +22,10 @@ public interface ComPlayerProfitRepository extends CommonRepository<ComPlayerPro
 
     Optional<ComPlayerProfit> findByUserIdAndPlantFlag(String userId, String plantFlag);
 
+    Optional<ComPlayerProfit> findByUserIdAndTargetIdAndPlantFlag(String userId,String otherUserId, String plantFlag);
+
     Optional<ComPlayerProfit> findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId, String targetId, Integer landId, String plantFlag);
 
-    @Query(value = "SELECT IFNULL(sum(u.stolen), 0.0) AS sum FROM  com_player_profit u  where u.plant_flag = :plantFlag", nativeQuery = true)
-    Double getStolenSumByPlantFlag(String plantFlag);
+    @Query(value = "SELECT IFNULL(sum(u.stolen), 0.0) AS sum FROM  com_player_profit u  where u.target_id=:targetId and u.plant_flag = :plantFlag", nativeQuery = true)
+    Double getStolenSumByTargetIdAndPlantFlag(String targetId,String plantFlag);
 }

+ 3 - 1
src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitService.java

@@ -20,7 +20,9 @@ public interface ComPlayerProfitService extends CommonService<ComPlayerProfitVo,
 
     ComPlayerProfit findByUserIdAndPlantFlag(String userId,String plantFlag);
 
+    ComPlayerProfit findByUserIdAndOtherUserIdAndPlantFlag(String userId,String otherUserId, String plantFlag);
+
     ComPlayerProfit findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId,String targetId,Integer configLandId, String plantFlag);
 
-    Double getStolenSumByPlantFlag(String plantFlag);
+    Double getStolenSumByOtherUserIdAndPlantFlag(String otherUserId, String plantFlag);
 }

+ 7 - 2
src/main/java/com/td/boss/game/complayerprofit/service/ComPlayerProfitServiceImpl.java

@@ -29,6 +29,11 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
     public ComPlayerProfit findByUserIdAndPlantFlag(String userId,String plantFlag) {
         return comPlayerProfitRepository.findByUserIdAndPlantFlag(userId,plantFlag).orElse(null);
     }
+    @Override
+    public ComPlayerProfit findByUserIdAndOtherUserIdAndPlantFlag(String userId,String otherUserId, String plantFlag) {
+        return comPlayerProfitRepository.findByUserIdAndTargetIdAndPlantFlag(userId,otherUserId,plantFlag).orElse(null);
+    }
+
 
     @Override
     public ComPlayerProfit findByUserIdAndTargetIdAndLandIdAndPlantFlag(String userId,String targetId, Integer configLandId, String plantFlag) {
@@ -36,7 +41,7 @@ public class ComPlayerProfitServiceImpl extends CommonServiceImpl<ComPlayerProfi
     }
 
     @Override
-    public Double getStolenSumByPlantFlag(String plantFlag) {
-        return comPlayerProfitRepository.getStolenSumByPlantFlag(plantFlag);
+    public Double getStolenSumByOtherUserIdAndPlantFlag(String otherUserId, String plantFlag) {
+        return comPlayerProfitRepository.getStolenSumByTargetIdAndPlantFlag(otherUserId,plantFlag);
     }
 }

+ 5 - 3
src/main/java/com/td/boss/game/complayersattri/controller/ComPlayersAttriController.java

@@ -10,6 +10,7 @@ import com.td.boss.game.complayersattri.service.ComPlayersAttriService;
 import com.td.boss.game.comsetting.service.ComSettingService;
 import com.td.boss.game.comsetting.vo.ComSettingVo;
 import com.td.boss.util.CopyUtil;
+import com.td.boss.util.DappUtil;
 import com.td.boss.util.DateUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -53,12 +54,13 @@ public class ComPlayersAttriController extends CommonController<ComPlayersAttriV
         }
         ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
         //todo 后台可配置,获取一个链上数据
-        Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = 0;
+        Integer _configStrength = comSettingVo.getMaxStrength() , _chainStrength = DappUtil.getChildrenCount(userId);
         //前端的显示,输出一个不小于0的体力值
-        Integer _out = _configStrength - Math.abs(playersAttribute.getStrength());
+        Integer _maxStrength = _configStrength + _chainStrength;
+        Integer _out = _maxStrength - Math.abs(playersAttribute.getStrength());
         comPlayersAttriSimpleVo.setCurrentStrength(_out < 0 ? 0 : _out);
         //最大值是配置的值和链上数据的值相加
-        comPlayersAttriSimpleVo.setMaxStrength(_configStrength + _chainStrength);
+        comPlayersAttriSimpleVo.setMaxStrength(_maxStrength);
 
         return Result.of(comPlayersAttriSimpleVo);
     }

+ 7 - 1
src/main/java/com/td/boss/game/comsetting/pojo/ComSetting.java

@@ -20,14 +20,20 @@ public class ComSetting implements Serializable {
 
     private Integer snbUnitStrength;//走snb不足时候,用这个单位
 
-    private Integer leastSnb;//最小判断的snb
+    private Double deductSnb;//扣除的snb
 
     private Double profit;//玩家的种植可以被偷的利润比例,默认是0
 
+    private Double profitDog;//存在狗时候可以偷取的数量
+
     private Double stealMaxRatio;//偷取的一个随机范围 比如 0.03 这样
 
     private Double stealMinRatio;//偷取的一个随机范围 比如 0.01 这样
 
+    private Double stealRatioHasStick;//如果有装备棒子偷的利润比例
+
+    private Double stealRatioNoStick;//没有装备打狗棒时候利润比例
+
     private Double finalRatio;//最后被偷取的比例,比如被偷取用户损失了10个,最后偷取的用户获得这10个乘这个比例
 
     private Date createTime;//

+ 7 - 1
src/main/java/com/td/boss/game/comsetting/vo/ComSettingSimpleVo.java

@@ -17,14 +17,20 @@ public class ComSettingSimpleVo  implements Serializable {
 
     private Integer snbUnitStrength;//走snb不足时候,用这个单位
 
-    private Integer leastSnb;//最小判断的snb
+    private Double deductSnb;//扣除的snb
 
     private Double profit;//玩家的种植可以被偷的利润比例,默认是0
 
+    private Double profitDog;//存在狗时候可以偷取的数量
+
     private Double stealMaxRatio;//偷取的一个随机范围 比如 0.03 这样
 
     private Double stealMinRatio;//偷取的一个随机范围 比如 0.01 这样
 
+    private Double stealRatioHasStick;//如果有装备棒子偷的利润比例
+
+    private Double stealRatioNoStick;//没有装备打狗棒时候利润比例
+
     private Double finalRatio;//最后被偷取的比例,比如被偷取用户损失了10个,最后偷取的用户获得这10个乘这个比例
 
     private Date createTime;//

+ 7 - 1
src/main/java/com/td/boss/game/comsetting/vo/ComSettingVo.java

@@ -16,14 +16,20 @@ public class ComSettingVo extends PageCondition implements Serializable {
 
     private Integer snbUnitStrength;//走snb不足时候,用这个单位
 
-    private Integer leastSnb;//最小判断的snb
+    private Double deductSnb;//扣除的snb
 
     private Double profit;//玩家的种植可以被偷的利润比例,默认是0
 
+    private Double profitDog;//存在狗时候可以偷取的数量
+
     private Double stealMaxRatio;//偷取的一个随机范围 比如 0.03 这样
 
     private Double stealMinRatio;//偷取的一个随机范围 比如 0.01 这样
 
+    private Double stealRatioHasStick;//如果有装备棒子偷的利润比例
+
+    private Double stealRatioNoStick;//没有装备打狗棒时候利润比例
+
     private Double finalRatio;//最后被偷取的比例,比如被偷取用户损失了10个,最后偷取的用户获得这10个乘这个比例
 
     private Date createTime;//

+ 54 - 2
src/main/java/com/td/boss/game/comsnbfreeze/controller/ComSnbFreezeController.java

@@ -29,6 +29,8 @@ import com.td.boss.game.comusers.service.ComUsersService;
 import com.td.boss.game.comusers.vo.ComUsersVo;
 import com.td.boss.util.CopyUtil;
 import com.td.boss.util.DateUtil;
+import com.td.boss.util.RedisData;
+import com.td.boss.util.RedisLock;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.transaction.annotation.Transactional;
@@ -67,6 +69,11 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
     @Autowired
     private ComSnbTranService comSnbTranService;
 
+
+    @Autowired
+    private RedisLock redisLock;
+
+
     /**
      * 获取用户神农呗 snb,前端用户调用
      *
@@ -122,7 +129,23 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
         Integer _beforeSnb = comUsersVo.getSnb();
         Integer _snb = comUsersVo.getSnb() - snbAmount;
         comUsersVo.setSnb(_snb);
-        comUsersService.save(comUsersVo);
+        //todo snb冻结加锁
+        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
+        String _redisKey = "SNB_SAVE_" + comUsersVo.getUserId();
+        try {
+            // 防止重复操作
+            if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                map.put("msg", "冻结操作:SNB保存失败,请重试此操作!");
+                return Result.of(map);
+            }
+            comUsersService.save(comUsersVo);
+            redisLock.unlock(_redisKey, String.valueOf(time));
+        }catch (Exception e){
+            redisLock.unlock(_redisKey, String.valueOf(time));
+            map.put("msg", "保存账户数据失败!");
+            return Result.of(map);
+        }
+
         //记录操作的snb,
         ComSnbFreezeVo entityVo = new ComSnbFreezeVo();
         entityVo.setUserId(id.toString());
@@ -151,6 +174,12 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
         _snbTran.setBeforeSnb(_beforeSnb);
         _snbTran.setTranSnb(snbAmount);
         _snbTran.setAfterSnb(_snb);
+
+        _snbTran.setTranAmountPart(0d);
+        _snbTran.setTranSnbPart(0d);
+        _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
+        _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
+
         comSnbTranService.save(_snbTran);
 
         return Result.of(map);
@@ -204,7 +233,23 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
             Integer _beforeSnb = comUsersVo.getSnb();
             Integer _snb = comUsersVo.getSnb() + comSnbFreezeVo.getSnb();
             comUsersVo.setSnb(_snb);
-            comUsersService.save(comUsersVo);
+            //todo snb冻结加锁
+            long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
+            String _redisKey = "SNB_SAVE_" + comUsersVo.getUserId();
+            try {
+                // 防止重复操作
+                if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                    map.put("msg", "冻结操作:SNB保存失败,请重试此操作!");
+                    return Result.of(map);
+                }
+                comUsersService.save(comUsersVo);
+                redisLock.unlock(_redisKey, String.valueOf(time));
+            }catch (Exception e){
+                redisLock.unlock(_redisKey, String.valueOf(time));
+                map.put("msg", "保存账户数据失败!");
+                return Result.of(map);
+            }
+
             map.put("SNB", comUsersVo.getSnb());
             //记录交易转态
             comSnbFreezeVo.setIsSuccess(2);
@@ -227,6 +272,11 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
             _snbTran.setBeforeSnb(_beforeSnb);
             _snbTran.setTranSnb(comSnbFreezeVo.getSnb());
             _snbTran.setAfterSnb(_snb);
+
+            _snbTran.setTranAmountPart(0d);
+            _snbTran.setTranSnbPart(0d);
+            _snbTran.setBeforeSnbPart(comUsersVo.getSnbPart());
+            _snbTran.setAfterSnbPart(comUsersVo.getSnbPart());
             comSnbTranService.save(_snbTran);
         }
 
@@ -317,6 +367,7 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
                     //初始化一下未种植参数
                     comPlayerLand.setIsPlant(0);
                     comPlayerLand.setCreateTime(new Date());
+                    comPlayerLand.setPlantSteal(1);
                     isNewPlant = true;
                 }
                 //todo 可能续租
@@ -437,6 +488,7 @@ public class ComSnbFreezeController extends CommonController<ComSnbFreezeVo, Com
                     entityVo.setUserId(id.toString());
                     entityVo.setAmount(_paySeedAmount);
                     entityVo.setName(seedVo.getName());
+                    entityVo.setAmountPart(0d);
                     entityVo.setPictureName(seedVo.getPicture());
                 } else {
                     Integer _amount = entityVo.getAmount() + _paySeedAmount;

+ 8 - 0
src/main/java/com/td/boss/game/comsnbtran/pojo/ComSnbTran.java

@@ -24,6 +24,8 @@ public class ComSnbTran implements Serializable {
 
     private Integer tranAmount;//交易数量,上限10个int长度
 
+    private Double tranAmountPart;//
+
     private Integer tranPrice;//物品的交易价格,单价
 
     private String tranDescribe;//交易描述
@@ -36,6 +38,12 @@ public class ComSnbTran implements Serializable {
 
     private Integer afterSnb;//交易完成后的snb
 
+    private Double beforeSnbPart;//交易之前的snb
+
+    private Double tranSnbPart;//交易的snb
+
+    private Double afterSnbPart;//交易完成后的snb
+
     private Date createTime;//
 
     private Date updateTime;//

+ 8 - 0
src/main/java/com/td/boss/game/comsnbtran/vo/ComSnbTranVo.java

@@ -19,6 +19,8 @@ public class ComSnbTranVo extends PageCondition implements Serializable {
 
     private Integer tranAmount;//交易数量,上限10个int长度
 
+    private Double tranAmountPart;//
+
     private Integer tranPrice;//物品的交易价格,单价
 
     private String tranDescribe;//交易描述
@@ -31,6 +33,12 @@ public class ComSnbTranVo extends PageCondition implements Serializable {
 
     private Integer afterSnb;//交易完成后的snb
 
+    private Double beforeSnbPart;//交易之前的snb
+
+    private Double tranSnbPart;//交易的snb
+
+    private Double afterSnbPart;//交易完成后的snb
+
     private Date createTime;//
 
     private Date updateTime;//

+ 30 - 9
src/main/java/com/td/boss/game/comusers/controller/ComUsersController.java

@@ -63,6 +63,9 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
     @Value(value = "classpath:static/dapp/dapp.js")
     private Resource dappFile;
 
+    @Autowired
+    private RedisLock redisLock;
+
     /**
      * 接口需要token放行
      *
@@ -198,6 +201,10 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
         HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers);
         String response = "";
         Map map = new HashMap();
+
+        String _redisKey = "SNB_SAVE_" + id;
+        //todo snb冻结加锁
+        long time = System.currentTimeMillis() + RedisData.getSnbTimeout();
         try {
             response = restTemplate.postForObject(DAppUrl, files, String.class);
             log.info("response={}", response);
@@ -211,6 +218,7 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
                 comUsersVo.setDiamond(0);
                 comUsersVo.setCnt(0);
                 comUsersVo.setSnb(0);
+                comUsersVo.setSnbPart(0d);
                 comUsersVo.setLimitTran(0);
                 comUsersVo.setLimitLogin(0);
                 comUsersVo.setAddress(address);
@@ -229,7 +237,14 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
                 }
                 //维护一个最后登录时间
                 comUsersVo.setLastLogin(new Date());
+
+                // 防止重复操作
+                if (!redisLock.lock(_redisKey, String.valueOf(time))) {
+                    return Result.of(map, false, ResultEnum.USER_LOGIN_LOCK.getMessage(), ResultEnum.USER_LOGIN_LOCK.getCode());
+                }
                 comUsersService.save(comUsersVo);
+                redisLock.unlock(_redisKey, String.valueOf(time));
+
             }
             //生成token
             final String token = jwtTokenUtil.generateToken(comUsersVo.getUserId());
@@ -249,15 +264,15 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
                 playersAttribute.setCreateTime(DateUtil.getNowDate());
                 playersAttribute.setUpdateTime(DateUtil.getNowDate());
                 comPlayersAttriService.save(playersAttribute);
-            }else{
+            } else {
                 //todo 判断是否过了一天,是的话重置体力值
-                if(playersAttribute.getResetStrength() == null){
+                if (playersAttribute.getResetStrength() == null) {
                     playersAttribute.setStrength(0);
                     playersAttribute.setResetStrength(DateUtil.getNowDate());
                     comPlayersAttriService.save(playersAttribute);
-                }else{
-                    Long  _attributeTime =  DateUtil.getOldDateAddDay(playersAttribute.getResetStrength(),1).getTime()- DateUtil.getNowDate().getTime();
-                    if(_attributeTime<=0){
+                } else {
+                    Long _attributeTime = DateUtil.getOldDateAddDay(playersAttribute.getResetStrength(), 1).getTime() - DateUtil.getNowDate().getTime();
+                    if (_attributeTime <= 0) {
                         playersAttribute.setStrength(0);
                         playersAttribute.setResetStrength(DateUtil.getNowDate());
                         comPlayersAttriService.save(playersAttribute);
@@ -271,22 +286,26 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
                 return Result.of(null, false, ResultEnum.SETTING_IS_NULL.getMessage(), ResultEnum.SETTING_IS_NULL.getCode());
             }
             ComPlayersAttriSimpleVo comPlayersAttriSimpleVo = CopyUtil.copy(playersAttribute, ComPlayersAttriSimpleVo.class);
+
+            //获取一个体力值
             //todo 后台可配置,获取一个链上数据
-            Integer _configStrength = comSettingVo.getMaxStrength() , _chainStrength = 0;
+            Integer _configStrength = comSettingVo.getMaxStrength(), _chainStrength = DappUtil.getChildrenCount(comUsersVo.getUserId());
             //前端的显示,输出一个不小于0的体力值
-            Integer _out = _configStrength - Math.abs(playersAttribute.getStrength());
+            Integer _maxStrength = _configStrength + _chainStrength;
+            Integer _out = _maxStrength - Math.abs(playersAttribute.getStrength());
             comPlayersAttriSimpleVo.setCurrentStrength(_out < 0 ? 0 : _out);
             //最大值是配置的值和链上数据的值相加
-            comPlayersAttriSimpleVo.setMaxStrength(_configStrength + _chainStrength);
+            comPlayersAttriSimpleVo.setMaxStrength(_maxStrength);
 
             //返回前端的体力值是读取一个配置的体力值,
             map.put("playerAttribute", comPlayersAttriSimpleVo);
 
             //返回一个游戏配置
-            map.put("gameSetting",CopyUtil.copy(comSettingVo, ComSettingSimpleVo.class));
+            map.put("gameSetting", CopyUtil.copy(comSettingVo, ComSettingSimpleVo.class));
             map.put("response", JSON.parse(response));
             return Result.of(map);
         } catch (HttpClientErrorException e) {
+            redisLock.unlock(_redisKey, String.valueOf(time));
             log.error(e.toString());
             //返回 402 错误
             response = e.toString();
@@ -315,6 +334,7 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
         map.put("diamond", comUsersVo.getDiamond());
         map.put("CNT", comUsersVo.getCnt());
         map.put("SNB", comUsersVo.getSnb());
+        map.put("snbPart",comUsersVo.getSnbPart());
         map.put("address", comUsersVo.getAddress());
         return Result.of(map);
     }
@@ -333,6 +353,7 @@ public class ComUsersController extends CommonController<ComUsersVo, ComUsers, S
             return Result.of(null, false, ResultEnum.USER_DOES_NOT_EXIST.getMessage(), ResultEnum.USER_DOES_NOT_EXIST.getCode());
         }
         map.put("SNB", comUsersVo.getSnb());
+        map.put("snbPart",comUsersVo.getSnbPart());
         map.put("address", comUsersVo.getAddress());
         return Result.of(map);
     }

+ 2 - 0
src/main/java/com/td/boss/game/comusers/pojo/ComUsers.java

@@ -20,6 +20,8 @@ public class ComUsers implements Serializable {
 
     private Integer snb;//
 
+    private Double snbPart;//神农呗小数部分
+
     private String address;//记录一个用户钱包地址
 
     private Integer limitLogin;//是否限制登录 0:否,1:是

+ 3 - 0
src/main/java/com/td/boss/game/comusers/service/ComUsersService.java

@@ -16,6 +16,9 @@ public interface ComUsersService extends CommonService<ComUsersVo, ComUsers, Str
 
     ComUsersVo findByAddress(String address);
 
+
+    ComUsersVo tranSNBByUserId(Double tranSnb,String userId);
+
     /**
      * 全部注册数量
      * @return

+ 15 - 0
src/main/java/com/td/boss/game/comusers/service/ComUsersServiceImpl.java

@@ -1,10 +1,14 @@
 package com.td.boss.game.comusers.service;
 
+import com.td.boss.common.pojo.Result;
 import com.td.boss.common.service.*;
+import com.td.boss.config.enums.ResultEnum;
+import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import com.td.boss.game.comusers.pojo.ComUsers;
 import com.td.boss.game.comusers.vo.ComUsersVo;
 import com.td.boss.game.comusers.repository.ComUsersRepository;
 import com.td.boss.util.CopyUtil;
+import com.td.boss.util.DoubleUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
@@ -43,6 +47,17 @@ public class ComUsersServiceImpl extends CommonServiceImpl<ComUsersVo, ComUsers,
         }
     }
 
+    /**
+     * 统一交易double snb 操作
+     * @param tranSnb
+     * @param userId
+     * @return
+     */
+    @Override
+    public ComUsersVo tranSNBByUserId(Double tranSnb, String userId) {
+
+        return null;
+    }
 
     @Override
     public Long findAllCount() {

+ 2 - 0
src/main/java/com/td/boss/game/comusers/vo/ComUsersSimpleVo.java

@@ -16,6 +16,8 @@ public class ComUsersSimpleVo implements Serializable {
 
     private Integer snb;//
 
+    private Double snbPart;//神农呗小数部分
+
     private String address;//记录一个用户钱包地址
 
     private Integer limitTran;//是否限制交易 0:否,1:是

+ 2 - 0
src/main/java/com/td/boss/game/comusers/vo/ComUsersVo.java

@@ -16,6 +16,8 @@ public class ComUsersVo extends PageCondition implements Serializable {
 
     private Integer snb;//
 
+    private Double snbPart;//神农呗小数部分
+
     private String address;//记录一个用户钱包地址
 
     private Integer limitLogin;//是否限制登录 0:否,1:是

+ 14 - 0
src/main/java/com/td/boss/sys/sysGame/controller/sysGameUsersController.java

@@ -16,6 +16,8 @@ import com.td.boss.game.complayerland.service.ComPlayerLandService;
 import com.td.boss.game.complayerland.vo.ComPlayerLandVo;
 import com.td.boss.game.complayerlog.service.ComPlayerLogService;
 import com.td.boss.game.complayerlog.vo.ComPlayerLogVo;
+import com.td.boss.game.complayerprofit.service.ComPlayerProfitService;
+import com.td.boss.game.complayerprofit.vo.ComPlayerProfitVo;
 import com.td.boss.game.comsnbtran.service.ComSnbTranService;
 import com.td.boss.game.comsnbtran.vo.ComSnbTranVo;
 import com.td.boss.game.comusers.pojo.ComUsers;
@@ -24,6 +26,7 @@ import com.td.boss.game.comusers.vo.ComUsersVo;
 import com.td.boss.sys.sysuser.vo.SysUserVo;
 import com.td.boss.util.JwtTokenUtil;
 import lombok.extern.slf4j.Slf4j;
+import net.bytebuddy.asm.Advice;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.security.core.userdetails.User;
@@ -51,6 +54,9 @@ public class sysGameUsersController extends CommonController<ComUsersVo, ComUser
     @Autowired
     private ComPlayerLogService comPlayerLogService;
 
+    @Autowired
+    private ComPlayerProfitService comPlayerProfitService;
+
     @Autowired
     private ComPlayerLandService comPlayerLandService;
 
@@ -109,6 +115,14 @@ public class sysGameUsersController extends CommonController<ComUsersVo, ComUser
         return comPlayerLogService.page(comPlayerLogVo);
     }
 
+    @PostMapping("findPlayerProfitPage")
+    @Decrypt
+    @Encrypt
+    public Result<PageInfo<ComPlayerProfitVo>> findPlayerProfitByUserId(ComPlayerProfitVo comPlayerProfitVo){
+        return comPlayerProfitService.page(comPlayerProfitVo);
+    }
+
+
 
 
     @GetMapping("userPlayerGoods")

+ 2 - 2
src/main/java/com/td/boss/util/CodeDOM.java

@@ -532,8 +532,8 @@ public class CodeDOM {
        // String[] tables = {"sys_user","sys_menu","sys_authority","sys_user_menu","sys_user_authority","sys_shortcut_menu","sys_setting"};
        // String[] tables = {"com_player_goods","com_players","com_users","com_rewards"};
        // String[] tables = {"com_wallet","com_cnt_order","com_mall_seed","com_player_goods","com_player_land","com_config_land","com_fruit","com_snb_tran"};
-       // "com_player_log" ,"com_explain_land","com_player_profit","com_players_attri"
-       // String[] tables = {"com_setting"};
+       // "com_player_log" ,"com_explain_land","com_player_profit","com_players_attri","com_setting","com_player_dog","com_mall_other"
+       // String[] tables = {"com_mall_food"};
        // for (String table : tables) {
        //     String msg = new CodeDOM(table).create();
        //     System.out.println(msg);

+ 88 - 0
src/main/java/com/td/boss/util/DappUtil.java

@@ -0,0 +1,88 @@
+package com.td.boss.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.td.boss.common.pojo.IpVo;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import org.springframework.stereotype.Component;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.client.RestTemplate;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+/**
+ * dapp工具类
+ */
+@Slf4j
+@Component
+public class DappUtil {
+
+    private static String env;
+
+    public static String getEnv() {
+        return env;
+    }
+
+    @Value("${spring.profiles.active}")
+    public void setEnv(String env) {
+        DappUtil.env = env;
+    }
+
+    /**
+     * 获取用户直推数量(模块1:偷菜)
+     * {
+     *     "code": 200,
+     *     "msg": "success",
+     *     "data": 0
+     * }
+     */
+    public static Integer getChildrenCount(String userId){
+
+        MultiValueMap<String, Object> form = new LinkedMultiValueMap<>();
+        form.add("id", userId);
+        //验证地址
+        String DAppChildrenCountOnlineUrl = "https://yt.landownership.live/api/game/childrenCount";
+        String DAppChildrenCountTestUrl = "https://wp.landownership.live/api/game/childrenCount";
+        String DAppUrl = DappUtil.getEnv().equals("prod") ? DAppChildrenCountOnlineUrl : DAppChildrenCountTestUrl;
+        log.info("用户直推数量地址:" + DAppUrl);
+        try {
+            RestTemplate restTemplate = new RestTemplate();
+            HttpHeaders headers = new HttpHeaders();
+            //设置content-type
+            MediaType type = MediaType.parseMediaType("multipart/form-data");
+            headers.setContentType(type);
+            // 以表单的方式提交
+            headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
+            //用HttpEntity封装整个请求报文
+
+            HttpEntity<MultiValueMap<String, Object>> files = new HttpEntity<>(form, headers);
+            Map response = restTemplate.postForObject(DAppUrl, files, Map.class);
+            log.info("response={}", response);
+            return (Integer) response.get("data");
+        } catch (Exception e) {
+            log.error(e.getMessage());
+            return 0;
+            //e.printStackTrace();
+        }
+    }
+
+
+
+}

+ 4 - 0
src/main/java/com/td/boss/util/DateUtil.java

@@ -166,4 +166,8 @@ public class DateUtil {
     public static Long getHours(Long millTime){
         return millTime / (60 * 60 * 1000) % 24;
     }
+
+    public static Long getDiffHours(Long millTime){
+        return millTime / (60 * 60 * 1000);
+    }
 }

+ 33 - 0
src/main/java/com/td/boss/util/RedisData.java

@@ -0,0 +1,33 @@
+package com.td.boss.util;
+
+import org.apache.tomcat.util.codec.binary.Base64;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import javax.crypto.Cipher;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.security.SecureRandom;
+import java.util.Random;
+
+/**
+ * redis 参数
+ */
+public class RedisData {
+
+    /**
+     * 1s SNB锁
+     */
+    private static final int SNB_TIMEOUT = 5 * 1000; //5s锁
+
+    public static int getSnbTimeout() {
+        return SNB_TIMEOUT;
+    }
+
+    /**
+     * 10s 背包锁
+     */
+    private static final int PLAYER_GOODS_TIMEOUT = 10 * 1000; //超时时间 10s
+    public static int getPlayerGoodsTimeout() {
+        return PLAYER_GOODS_TIMEOUT;
+    }
+}

+ 2 - 2
src/main/resources/application.yml

@@ -134,9 +134,9 @@ spring:
       connection-test-query: SELECT 1
 
   redis:
-    host: 42.192.165.168
+    host: 127.0.0.1
     port: 6379
-    password: abc123456abc-test
+    password: abc123456abc-redis
   data: #工程中只是把redis作为缓存,并未使用redis作为数据持久化存储源repository使用.
     redis:
       repositories:

+ 1 - 11
src/main/resources/banner.txt

@@ -4,14 +4,4 @@ ${AnsiColor.BRIGHT_YELLOW}
  | |_) |   __ _   ___    ___       /  \      __| |  _ __ ___    _   _ __
  |  _ <   / _` | / __|  / _ \     / /\ \    / _` | | '_ ` _ \  | | | '_ \
  | |_) | | (_| | \__ \ |  __/    / ____ \  | (_| | | | | | | | | | | | | |
- |____/   \__,_| |___/  \___|   /_/    \_\  \__,_| |_| |_| |_| |_| |_| |_|
-
-
-                                                            ____                _                                     _                           _
-                                                           |  _ \              | |                                   (_)                         | |
-                                                           | |_) |  _   _      | |__    _   _    __ _   _ __    ____  _   ______    __ _    ___  | |__
-                                                           |  _ <  | | | |     | '_ \  | | | |  / _` | | '_ \  |_  / | | |______|  / _` |  / __| | '_ \
-                                                           | |_) | | |_| |     | | | | | |_| | | (_| | | | | |  / /  | |          | (_| | | (__  | | | |
-                                                           |____/   \__, |     |_| |_|  \__,_|  \__,_| |_| |_| /___| |_|           \__, |  \___| |_| |_|
-                                                                     __/ |                                                            | |
-                                                                    |___/                                                             |_|
+ |____/   \__,_| |___/  \___|   /_/    \_\  \__,_| |_| |_| |_| |_| |_| |_|

+ 16 - 4
src/main/resources/static/sys/aComUser/js/user.js

@@ -471,15 +471,27 @@ function initPlayerLog(table, data) {
                         return '<span style="color: green">钻石兑换种子</span>';
                     } else if (d.tType == 5) {
                         return '<span style="color: red">出售果实</span>';
-                    } else {
+                    } else if (d.tType == 6) {
+                        return '<span style="color: green">偷取果实</span>';
+                    }
+                    else {
                         return '<span style="color: green">待添加:</span>' + d.tType;
                     }
                 }
             }
             , {field: 'tName', title: '物品名字', width: 120}
-            , {field: 'tAmount', title: '交易数量', width: 150}
-            , {field: 'beforeAmount', title: '交易前数量'}
-            , {field: 'afterAmount', title: '交易后数量'}
+            , {
+                field: 'tAmount', title: '交易数量', width: 150, templet: function (d) {
+                  return (d.tAmount + d.tPart).toFixed(5);
+                }
+            }
+            , {field: 'beforeAmount', title: '交易前数量', templet: function (d) {
+                    return (d.beforeAmount + d.beforePart).toFixed(5);
+                }}
+            , {field: 'afterAmount', title: '交易后数量', templet: function (d) {
+                    return (d.afterAmount + d.afterPart).toFixed(5);
+                }}
+            , {field: 'tLoss', title: '系统扣除部分'}
             , {field: 'lMultiple', title: 'land倍数', width: 80}
             , {field: 'createTime', title: '创建时间'}
             , {field: 'updateTime', title: '更新时间', hide: true}

+ 117 - 3
src/main/resources/static/sys/aComUser/js/userPlayerGoods.js

@@ -2,6 +2,7 @@ let tableIns;
 let tableCNT;
 let tableSNB;
 let tablePlayerLog;
+let tablePlayerProfit;
 let tree;
 layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], function () {
     let table = layui.table;
@@ -44,6 +45,12 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
                 } else {
                     playerLogReload(_findData);
                 }
+
+                if(!tablePlayerProfit){
+                    initPlayerProfit(table, _findData);
+                }else{
+                    playerProfitReload(_findData);
+                }
             }
 
             return {
@@ -72,6 +79,7 @@ layui.use(['element', 'form', 'table', 'layer', 'laydate', 'tree', 'util'], func
             }
             , {field: 'name', title: '物品名称'}
             , {field: 'amount', title: '数量'}
+            , {field: 'amountPart', title: '小数部分数量'}
             , {fixed: 'right', title: '操作', toolbar: '#userPlayerGoodsTableBarDemo'}
         ]]
         , defaultToolbar: ['', 'exports', 'print']
@@ -224,15 +232,29 @@ function initPlayerLog(table, data) {
                         return '<span style="color: green">钻石兑换种子</span>';
                     } else if (d.tType == 5) {
                         return '<span style="color: red">出售果实</span>';
+                    } else if (d.tType == 6) {
+                        return '<span style="color: green">偷取果实</span>';
                     } else {
                         return '<span style="color: green">待添加:</span>' + d.tType;
                     }
                 }
             }
             , {field: 'tName', title: '物品名字', width: 120}
-            , {field: 'tAmount', title: '交易数量', width: 150}
-            , {field: 'beforeAmount', title: '交易前数量'}
-            , {field: 'afterAmount', title: '交易后数量'}
+            // , {field: 'tAmount', title: '交易数量', width: 150}
+            // , {field: 'beforeAmount', title: '交易前数量'}
+            // , {field: 'afterAmount', title: '交易后数量'}
+            , {
+                field: 'tAmount', title: '交易数量', width: 150, templet: function (d) {
+                    return (d.tAmount + d.tPart).toFixed(5);
+                }
+            }
+            , {field: 'beforeAmount', title: '交易前数量', templet: function (d) {
+                    return (d.beforeAmount + d.beforePart).toFixed(5);
+                }}
+            , {field: 'afterAmount', title: '交易后数量', templet: function (d) {
+                    return (d.afterAmount + d.afterPart).toFixed(5);
+                }}
+            , {field: 'tLoss', title: '系统扣除部分'}
             , {field: 'lMultiple', title: 'land倍数', width: 80}
             , {field: 'createTime', title: '创建时间'}
             , {field: 'updateTime', title: '更新时间', hide: true}
@@ -257,4 +279,96 @@ function playerLogReload(data) {
         , done: function (res, curr, count) {
         }
     });
+}
+
+
+
+/**
+ * 用户偷取的操作
+ * @param table
+ * @param data
+ */
+function initPlayerProfit(table, data) {
+    //用户操作PlayerProfit
+    tablePlayerProfit = table.render({
+        elem: '#comPlayerProfitTable'
+        , url: ctx + "/sys/sysComUsers/findPlayerProfitPage"
+        , method: 'POST'
+        //请求前参数处理
+        , request: {
+            pageName: 'page' //页码的参数名称,默认:page
+            , limitName: 'rows' //每页数据量的参数名,默认:limit
+        }
+        , where: data
+        , response: {
+            statusName: 'flag' //规定数据状态的字段名称,默认:code
+            , statusCode: true //规定成功的状态码,默认:0
+            , msgName: 'msg' //规定状态信息的字段名称,默认:msg
+            , countName: 'records' //规定数据总数的字段名称,默认:count
+            , dataName: 'rows' //规定数据列表的字段名称,默认:data
+        }
+        //响应后数据处理
+        , parseData: function (res) { //res 即为原始返回的数据
+            let data = res.data;
+            // console.log("playerLog",res);
+            return {
+                "flag": res.flag, //解析接口状态
+                "msg": res.msg, //解析提示文本
+                "records": data.records, //解析数据长度
+                "rows": data.rows //解析数据列表
+            };
+        }
+        , toolbar: '#comPlayerProfitTableToolbarDemo'
+        , title: '用户仓库操作列表'
+        , cols: [[
+            {field: 'id', title: 'ID', hide: true}
+            , {field: 'userId', title: 'userId', width: 260}
+            , {field: 'targetId', title: '目标id', width: 100}
+            , {field: 'plantFlag', title: '种植标识', width: 120}
+            , {field: 'landId', title: '土地号数', width: 120}
+            , {
+                field: 'leaseDate', title: '租赁类型', width: 100, templet: function (d) {
+                    if (d.leaseDate == 1) {  // 自定义内容
+                        return '<span style="color: green">3个月</span>';
+                    } else if (d.leaseDate == 2) {
+                        return '<span style="color: red">1年</span>';
+                    } else if (d.leaseDate == 3) {
+                        return '<span style="color: red">5年</span>';
+                    } else {
+                        return '<span style="color: green">待添加:</span>' + d.leaseDate;
+                    }
+                }
+            }
+            , {field: 'leaseMultiple', title: '租赁倍数', width: 120}
+            , {field: 'harvest', title: '土地产出量', width: 150}
+            , {field: 'profit', title: '利润总值'}
+            , {field: 'profitAfter', title: '交易后利润'}
+            , {field: 'stolen', title: '目标损失量', width: 150}
+            , {field: 'finalSteal', title: '玩家偷取得到的数量'}
+            , {field: 'profitRatio', title: '收成的比例值'}
+            , {field: 'stealRatio', title: '比例区间1%~3%'}
+            , {field: 'finalRatio', title: '损失比例', width: 80}
+            , {field: 'createTime', title: '创建时间'}
+            , {field: 'updateTime', title: '更新时间', hide: true}
+        ]]
+        , defaultToolbar: ['', 'exports', 'print']
+        , page: true
+        , height: 500
+        , cellMinWidth: 80
+    });
+}
+
+
+function playerProfitReload(data) {
+    tablePlayerProfit.reload({
+        page: {
+            curr: 1 //重新从第 1 页开始
+            , limit: 10
+        }
+        , method: 'POST'
+        , url: ctx + "/sys/sysComUsers/findPlayerProfitPage"
+        , where: data
+        , done: function (res, curr, count) {
+        }
+    });
 }

+ 24 - 0
src/main/resources/view/sys/aComUser/userPlayerGoods.html

@@ -60,6 +60,14 @@
                                    class="layui-input" lay-verify="positiveWholeNumberRequiredTrue">
                         </div>
                     </div>
+
+                    <div class="layui-form-item">
+                        <label class="layui-form-label">物品小数数量</label>
+                        <div class="layui-input-block">
+                            <input type="text" name="amountPart" autocomplete="off" placeholder="物品数量"
+                                   class="layui-input">
+                        </div>
+                    </div>
                     <!-- 隐藏域 -->
                     <input type="text" name="goodsId" hidden="hidden"/>
 
@@ -89,6 +97,22 @@
         </div>
     </div>
 
+    <div class="layui-col-md12">
+        <div class="layui-card">
+            <div class="layui-card-header">用户偷取操作列表</div>
+            <div class="layui-card-body">
+                <!-- 表格主体 -->
+                <table class="layui-hide" id="comPlayerProfitTable" lay-filter="test"></table>
+                <!-- 模板 -->
+                <script type="text/html" id="comPlayerProfitTableToolbarDemo">
+                    <div class="layui-btn-container">
+                        <button class="layui-btn layui-btn-sm" lay-event="playerProfitReload">刷新</button>
+                    </div>
+                </script>
+            </div>
+        </div>
+    </div>
+
 </div>
 </body>
 <!-- js -->